coresight-syscfg.c (31260B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2020 Linaro Limited, All rights reserved. 4 * Author: Mike Leach <mike.leach@linaro.org> 5 */ 6 7#include <linux/platform_device.h> 8#include <linux/slab.h> 9 10#include "coresight-config.h" 11#include "coresight-etm-perf.h" 12#include "coresight-syscfg.h" 13#include "coresight-syscfg-configfs.h" 14 15/* 16 * cscfg_ API manages configurations and features for the entire coresight 17 * infrastructure. 18 * 19 * It allows the loading of configurations and features, and loads these into 20 * coresight devices as appropriate. 21 */ 22 23/* protect the cscsg_data and device */ 24static DEFINE_MUTEX(cscfg_mutex); 25 26/* only one of these */ 27static struct cscfg_manager *cscfg_mgr; 28 29/* load features and configuations into the lists */ 30 31/* get name feature instance from a coresight device list of features */ 32static struct cscfg_feature_csdev * 33cscfg_get_feat_csdev(struct coresight_device *csdev, const char *name) 34{ 35 struct cscfg_feature_csdev *feat_csdev = NULL; 36 37 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) { 38 if (strcmp(feat_csdev->feat_desc->name, name) == 0) 39 return feat_csdev; 40 } 41 return NULL; 42} 43 44/* allocate the device config instance - with max number of used features */ 45static struct cscfg_config_csdev * 46cscfg_alloc_csdev_cfg(struct coresight_device *csdev, int nr_feats) 47{ 48 struct cscfg_config_csdev *config_csdev = NULL; 49 struct device *dev = csdev->dev.parent; 50 51 /* this is being allocated using the devm for the coresight device */ 52 config_csdev = devm_kzalloc(dev, 53 offsetof(struct cscfg_config_csdev, feats_csdev[nr_feats]), 54 GFP_KERNEL); 55 if (!config_csdev) 56 return NULL; 57 58 config_csdev->csdev = csdev; 59 return config_csdev; 60} 61 62/* Load a config into a device if there are any feature matches between config and device */ 63static int cscfg_add_csdev_cfg(struct coresight_device *csdev, 64 struct cscfg_config_desc *config_desc) 65{ 66 struct cscfg_config_csdev *config_csdev = NULL; 67 struct cscfg_feature_csdev *feat_csdev; 68 unsigned long flags; 69 int i; 70 71 /* look at each required feature and see if it matches any feature on the device */ 72 for (i = 0; i < config_desc->nr_feat_refs; i++) { 73 /* look for a matching name */ 74 feat_csdev = cscfg_get_feat_csdev(csdev, config_desc->feat_ref_names[i]); 75 if (feat_csdev) { 76 /* 77 * At least one feature on this device matches the config 78 * add a config instance to the device and a reference to the feature. 79 */ 80 if (!config_csdev) { 81 config_csdev = cscfg_alloc_csdev_cfg(csdev, 82 config_desc->nr_feat_refs); 83 if (!config_csdev) 84 return -ENOMEM; 85 config_csdev->config_desc = config_desc; 86 } 87 config_csdev->feats_csdev[config_csdev->nr_feat++] = feat_csdev; 88 } 89 } 90 /* if matched features, add config to device.*/ 91 if (config_csdev) { 92 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 93 list_add(&config_csdev->node, &csdev->config_csdev_list); 94 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 95 } 96 97 return 0; 98} 99 100/* 101 * Add the config to the set of registered devices - call with mutex locked. 102 * Iterates through devices - any device that matches one or more of the 103 * configuration features will load it, the others will ignore it. 104 */ 105static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *config_desc) 106{ 107 struct cscfg_registered_csdev *csdev_item; 108 int err; 109 110 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 111 err = cscfg_add_csdev_cfg(csdev_item->csdev, config_desc); 112 if (err) 113 return err; 114 } 115 return 0; 116} 117 118/* 119 * Allocate a feature object for load into a csdev. 120 * memory allocated using the csdev->dev object using devm managed allocator. 121 */ 122static struct cscfg_feature_csdev * 123cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc) 124{ 125 struct cscfg_feature_csdev *feat_csdev = NULL; 126 struct device *dev = csdev->dev.parent; 127 int i; 128 129 feat_csdev = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL); 130 if (!feat_csdev) 131 return NULL; 132 133 /* parameters are optional - could be 0 */ 134 feat_csdev->nr_params = feat_desc->nr_params; 135 136 /* 137 * if we need parameters, zero alloc the space here, the load routine in 138 * the csdev device driver will fill out some information according to 139 * feature descriptor. 140 */ 141 if (feat_csdev->nr_params) { 142 feat_csdev->params_csdev = devm_kcalloc(dev, feat_csdev->nr_params, 143 sizeof(struct cscfg_parameter_csdev), 144 GFP_KERNEL); 145 if (!feat_csdev->params_csdev) 146 return NULL; 147 148 /* 149 * fill in the feature reference in the param - other fields 150 * handled by loader in csdev. 151 */ 152 for (i = 0; i < feat_csdev->nr_params; i++) 153 feat_csdev->params_csdev[i].feat_csdev = feat_csdev; 154 } 155 156 /* 157 * Always have registers to program - again the load routine in csdev device 158 * will fill out according to feature descriptor and device requirements. 159 */ 160 feat_csdev->nr_regs = feat_desc->nr_regs; 161 feat_csdev->regs_csdev = devm_kcalloc(dev, feat_csdev->nr_regs, 162 sizeof(struct cscfg_regval_csdev), 163 GFP_KERNEL); 164 if (!feat_csdev->regs_csdev) 165 return NULL; 166 167 /* load the feature default values */ 168 feat_csdev->feat_desc = feat_desc; 169 feat_csdev->csdev = csdev; 170 171 return feat_csdev; 172} 173 174/* load one feature into one coresight device */ 175static int cscfg_load_feat_csdev(struct coresight_device *csdev, 176 struct cscfg_feature_desc *feat_desc, 177 struct cscfg_csdev_feat_ops *ops) 178{ 179 struct cscfg_feature_csdev *feat_csdev; 180 unsigned long flags; 181 int err; 182 183 if (!ops->load_feat) 184 return -EINVAL; 185 186 feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc); 187 if (!feat_csdev) 188 return -ENOMEM; 189 190 /* load the feature into the device */ 191 err = ops->load_feat(csdev, feat_csdev); 192 if (err) 193 return err; 194 195 /* add to internal csdev feature list & initialise using reset call */ 196 cscfg_reset_feat(feat_csdev); 197 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 198 list_add(&feat_csdev->node, &csdev->feature_csdev_list); 199 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 200 201 return 0; 202} 203 204/* 205 * Add feature to any matching devices - call with mutex locked. 206 * Iterates through devices - any device that matches the feature will be 207 * called to load it. 208 */ 209static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc) 210{ 211 struct cscfg_registered_csdev *csdev_item; 212 int err; 213 214 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 215 if (csdev_item->match_flags & feat_desc->match_flags) { 216 err = cscfg_load_feat_csdev(csdev_item->csdev, feat_desc, &csdev_item->ops); 217 if (err) 218 return err; 219 } 220 } 221 return 0; 222} 223 224/* check feature list for a named feature - call with mutex locked. */ 225static bool cscfg_match_list_feat(const char *name) 226{ 227 struct cscfg_feature_desc *feat_desc; 228 229 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) { 230 if (strcmp(feat_desc->name, name) == 0) 231 return true; 232 } 233 return false; 234} 235 236/* check all feat needed for cfg are in the list - call with mutex locked. */ 237static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *config_desc) 238{ 239 int i; 240 241 for (i = 0; i < config_desc->nr_feat_refs; i++) 242 if (!cscfg_match_list_feat(config_desc->feat_ref_names[i])) 243 return -EINVAL; 244 return 0; 245} 246 247/* 248 * load feature - add to feature list. 249 */ 250static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) 251{ 252 int err; 253 struct cscfg_feature_desc *feat_desc_exist; 254 255 /* new feature must have unique name */ 256 list_for_each_entry(feat_desc_exist, &cscfg_mgr->feat_desc_list, item) { 257 if (!strcmp(feat_desc_exist->name, feat_desc->name)) 258 return -EEXIST; 259 } 260 261 /* add feature to any matching registered devices */ 262 err = cscfg_add_feat_to_csdevs(feat_desc); 263 if (err) 264 return err; 265 266 list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list); 267 return 0; 268} 269 270/* 271 * load config into the system - validate used features exist then add to 272 * config list. 273 */ 274static int cscfg_load_config(struct cscfg_config_desc *config_desc) 275{ 276 int err; 277 struct cscfg_config_desc *config_desc_exist; 278 279 /* new configuration must have a unique name */ 280 list_for_each_entry(config_desc_exist, &cscfg_mgr->config_desc_list, item) { 281 if (!strcmp(config_desc_exist->name, config_desc->name)) 282 return -EEXIST; 283 } 284 285 /* validate features are present */ 286 err = cscfg_check_feat_for_cfg(config_desc); 287 if (err) 288 return err; 289 290 /* add config to any matching registered device */ 291 err = cscfg_add_cfg_to_csdevs(config_desc); 292 if (err) 293 return err; 294 295 /* add config to perf fs to allow selection */ 296 err = etm_perf_add_symlink_cscfg(cscfg_device(), config_desc); 297 if (err) 298 return err; 299 300 list_add(&config_desc->item, &cscfg_mgr->config_desc_list); 301 atomic_set(&config_desc->active_cnt, 0); 302 return 0; 303} 304 305/* get a feature descriptor by name */ 306const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name) 307{ 308 const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item; 309 310 mutex_lock(&cscfg_mutex); 311 312 list_for_each_entry(feat_desc_item, &cscfg_mgr->feat_desc_list, item) { 313 if (strcmp(feat_desc_item->name, name) == 0) { 314 feat_desc = feat_desc_item; 315 break; 316 } 317 } 318 319 mutex_unlock(&cscfg_mutex); 320 return feat_desc; 321} 322 323/* called with cscfg_mutex held */ 324static struct cscfg_feature_csdev * 325cscfg_csdev_get_feat_from_desc(struct coresight_device *csdev, 326 struct cscfg_feature_desc *feat_desc) 327{ 328 struct cscfg_feature_csdev *feat_csdev; 329 330 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) { 331 if (feat_csdev->feat_desc == feat_desc) 332 return feat_csdev; 333 } 334 return NULL; 335} 336 337int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc, 338 int param_idx, u64 value) 339{ 340 int err = 0; 341 struct cscfg_feature_csdev *feat_csdev; 342 struct cscfg_registered_csdev *csdev_item; 343 344 mutex_lock(&cscfg_mutex); 345 346 /* check if any config active & return busy */ 347 if (atomic_read(&cscfg_mgr->sys_active_cnt)) { 348 err = -EBUSY; 349 goto unlock_exit; 350 } 351 352 /* set the value */ 353 if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) { 354 err = -EINVAL; 355 goto unlock_exit; 356 } 357 feat_desc->params_desc[param_idx].value = value; 358 359 /* update loaded instances.*/ 360 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 361 feat_csdev = cscfg_csdev_get_feat_from_desc(csdev_item->csdev, feat_desc); 362 if (feat_csdev) 363 feat_csdev->params_csdev[param_idx].current_value = value; 364 } 365 366unlock_exit: 367 mutex_unlock(&cscfg_mutex); 368 return err; 369} 370 371/* 372 * Conditionally up reference count on owner to prevent unload. 373 * 374 * module loaded configs need to be locked in to prevent premature unload. 375 */ 376static int cscfg_owner_get(struct cscfg_load_owner_info *owner_info) 377{ 378 if ((owner_info->type == CSCFG_OWNER_MODULE) && 379 (!try_module_get(owner_info->owner_handle))) 380 return -EINVAL; 381 return 0; 382} 383 384/* conditionally lower ref count on an owner */ 385static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info) 386{ 387 if (owner_info->type == CSCFG_OWNER_MODULE) 388 module_put(owner_info->owner_handle); 389} 390 391static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner) 392{ 393 struct cscfg_config_csdev *config_csdev, *tmp; 394 395 if (list_empty(&csdev->config_csdev_list)) 396 return; 397 398 list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) { 399 if (config_csdev->config_desc->load_owner == load_owner) 400 list_del(&config_csdev->node); 401 } 402} 403 404static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner) 405{ 406 struct cscfg_feature_csdev *feat_csdev, *tmp; 407 408 if (list_empty(&csdev->feature_csdev_list)) 409 return; 410 411 list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) { 412 if (feat_csdev->feat_desc->load_owner == load_owner) 413 list_del(&feat_csdev->node); 414 } 415} 416 417/* 418 * removal is relatively easy - just remove from all lists, anything that 419 * matches the owner. Memory for the descriptors will be managed by the owner, 420 * memory for the csdev items is devm_ allocated with the individual csdev 421 * devices. 422 */ 423static void cscfg_unload_owned_cfgs_feats(void *load_owner) 424{ 425 struct cscfg_config_desc *config_desc, *cfg_tmp; 426 struct cscfg_feature_desc *feat_desc, *feat_tmp; 427 struct cscfg_registered_csdev *csdev_item; 428 429 /* remove from each csdev instance feature and config lists */ 430 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 431 /* 432 * for each csdev, check the loaded lists and remove if 433 * referenced descriptor is owned 434 */ 435 cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner); 436 cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner); 437 } 438 439 /* remove from the config descriptor lists */ 440 list_for_each_entry_safe(config_desc, cfg_tmp, &cscfg_mgr->config_desc_list, item) { 441 if (config_desc->load_owner == load_owner) { 442 cscfg_configfs_del_config(config_desc); 443 etm_perf_del_symlink_cscfg(config_desc); 444 list_del(&config_desc->item); 445 } 446 } 447 448 /* remove from the feature descriptor lists */ 449 list_for_each_entry_safe(feat_desc, feat_tmp, &cscfg_mgr->feat_desc_list, item) { 450 if (feat_desc->load_owner == load_owner) { 451 cscfg_configfs_del_feature(feat_desc); 452 list_del(&feat_desc->item); 453 } 454 } 455} 456 457/** 458 * cscfg_load_config_sets - API function to load feature and config sets. 459 * 460 * Take a 0 terminated array of feature descriptors and/or configuration 461 * descriptors and load into the system. 462 * Features are loaded first to ensure configuration dependencies can be met. 463 * 464 * To facilitate dynamic loading and unloading, features and configurations 465 * have a "load_owner", to allow later unload by the same owner. An owner may 466 * be a loadable module or configuration dynamically created via configfs. 467 * As later loaded configurations can use earlier loaded features, creating load 468 * dependencies, a load order list is maintained. Unload is strictly in the 469 * reverse order to load. 470 * 471 * @config_descs: 0 terminated array of configuration descriptors. 472 * @feat_descs: 0 terminated array of feature descriptors. 473 * @owner_info: Information on the owner of this set. 474 */ 475int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, 476 struct cscfg_feature_desc **feat_descs, 477 struct cscfg_load_owner_info *owner_info) 478{ 479 int err = 0, i = 0; 480 481 mutex_lock(&cscfg_mutex); 482 483 /* load features first */ 484 if (feat_descs) { 485 while (feat_descs[i]) { 486 err = cscfg_load_feat(feat_descs[i]); 487 if (!err) 488 err = cscfg_configfs_add_feature(feat_descs[i]); 489 if (err) { 490 pr_err("coresight-syscfg: Failed to load feature %s\n", 491 feat_descs[i]->name); 492 cscfg_unload_owned_cfgs_feats(owner_info); 493 goto exit_unlock; 494 } 495 feat_descs[i]->load_owner = owner_info; 496 i++; 497 } 498 } 499 500 /* next any configurations to check feature dependencies */ 501 i = 0; 502 if (config_descs) { 503 while (config_descs[i]) { 504 err = cscfg_load_config(config_descs[i]); 505 if (!err) 506 err = cscfg_configfs_add_config(config_descs[i]); 507 if (err) { 508 pr_err("coresight-syscfg: Failed to load configuration %s\n", 509 config_descs[i]->name); 510 cscfg_unload_owned_cfgs_feats(owner_info); 511 goto exit_unlock; 512 } 513 config_descs[i]->load_owner = owner_info; 514 i++; 515 } 516 } 517 518 /* add the load owner to the load order list */ 519 list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list); 520 if (!list_is_singular(&cscfg_mgr->load_order_list)) { 521 /* lock previous item in load order list */ 522 err = cscfg_owner_get(list_prev_entry(owner_info, item)); 523 if (err) { 524 cscfg_unload_owned_cfgs_feats(owner_info); 525 list_del(&owner_info->item); 526 } 527 } 528 529exit_unlock: 530 mutex_unlock(&cscfg_mutex); 531 return err; 532} 533EXPORT_SYMBOL_GPL(cscfg_load_config_sets); 534 535/** 536 * cscfg_unload_config_sets - unload a set of configurations by owner. 537 * 538 * Dynamic unload of configuration and feature sets is done on the basis of 539 * the load owner of that set. Later loaded configurations can depend on 540 * features loaded earlier. 541 * 542 * Therefore, unload is only possible if:- 543 * 1) no configurations are active. 544 * 2) the set being unloaded was the last to be loaded to maintain dependencies. 545 * 546 * @owner_info: Information on owner for set being unloaded. 547 */ 548int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) 549{ 550 int err = 0; 551 struct cscfg_load_owner_info *load_list_item = NULL; 552 553 mutex_lock(&cscfg_mutex); 554 555 /* cannot unload if anything is active */ 556 if (atomic_read(&cscfg_mgr->sys_active_cnt)) { 557 err = -EBUSY; 558 goto exit_unlock; 559 } 560 561 /* cannot unload if not last loaded in load order */ 562 if (!list_empty(&cscfg_mgr->load_order_list)) { 563 load_list_item = list_last_entry(&cscfg_mgr->load_order_list, 564 struct cscfg_load_owner_info, item); 565 if (load_list_item != owner_info) 566 load_list_item = NULL; 567 } 568 569 if (!load_list_item) { 570 err = -EINVAL; 571 goto exit_unlock; 572 } 573 574 /* unload all belonging to load_owner */ 575 cscfg_unload_owned_cfgs_feats(owner_info); 576 577 /* remove from load order list */ 578 if (!list_is_singular(&cscfg_mgr->load_order_list)) { 579 /* unlock previous item in load order list */ 580 cscfg_owner_put(list_prev_entry(owner_info, item)); 581 } 582 list_del(&owner_info->item); 583 584exit_unlock: 585 mutex_unlock(&cscfg_mutex); 586 return err; 587} 588EXPORT_SYMBOL_GPL(cscfg_unload_config_sets); 589 590/* Handle coresight device registration and add configs and features to devices */ 591 592/* iterate through config lists and load matching configs to device */ 593static int cscfg_add_cfgs_csdev(struct coresight_device *csdev) 594{ 595 struct cscfg_config_desc *config_desc; 596 int err = 0; 597 598 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 599 err = cscfg_add_csdev_cfg(csdev, config_desc); 600 if (err) 601 break; 602 } 603 return err; 604} 605 606/* iterate through feature lists and load matching features to device */ 607static int cscfg_add_feats_csdev(struct coresight_device *csdev, 608 u32 match_flags, 609 struct cscfg_csdev_feat_ops *ops) 610{ 611 struct cscfg_feature_desc *feat_desc; 612 int err = 0; 613 614 if (!ops->load_feat) 615 return -EINVAL; 616 617 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) { 618 if (feat_desc->match_flags & match_flags) { 619 err = cscfg_load_feat_csdev(csdev, feat_desc, ops); 620 if (err) 621 break; 622 } 623 } 624 return err; 625} 626 627/* Add coresight device to list and copy its matching info */ 628static int cscfg_list_add_csdev(struct coresight_device *csdev, 629 u32 match_flags, 630 struct cscfg_csdev_feat_ops *ops) 631{ 632 struct cscfg_registered_csdev *csdev_item; 633 634 /* allocate the list entry structure */ 635 csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL); 636 if (!csdev_item) 637 return -ENOMEM; 638 639 csdev_item->csdev = csdev; 640 csdev_item->match_flags = match_flags; 641 csdev_item->ops.load_feat = ops->load_feat; 642 list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list); 643 644 INIT_LIST_HEAD(&csdev->feature_csdev_list); 645 INIT_LIST_HEAD(&csdev->config_csdev_list); 646 spin_lock_init(&csdev->cscfg_csdev_lock); 647 648 return 0; 649} 650 651/* remove a coresight device from the list and free data */ 652static void cscfg_list_remove_csdev(struct coresight_device *csdev) 653{ 654 struct cscfg_registered_csdev *csdev_item, *tmp; 655 656 list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) { 657 if (csdev_item->csdev == csdev) { 658 list_del(&csdev_item->item); 659 kfree(csdev_item); 660 break; 661 } 662 } 663} 664 665/** 666 * cscfg_register_csdev - register a coresight device with the syscfg manager. 667 * 668 * Registers the coresight device with the system. @match_flags used to check 669 * if the device is a match for registered features. Any currently registered 670 * configurations and features that match the device will be loaded onto it. 671 * 672 * @csdev: The coresight device to register. 673 * @match_flags: Matching information to load features. 674 * @ops: Standard operations supported by the device. 675 */ 676int cscfg_register_csdev(struct coresight_device *csdev, 677 u32 match_flags, 678 struct cscfg_csdev_feat_ops *ops) 679{ 680 int ret = 0; 681 682 mutex_lock(&cscfg_mutex); 683 684 /* add device to list of registered devices */ 685 ret = cscfg_list_add_csdev(csdev, match_flags, ops); 686 if (ret) 687 goto reg_csdev_unlock; 688 689 /* now load any registered features and configs matching the device. */ 690 ret = cscfg_add_feats_csdev(csdev, match_flags, ops); 691 if (ret) { 692 cscfg_list_remove_csdev(csdev); 693 goto reg_csdev_unlock; 694 } 695 696 ret = cscfg_add_cfgs_csdev(csdev); 697 if (ret) { 698 cscfg_list_remove_csdev(csdev); 699 goto reg_csdev_unlock; 700 } 701 702 pr_info("CSCFG registered %s", dev_name(&csdev->dev)); 703 704reg_csdev_unlock: 705 mutex_unlock(&cscfg_mutex); 706 return ret; 707} 708EXPORT_SYMBOL_GPL(cscfg_register_csdev); 709 710/** 711 * cscfg_unregister_csdev - remove coresight device from syscfg manager. 712 * 713 * @csdev: Device to remove. 714 */ 715void cscfg_unregister_csdev(struct coresight_device *csdev) 716{ 717 mutex_lock(&cscfg_mutex); 718 cscfg_list_remove_csdev(csdev); 719 mutex_unlock(&cscfg_mutex); 720} 721EXPORT_SYMBOL_GPL(cscfg_unregister_csdev); 722 723/** 724 * cscfg_csdev_reset_feats - reset features for a CoreSight device. 725 * 726 * Resets all parameters and register values for any features loaded 727 * into @csdev to their default values. 728 * 729 * @csdev: The CoreSight device. 730 */ 731void cscfg_csdev_reset_feats(struct coresight_device *csdev) 732{ 733 struct cscfg_feature_csdev *feat_csdev; 734 unsigned long flags; 735 736 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 737 if (list_empty(&csdev->feature_csdev_list)) 738 goto unlock_exit; 739 740 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) 741 cscfg_reset_feat(feat_csdev); 742 743unlock_exit: 744 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 745} 746EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats); 747 748/* 749 * This activate configuration for either perf or sysfs. Perf can have multiple 750 * active configs, selected per event, sysfs is limited to one. 751 * 752 * Increments the configuration descriptor active count and the global active 753 * count. 754 * 755 * @cfg_hash: Hash value of the selected configuration name. 756 */ 757static int _cscfg_activate_config(unsigned long cfg_hash) 758{ 759 struct cscfg_config_desc *config_desc; 760 int err = -EINVAL; 761 762 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 763 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 764 /* must ensure that config cannot be unloaded in use */ 765 err = cscfg_owner_get(config_desc->load_owner); 766 if (err) 767 break; 768 /* 769 * increment the global active count - control changes to 770 * active configurations 771 */ 772 atomic_inc(&cscfg_mgr->sys_active_cnt); 773 774 /* 775 * mark the descriptor as active so enable config on a 776 * device instance will use it 777 */ 778 atomic_inc(&config_desc->active_cnt); 779 780 err = 0; 781 dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name); 782 break; 783 } 784 } 785 return err; 786} 787 788static void _cscfg_deactivate_config(unsigned long cfg_hash) 789{ 790 struct cscfg_config_desc *config_desc; 791 792 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 793 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 794 atomic_dec(&config_desc->active_cnt); 795 atomic_dec(&cscfg_mgr->sys_active_cnt); 796 cscfg_owner_put(config_desc->load_owner); 797 dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); 798 break; 799 } 800 } 801} 802 803/* 804 * called from configfs to set/clear the active configuration for use when 805 * using sysfs to control trace. 806 */ 807int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate) 808{ 809 unsigned long cfg_hash; 810 int err = 0; 811 812 mutex_lock(&cscfg_mutex); 813 814 cfg_hash = (unsigned long)config_desc->event_ea->var; 815 816 if (activate) { 817 /* cannot be a current active value to activate this */ 818 if (cscfg_mgr->sysfs_active_config) { 819 err = -EBUSY; 820 goto exit_unlock; 821 } 822 err = _cscfg_activate_config(cfg_hash); 823 if (!err) 824 cscfg_mgr->sysfs_active_config = cfg_hash; 825 } else { 826 /* disable if matching current value */ 827 if (cscfg_mgr->sysfs_active_config == cfg_hash) { 828 _cscfg_deactivate_config(cfg_hash); 829 cscfg_mgr->sysfs_active_config = 0; 830 } else 831 err = -EINVAL; 832 } 833 834exit_unlock: 835 mutex_unlock(&cscfg_mutex); 836 return err; 837} 838 839/* set the sysfs preset value */ 840void cscfg_config_sysfs_set_preset(int preset) 841{ 842 mutex_lock(&cscfg_mutex); 843 cscfg_mgr->sysfs_active_preset = preset; 844 mutex_unlock(&cscfg_mutex); 845} 846 847/* 848 * Used by a device to get the config and preset selected as active in configfs, 849 * when using sysfs to control trace. 850 */ 851void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset) 852{ 853 mutex_lock(&cscfg_mutex); 854 *preset = cscfg_mgr->sysfs_active_preset; 855 *cfg_hash = cscfg_mgr->sysfs_active_config; 856 mutex_unlock(&cscfg_mutex); 857} 858EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg); 859 860/** 861 * cscfg_activate_config - Mark a configuration descriptor as active. 862 * 863 * This will be seen when csdev devices are enabled in the system. 864 * Only activated configurations can be enabled on individual devices. 865 * Activation protects the configuration from alteration or removal while 866 * active. 867 * 868 * Selection by hash value - generated from the configuration name when it 869 * was loaded and added to the cs_etm/configurations file system for selection 870 * by perf. 871 * 872 * @cfg_hash: Hash value of the selected configuration name. 873 */ 874int cscfg_activate_config(unsigned long cfg_hash) 875{ 876 int err = 0; 877 878 mutex_lock(&cscfg_mutex); 879 err = _cscfg_activate_config(cfg_hash); 880 mutex_unlock(&cscfg_mutex); 881 882 return err; 883} 884EXPORT_SYMBOL_GPL(cscfg_activate_config); 885 886/** 887 * cscfg_deactivate_config - Mark a config descriptor as inactive. 888 * 889 * Decrement the configuration and global active counts. 890 * 891 * @cfg_hash: Hash value of the selected configuration name. 892 */ 893void cscfg_deactivate_config(unsigned long cfg_hash) 894{ 895 mutex_lock(&cscfg_mutex); 896 _cscfg_deactivate_config(cfg_hash); 897 mutex_unlock(&cscfg_mutex); 898} 899EXPORT_SYMBOL_GPL(cscfg_deactivate_config); 900 901/** 902 * cscfg_csdev_enable_active_config - Enable matching active configuration for device. 903 * 904 * Enables the configuration selected by @cfg_hash if the configuration is supported 905 * on the device and has been activated. 906 * 907 * If active and supported the CoreSight device @csdev will be programmed with the 908 * configuration, using @preset parameters. 909 * 910 * Should be called before driver hardware enable for the requested device, prior to 911 * programming and enabling the physical hardware. 912 * 913 * @csdev: CoreSight device to program. 914 * @cfg_hash: Selector for the configuration. 915 * @preset: Preset parameter values to use, 0 for current / default values. 916 */ 917int cscfg_csdev_enable_active_config(struct coresight_device *csdev, 918 unsigned long cfg_hash, int preset) 919{ 920 struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item; 921 const struct cscfg_config_desc *config_desc; 922 unsigned long flags; 923 int err = 0; 924 925 /* quickly check global count */ 926 if (!atomic_read(&cscfg_mgr->sys_active_cnt)) 927 return 0; 928 929 /* 930 * Look for matching configuration - set the active configuration 931 * context if found. 932 */ 933 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 934 list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) { 935 config_desc = config_csdev_item->config_desc; 936 if ((atomic_read(&config_desc->active_cnt)) && 937 ((unsigned long)config_desc->event_ea->var == cfg_hash)) { 938 config_csdev_active = config_csdev_item; 939 csdev->active_cscfg_ctxt = (void *)config_csdev_active; 940 break; 941 } 942 } 943 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 944 945 /* 946 * If found, attempt to enable 947 */ 948 if (config_csdev_active) { 949 /* 950 * Call the generic routine that will program up the internal 951 * driver structures prior to programming up the hardware. 952 * This routine takes the driver spinlock saved in the configs. 953 */ 954 err = cscfg_csdev_enable_config(config_csdev_active, preset); 955 if (!err) { 956 /* 957 * Successful programming. Check the active_cscfg_ctxt 958 * pointer to ensure no pre-emption disabled it via 959 * cscfg_csdev_disable_active_config() before 960 * we could start. 961 * 962 * Set enabled if OK, err if not. 963 */ 964 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 965 if (csdev->active_cscfg_ctxt) 966 config_csdev_active->enabled = true; 967 else 968 err = -EBUSY; 969 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 970 } 971 } 972 return err; 973} 974EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config); 975 976/** 977 * cscfg_csdev_disable_active_config - disable an active config on the device. 978 * 979 * Disables the active configuration on the CoreSight device @csdev. 980 * Disable will save the values of any registers marked in the configurations 981 * as save on disable. 982 * 983 * Should be called after driver hardware disable for the requested device, 984 * after disabling the physical hardware and reading back registers. 985 * 986 * @csdev: The CoreSight device. 987 */ 988void cscfg_csdev_disable_active_config(struct coresight_device *csdev) 989{ 990 struct cscfg_config_csdev *config_csdev; 991 unsigned long flags; 992 993 /* 994 * Check if we have an active config, and that it was successfully enabled. 995 * If it was not enabled, we have no work to do, otherwise mark as disabled. 996 * Clear the active config pointer. 997 */ 998 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 999 config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt; 1000 if (config_csdev) { 1001 if (!config_csdev->enabled) 1002 config_csdev = NULL; 1003 else 1004 config_csdev->enabled = false; 1005 } 1006 csdev->active_cscfg_ctxt = NULL; 1007 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 1008 1009 /* true if there was an enabled active config */ 1010 if (config_csdev) 1011 cscfg_csdev_disable_config(config_csdev); 1012} 1013EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config); 1014 1015/* Initialise system configuration management device. */ 1016 1017struct device *cscfg_device(void) 1018{ 1019 return cscfg_mgr ? &cscfg_mgr->dev : NULL; 1020} 1021 1022/* Must have a release function or the kernel will complain on module unload */ 1023static void cscfg_dev_release(struct device *dev) 1024{ 1025 kfree(cscfg_mgr); 1026 cscfg_mgr = NULL; 1027} 1028 1029/* a device is needed to "own" some kernel elements such as sysfs entries. */ 1030static int cscfg_create_device(void) 1031{ 1032 struct device *dev; 1033 int err = -ENOMEM; 1034 1035 mutex_lock(&cscfg_mutex); 1036 if (cscfg_mgr) { 1037 err = -EINVAL; 1038 goto create_dev_exit_unlock; 1039 } 1040 1041 cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL); 1042 if (!cscfg_mgr) 1043 goto create_dev_exit_unlock; 1044 1045 /* setup the device */ 1046 dev = cscfg_device(); 1047 dev->release = cscfg_dev_release; 1048 dev->init_name = "cs_system_cfg"; 1049 1050 err = device_register(dev); 1051 if (err) 1052 put_device(dev); 1053 1054create_dev_exit_unlock: 1055 mutex_unlock(&cscfg_mutex); 1056 return err; 1057} 1058 1059static void cscfg_clear_device(void) 1060{ 1061 struct cscfg_config_desc *cfg_desc; 1062 1063 mutex_lock(&cscfg_mutex); 1064 list_for_each_entry(cfg_desc, &cscfg_mgr->config_desc_list, item) { 1065 etm_perf_del_symlink_cscfg(cfg_desc); 1066 } 1067 cscfg_configfs_release(cscfg_mgr); 1068 device_unregister(cscfg_device()); 1069 mutex_unlock(&cscfg_mutex); 1070} 1071 1072/* Initialise system config management API device */ 1073int __init cscfg_init(void) 1074{ 1075 int err = 0; 1076 1077 err = cscfg_create_device(); 1078 if (err) 1079 return err; 1080 1081 err = cscfg_configfs_init(cscfg_mgr); 1082 if (err) 1083 goto exit_err; 1084 1085 INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list); 1086 INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list); 1087 INIT_LIST_HEAD(&cscfg_mgr->config_desc_list); 1088 INIT_LIST_HEAD(&cscfg_mgr->load_order_list); 1089 atomic_set(&cscfg_mgr->sys_active_cnt, 0); 1090 1091 /* preload built-in configurations */ 1092 err = cscfg_preload(THIS_MODULE); 1093 if (err) 1094 goto exit_err; 1095 1096 dev_info(cscfg_device(), "CoreSight Configuration manager initialised"); 1097 return 0; 1098 1099exit_err: 1100 cscfg_clear_device(); 1101 return err; 1102} 1103 1104void cscfg_exit(void) 1105{ 1106 cscfg_clear_device(); 1107}