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 */ 24 static DEFINE_MUTEX(cscfg_mutex); 25 26 /* only one of these */ 27 static 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 */ 32 static struct cscfg_feature_csdev * 33 cscfg_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 */ 45 static struct cscfg_config_csdev * 46 cscfg_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 */ 63 static 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 raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 93 list_add(&config_csdev->node, &csdev->config_csdev_list); 94 raw_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 */ 105 static 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 */ 122 static struct cscfg_feature_csdev * 123 cscfg_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 */ 175 static 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 raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 198 list_add(&feat_csdev->node, &csdev->feature_csdev_list); 199 raw_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 */ 209 static 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. */ 225 static 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. */ 237 static 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 */ 250 static 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 */ 274 static 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 */ 306 const 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 */ 324 static struct cscfg_feature_csdev * 325 cscfg_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 337 int 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 366 unlock_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 */ 376 static 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 */ 385 static 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 391 static 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 guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock); 399 400 list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) { 401 if (config_csdev->config_desc->load_owner == load_owner) 402 list_del(&config_csdev->node); 403 } 404 } 405 406 static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner) 407 { 408 struct cscfg_feature_csdev *feat_csdev, *tmp; 409 410 if (list_empty(&csdev->feature_csdev_list)) 411 return; 412 413 list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) { 414 if (feat_csdev->feat_desc->load_owner == load_owner) 415 list_del(&feat_csdev->node); 416 } 417 } 418 419 /* 420 * Unregister all configuration and features from configfs owned by load_owner. 421 * Although this is called without the list mutex being held, it is in the 422 * context of an unload operation which are strictly serialised, 423 * so the lists cannot change during this call. 424 */ 425 static void cscfg_fs_unregister_cfgs_feats(void *load_owner) 426 { 427 struct cscfg_config_desc *config_desc; 428 struct cscfg_feature_desc *feat_desc; 429 430 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 431 if (config_desc->load_owner == load_owner) 432 cscfg_configfs_del_config(config_desc); 433 } 434 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) { 435 if (feat_desc->load_owner == load_owner) 436 cscfg_configfs_del_feature(feat_desc); 437 } 438 } 439 440 /* 441 * removal is relatively easy - just remove from all lists, anything that 442 * matches the owner. Memory for the descriptors will be managed by the owner, 443 * memory for the csdev items is devm_ allocated with the individual csdev 444 * devices. 445 */ 446 static void cscfg_unload_owned_cfgs_feats(void *load_owner) 447 { 448 struct cscfg_config_desc *config_desc, *cfg_tmp; 449 struct cscfg_feature_desc *feat_desc, *feat_tmp; 450 struct cscfg_registered_csdev *csdev_item; 451 452 lockdep_assert_held(&cscfg_mutex); 453 454 /* remove from each csdev instance feature and config lists */ 455 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 456 /* 457 * for each csdev, check the loaded lists and remove if 458 * referenced descriptor is owned 459 */ 460 cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner); 461 cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner); 462 } 463 464 /* remove from the config descriptor lists */ 465 list_for_each_entry_safe(config_desc, cfg_tmp, &cscfg_mgr->config_desc_list, item) { 466 if (config_desc->load_owner == load_owner) { 467 etm_perf_del_symlink_cscfg(config_desc); 468 list_del(&config_desc->item); 469 } 470 } 471 472 /* remove from the feature descriptor lists */ 473 list_for_each_entry_safe(feat_desc, feat_tmp, &cscfg_mgr->feat_desc_list, item) { 474 if (feat_desc->load_owner == load_owner) { 475 list_del(&feat_desc->item); 476 } 477 } 478 } 479 480 /* 481 * load the features and configs to the lists - called with list mutex held 482 */ 483 static int cscfg_load_owned_cfgs_feats(struct cscfg_config_desc **config_descs, 484 struct cscfg_feature_desc **feat_descs, 485 struct cscfg_load_owner_info *owner_info) 486 { 487 int i, err; 488 489 lockdep_assert_held(&cscfg_mutex); 490 491 /* load features first */ 492 if (feat_descs) { 493 for (i = 0; feat_descs[i]; i++) { 494 err = cscfg_load_feat(feat_descs[i]); 495 if (err) { 496 pr_err("coresight-syscfg: Failed to load feature %s\n", 497 feat_descs[i]->name); 498 return err; 499 } 500 feat_descs[i]->load_owner = owner_info; 501 } 502 } 503 504 /* next any configurations to check feature dependencies */ 505 if (config_descs) { 506 for (i = 0; config_descs[i]; i++) { 507 err = cscfg_load_config(config_descs[i]); 508 if (err) { 509 pr_err("coresight-syscfg: Failed to load configuration %s\n", 510 config_descs[i]->name); 511 return err; 512 } 513 config_descs[i]->load_owner = owner_info; 514 config_descs[i]->available = false; 515 } 516 } 517 return 0; 518 } 519 520 /* set configurations as available to activate at the end of the load process */ 521 static void cscfg_set_configs_available(struct cscfg_config_desc **config_descs) 522 { 523 int i; 524 525 lockdep_assert_held(&cscfg_mutex); 526 527 if (config_descs) { 528 for (i = 0; config_descs[i]; i++) 529 config_descs[i]->available = true; 530 } 531 } 532 533 /* 534 * Create and register each of the configurations and features with configfs. 535 * Called without mutex being held. 536 */ 537 static int cscfg_fs_register_cfgs_feats(struct cscfg_config_desc **config_descs, 538 struct cscfg_feature_desc **feat_descs) 539 { 540 int i, err; 541 542 if (feat_descs) { 543 for (i = 0; feat_descs[i]; i++) { 544 err = cscfg_configfs_add_feature(feat_descs[i]); 545 if (err) 546 return err; 547 } 548 } 549 if (config_descs) { 550 for (i = 0; config_descs[i]; i++) { 551 err = cscfg_configfs_add_config(config_descs[i]); 552 if (err) 553 return err; 554 } 555 } 556 return 0; 557 } 558 559 /** 560 * cscfg_load_config_sets - API function to load feature and config sets. 561 * 562 * Take a 0 terminated array of feature descriptors and/or configuration 563 * descriptors and load into the system. 564 * Features are loaded first to ensure configuration dependencies can be met. 565 * 566 * To facilitate dynamic loading and unloading, features and configurations 567 * have a "load_owner", to allow later unload by the same owner. An owner may 568 * be a loadable module or configuration dynamically created via configfs. 569 * As later loaded configurations can use earlier loaded features, creating load 570 * dependencies, a load order list is maintained. Unload is strictly in the 571 * reverse order to load. 572 * 573 * @config_descs: 0 terminated array of configuration descriptors. 574 * @feat_descs: 0 terminated array of feature descriptors. 575 * @owner_info: Information on the owner of this set. 576 */ 577 int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, 578 struct cscfg_feature_desc **feat_descs, 579 struct cscfg_load_owner_info *owner_info) 580 { 581 int err = 0; 582 583 mutex_lock(&cscfg_mutex); 584 if (cscfg_mgr->load_state != CSCFG_NONE) { 585 mutex_unlock(&cscfg_mutex); 586 return -EBUSY; 587 } 588 cscfg_mgr->load_state = CSCFG_LOAD; 589 590 /* first load and add to the lists */ 591 err = cscfg_load_owned_cfgs_feats(config_descs, feat_descs, owner_info); 592 if (err) 593 goto err_clean_load; 594 595 /* add the load owner to the load order list */ 596 list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list); 597 if (!list_is_singular(&cscfg_mgr->load_order_list)) { 598 /* lock previous item in load order list */ 599 err = cscfg_owner_get(list_prev_entry(owner_info, item)); 600 if (err) 601 goto err_clean_owner_list; 602 } 603 604 /* 605 * make visible to configfs - configfs manipulation must occur outside 606 * the list mutex lock to avoid circular lockdep issues with configfs 607 * built in mutexes and semaphores. This is safe as it is not possible 608 * to start a new load/unload operation till the current one is done. 609 */ 610 mutex_unlock(&cscfg_mutex); 611 612 /* create the configfs elements */ 613 err = cscfg_fs_register_cfgs_feats(config_descs, feat_descs); 614 mutex_lock(&cscfg_mutex); 615 616 if (err) 617 goto err_clean_cfs; 618 619 /* mark any new configs as available for activation */ 620 cscfg_set_configs_available(config_descs); 621 goto exit_unlock; 622 623 err_clean_cfs: 624 /* cleanup after error registering with configfs */ 625 cscfg_fs_unregister_cfgs_feats(owner_info); 626 627 if (!list_is_singular(&cscfg_mgr->load_order_list)) 628 cscfg_owner_put(list_prev_entry(owner_info, item)); 629 630 err_clean_owner_list: 631 list_del(&owner_info->item); 632 633 err_clean_load: 634 cscfg_unload_owned_cfgs_feats(owner_info); 635 636 exit_unlock: 637 cscfg_mgr->load_state = CSCFG_NONE; 638 mutex_unlock(&cscfg_mutex); 639 return err; 640 } 641 EXPORT_SYMBOL_GPL(cscfg_load_config_sets); 642 643 /** 644 * cscfg_unload_config_sets - unload a set of configurations by owner. 645 * 646 * Dynamic unload of configuration and feature sets is done on the basis of 647 * the load owner of that set. Later loaded configurations can depend on 648 * features loaded earlier. 649 * 650 * Therefore, unload is only possible if:- 651 * 1) no configurations are active. 652 * 2) the set being unloaded was the last to be loaded to maintain dependencies. 653 * 654 * Once the unload operation commences, we disallow any configuration being 655 * made active until it is complete. 656 * 657 * @owner_info: Information on owner for set being unloaded. 658 */ 659 int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) 660 { 661 int err = 0; 662 struct cscfg_load_owner_info *load_list_item = NULL; 663 664 mutex_lock(&cscfg_mutex); 665 if (cscfg_mgr->load_state != CSCFG_NONE) { 666 mutex_unlock(&cscfg_mutex); 667 return -EBUSY; 668 } 669 670 /* unload op in progress also prevents activation of any config */ 671 cscfg_mgr->load_state = CSCFG_UNLOAD; 672 673 /* cannot unload if anything is active */ 674 if (atomic_read(&cscfg_mgr->sys_active_cnt)) { 675 err = -EBUSY; 676 goto exit_unlock; 677 } 678 679 /* cannot unload if not last loaded in load order */ 680 if (!list_empty(&cscfg_mgr->load_order_list)) { 681 load_list_item = list_last_entry(&cscfg_mgr->load_order_list, 682 struct cscfg_load_owner_info, item); 683 if (load_list_item != owner_info) 684 load_list_item = NULL; 685 } 686 687 if (!load_list_item) { 688 err = -EINVAL; 689 goto exit_unlock; 690 } 691 692 /* remove from configfs - again outside the scope of the list mutex */ 693 mutex_unlock(&cscfg_mutex); 694 cscfg_fs_unregister_cfgs_feats(owner_info); 695 mutex_lock(&cscfg_mutex); 696 697 /* unload everything from lists belonging to load_owner */ 698 cscfg_unload_owned_cfgs_feats(owner_info); 699 700 /* remove from load order list */ 701 if (!list_is_singular(&cscfg_mgr->load_order_list)) { 702 /* unlock previous item in load order list */ 703 cscfg_owner_put(list_prev_entry(owner_info, item)); 704 } 705 list_del(&owner_info->item); 706 707 exit_unlock: 708 cscfg_mgr->load_state = CSCFG_NONE; 709 mutex_unlock(&cscfg_mutex); 710 return err; 711 } 712 EXPORT_SYMBOL_GPL(cscfg_unload_config_sets); 713 714 /* Handle coresight device registration and add configs and features to devices */ 715 716 /* iterate through config lists and load matching configs to device */ 717 static int cscfg_add_cfgs_csdev(struct coresight_device *csdev) 718 { 719 struct cscfg_config_desc *config_desc; 720 int err = 0; 721 722 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 723 err = cscfg_add_csdev_cfg(csdev, config_desc); 724 if (err) 725 break; 726 } 727 return err; 728 } 729 730 /* iterate through feature lists and load matching features to device */ 731 static int cscfg_add_feats_csdev(struct coresight_device *csdev, 732 u32 match_flags, 733 struct cscfg_csdev_feat_ops *ops) 734 { 735 struct cscfg_feature_desc *feat_desc; 736 int err = 0; 737 738 if (!ops->load_feat) 739 return -EINVAL; 740 741 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) { 742 if (feat_desc->match_flags & match_flags) { 743 err = cscfg_load_feat_csdev(csdev, feat_desc, ops); 744 if (err) 745 break; 746 } 747 } 748 return err; 749 } 750 751 /* Add coresight device to list and copy its matching info */ 752 static int cscfg_list_add_csdev(struct coresight_device *csdev, 753 u32 match_flags, 754 struct cscfg_csdev_feat_ops *ops) 755 { 756 struct cscfg_registered_csdev *csdev_item; 757 758 /* allocate the list entry structure */ 759 csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL); 760 if (!csdev_item) 761 return -ENOMEM; 762 763 csdev_item->csdev = csdev; 764 csdev_item->match_flags = match_flags; 765 csdev_item->ops.load_feat = ops->load_feat; 766 list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list); 767 768 INIT_LIST_HEAD(&csdev->feature_csdev_list); 769 INIT_LIST_HEAD(&csdev->config_csdev_list); 770 raw_spin_lock_init(&csdev->cscfg_csdev_lock); 771 772 return 0; 773 } 774 775 /* remove a coresight device from the list and free data */ 776 static void cscfg_list_remove_csdev(struct coresight_device *csdev) 777 { 778 struct cscfg_registered_csdev *csdev_item, *tmp; 779 780 list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) { 781 if (csdev_item->csdev == csdev) { 782 list_del(&csdev_item->item); 783 kfree(csdev_item); 784 break; 785 } 786 } 787 } 788 789 /** 790 * cscfg_register_csdev - register a coresight device with the syscfg manager. 791 * 792 * Registers the coresight device with the system. @match_flags used to check 793 * if the device is a match for registered features. Any currently registered 794 * configurations and features that match the device will be loaded onto it. 795 * 796 * @csdev: The coresight device to register. 797 * @match_flags: Matching information to load features. 798 * @ops: Standard operations supported by the device. 799 */ 800 int cscfg_register_csdev(struct coresight_device *csdev, 801 u32 match_flags, 802 struct cscfg_csdev_feat_ops *ops) 803 { 804 int ret = 0; 805 806 mutex_lock(&cscfg_mutex); 807 808 /* add device to list of registered devices */ 809 ret = cscfg_list_add_csdev(csdev, match_flags, ops); 810 if (ret) 811 goto reg_csdev_unlock; 812 813 /* now load any registered features and configs matching the device. */ 814 ret = cscfg_add_feats_csdev(csdev, match_flags, ops); 815 if (ret) { 816 cscfg_list_remove_csdev(csdev); 817 goto reg_csdev_unlock; 818 } 819 820 ret = cscfg_add_cfgs_csdev(csdev); 821 if (ret) { 822 cscfg_list_remove_csdev(csdev); 823 goto reg_csdev_unlock; 824 } 825 826 pr_info("CSCFG registered %s", dev_name(&csdev->dev)); 827 828 reg_csdev_unlock: 829 mutex_unlock(&cscfg_mutex); 830 return ret; 831 } 832 EXPORT_SYMBOL_GPL(cscfg_register_csdev); 833 834 /** 835 * cscfg_unregister_csdev - remove coresight device from syscfg manager. 836 * 837 * @csdev: Device to remove. 838 */ 839 void cscfg_unregister_csdev(struct coresight_device *csdev) 840 { 841 mutex_lock(&cscfg_mutex); 842 cscfg_list_remove_csdev(csdev); 843 mutex_unlock(&cscfg_mutex); 844 } 845 EXPORT_SYMBOL_GPL(cscfg_unregister_csdev); 846 847 /** 848 * cscfg_csdev_reset_feats - reset features for a CoreSight device. 849 * 850 * Resets all parameters and register values for any features loaded 851 * into @csdev to their default values. 852 * 853 * @csdev: The CoreSight device. 854 */ 855 void cscfg_csdev_reset_feats(struct coresight_device *csdev) 856 { 857 struct cscfg_feature_csdev *feat_csdev; 858 unsigned long flags; 859 860 raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 861 if (list_empty(&csdev->feature_csdev_list)) 862 goto unlock_exit; 863 864 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) 865 cscfg_reset_feat(feat_csdev); 866 867 unlock_exit: 868 raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 869 } 870 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats); 871 872 static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc) 873 { 874 if (!atomic_fetch_inc(&config_desc->active_cnt)) { 875 /* must ensure that config cannot be unloaded in use */ 876 if (unlikely(cscfg_owner_get(config_desc->load_owner))) { 877 atomic_dec(&config_desc->active_cnt); 878 return false; 879 } 880 } 881 882 return true; 883 } 884 885 static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc) 886 { 887 if (!atomic_dec_return(&config_desc->active_cnt)) 888 cscfg_owner_put(config_desc->load_owner); 889 } 890 891 /* 892 * This activate configuration for either perf or sysfs. Perf can have multiple 893 * active configs, selected per event, sysfs is limited to one. 894 * 895 * Increments the configuration descriptor active count and the global active 896 * count. 897 * 898 * @cfg_hash: Hash value of the selected configuration name. 899 */ 900 static int _cscfg_activate_config(unsigned long cfg_hash) 901 { 902 struct cscfg_config_desc *config_desc; 903 int err = -EINVAL; 904 905 if (cscfg_mgr->load_state == CSCFG_UNLOAD) 906 return -EBUSY; 907 908 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 909 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 910 /* if we happen upon a partly loaded config, can't use it */ 911 if (config_desc->available == false) 912 return -EBUSY; 913 914 if (!cscfg_config_desc_get(config_desc)) { 915 err = -EINVAL; 916 break; 917 } 918 919 /* 920 * increment the global active count - control changes to 921 * active configurations 922 */ 923 atomic_inc(&cscfg_mgr->sys_active_cnt); 924 925 err = 0; 926 dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name); 927 break; 928 } 929 } 930 return err; 931 } 932 933 static void _cscfg_deactivate_config(unsigned long cfg_hash) 934 { 935 struct cscfg_config_desc *config_desc; 936 937 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 938 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 939 atomic_dec(&cscfg_mgr->sys_active_cnt); 940 cscfg_config_desc_put(config_desc); 941 dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); 942 break; 943 } 944 } 945 } 946 947 /* 948 * called from configfs to set/clear the active configuration for use when 949 * using sysfs to control trace. 950 */ 951 int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate) 952 { 953 unsigned long cfg_hash; 954 int err = 0; 955 956 mutex_lock(&cscfg_mutex); 957 958 cfg_hash = (unsigned long)config_desc->event_ea->var; 959 960 if (activate) { 961 /* cannot be a current active value to activate this */ 962 if (cscfg_mgr->sysfs_active_config) { 963 err = -EBUSY; 964 goto exit_unlock; 965 } 966 err = _cscfg_activate_config(cfg_hash); 967 if (!err) 968 cscfg_mgr->sysfs_active_config = cfg_hash; 969 } else { 970 /* disable if matching current value */ 971 if (cscfg_mgr->sysfs_active_config == cfg_hash) { 972 _cscfg_deactivate_config(cfg_hash); 973 cscfg_mgr->sysfs_active_config = 0; 974 } else 975 err = -EINVAL; 976 } 977 978 exit_unlock: 979 mutex_unlock(&cscfg_mutex); 980 return err; 981 } 982 983 /* set the sysfs preset value */ 984 void cscfg_config_sysfs_set_preset(int preset) 985 { 986 mutex_lock(&cscfg_mutex); 987 cscfg_mgr->sysfs_active_preset = preset; 988 mutex_unlock(&cscfg_mutex); 989 } 990 991 /* 992 * Used by a device to get the config and preset selected as active in configfs, 993 * when using sysfs to control trace. 994 */ 995 void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset) 996 { 997 mutex_lock(&cscfg_mutex); 998 *preset = cscfg_mgr->sysfs_active_preset; 999 *cfg_hash = cscfg_mgr->sysfs_active_config; 1000 mutex_unlock(&cscfg_mutex); 1001 } 1002 EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg); 1003 1004 /** 1005 * cscfg_activate_config - Mark a configuration descriptor as active. 1006 * 1007 * This will be seen when csdev devices are enabled in the system. 1008 * Only activated configurations can be enabled on individual devices. 1009 * Activation protects the configuration from alteration or removal while 1010 * active. 1011 * 1012 * Selection by hash value - generated from the configuration name when it 1013 * was loaded and added to the cs_etm/configurations file system for selection 1014 * by perf. 1015 * 1016 * @cfg_hash: Hash value of the selected configuration name. 1017 */ 1018 int cscfg_activate_config(unsigned long cfg_hash) 1019 { 1020 int err = 0; 1021 1022 mutex_lock(&cscfg_mutex); 1023 err = _cscfg_activate_config(cfg_hash); 1024 mutex_unlock(&cscfg_mutex); 1025 1026 return err; 1027 } 1028 EXPORT_SYMBOL_GPL(cscfg_activate_config); 1029 1030 /** 1031 * cscfg_deactivate_config - Mark a config descriptor as inactive. 1032 * 1033 * Decrement the configuration and global active counts. 1034 * 1035 * @cfg_hash: Hash value of the selected configuration name. 1036 */ 1037 void cscfg_deactivate_config(unsigned long cfg_hash) 1038 { 1039 mutex_lock(&cscfg_mutex); 1040 _cscfg_deactivate_config(cfg_hash); 1041 mutex_unlock(&cscfg_mutex); 1042 } 1043 EXPORT_SYMBOL_GPL(cscfg_deactivate_config); 1044 1045 /** 1046 * cscfg_csdev_enable_active_config - Enable matching active configuration for device. 1047 * 1048 * Enables the configuration selected by @cfg_hash if the configuration is supported 1049 * on the device and has been activated. 1050 * 1051 * If active and supported the CoreSight device @csdev will be programmed with the 1052 * configuration, using @preset parameters. 1053 * 1054 * Should be called before driver hardware enable for the requested device, prior to 1055 * programming and enabling the physical hardware. 1056 * 1057 * @csdev: CoreSight device to program. 1058 * @cfg_hash: Selector for the configuration. 1059 * @preset: Preset parameter values to use, 0 for current / default values. 1060 */ 1061 int cscfg_csdev_enable_active_config(struct coresight_device *csdev, 1062 unsigned long cfg_hash, int preset) 1063 { 1064 struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item; 1065 struct cscfg_config_desc *config_desc; 1066 unsigned long flags; 1067 int err = 0; 1068 1069 /* quickly check global count */ 1070 if (!atomic_read(&cscfg_mgr->sys_active_cnt)) 1071 return 0; 1072 1073 /* 1074 * Look for matching configuration - set the active configuration 1075 * context if found. 1076 */ 1077 raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 1078 list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) { 1079 config_desc = config_csdev_item->config_desc; 1080 if (((unsigned long)config_desc->event_ea->var == cfg_hash) && 1081 cscfg_config_desc_get(config_desc)) { 1082 config_csdev_active = config_csdev_item; 1083 csdev->active_cscfg_ctxt = (void *)config_csdev_active; 1084 break; 1085 } 1086 } 1087 raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 1088 1089 /* 1090 * If found, attempt to enable 1091 */ 1092 if (config_csdev_active) { 1093 /* 1094 * Call the generic routine that will program up the internal 1095 * driver structures prior to programming up the hardware. 1096 * This routine takes the driver spinlock saved in the configs. 1097 */ 1098 err = cscfg_csdev_enable_config(config_csdev_active, preset); 1099 if (!err) { 1100 /* 1101 * Successful programming. Check the active_cscfg_ctxt 1102 * pointer to ensure no pre-emption disabled it via 1103 * cscfg_csdev_disable_active_config() before 1104 * we could start. 1105 * 1106 * Set enabled if OK, err if not. 1107 */ 1108 raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 1109 if (csdev->active_cscfg_ctxt) 1110 config_csdev_active->enabled = true; 1111 else 1112 err = -EBUSY; 1113 raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 1114 } 1115 1116 if (err) 1117 cscfg_config_desc_put(config_desc); 1118 } 1119 1120 return err; 1121 } 1122 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config); 1123 1124 /** 1125 * cscfg_csdev_disable_active_config - disable an active config on the device. 1126 * 1127 * Disables the active configuration on the CoreSight device @csdev. 1128 * Disable will save the values of any registers marked in the configurations 1129 * as save on disable. 1130 * 1131 * Should be called after driver hardware disable for the requested device, 1132 * after disabling the physical hardware and reading back registers. 1133 * 1134 * @csdev: The CoreSight device. 1135 */ 1136 void cscfg_csdev_disable_active_config(struct coresight_device *csdev) 1137 { 1138 struct cscfg_config_csdev *config_csdev; 1139 unsigned long flags; 1140 1141 /* 1142 * Check if we have an active config, and that it was successfully enabled. 1143 * If it was not enabled, we have no work to do, otherwise mark as disabled. 1144 * Clear the active config pointer. 1145 */ 1146 raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 1147 config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt; 1148 if (config_csdev) { 1149 if (!config_csdev->enabled) 1150 config_csdev = NULL; 1151 else 1152 config_csdev->enabled = false; 1153 } 1154 csdev->active_cscfg_ctxt = NULL; 1155 raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 1156 1157 /* true if there was an enabled active config */ 1158 if (config_csdev) { 1159 cscfg_csdev_disable_config(config_csdev); 1160 cscfg_config_desc_put(config_csdev->config_desc); 1161 } 1162 } 1163 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config); 1164 1165 /* Initialise system configuration management device. */ 1166 1167 struct device *cscfg_device(void) 1168 { 1169 return cscfg_mgr ? &cscfg_mgr->dev : NULL; 1170 } 1171 1172 /* Must have a release function or the kernel will complain on module unload */ 1173 static void cscfg_dev_release(struct device *dev) 1174 { 1175 mutex_lock(&cscfg_mutex); 1176 kfree(cscfg_mgr); 1177 cscfg_mgr = NULL; 1178 mutex_unlock(&cscfg_mutex); 1179 } 1180 1181 /* a device is needed to "own" some kernel elements such as sysfs entries. */ 1182 static int cscfg_create_device(void) 1183 { 1184 struct device *dev; 1185 int err = -ENOMEM; 1186 1187 mutex_lock(&cscfg_mutex); 1188 if (cscfg_mgr) { 1189 err = -EINVAL; 1190 goto create_dev_exit_unlock; 1191 } 1192 1193 cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL); 1194 if (!cscfg_mgr) 1195 goto create_dev_exit_unlock; 1196 1197 /* initialise the cscfg_mgr structure */ 1198 INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list); 1199 INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list); 1200 INIT_LIST_HEAD(&cscfg_mgr->config_desc_list); 1201 INIT_LIST_HEAD(&cscfg_mgr->load_order_list); 1202 atomic_set(&cscfg_mgr->sys_active_cnt, 0); 1203 cscfg_mgr->load_state = CSCFG_NONE; 1204 1205 /* setup the device */ 1206 dev = cscfg_device(); 1207 dev->release = cscfg_dev_release; 1208 dev->init_name = "cs_system_cfg"; 1209 1210 err = device_register(dev); 1211 if (err) 1212 put_device(dev); 1213 1214 create_dev_exit_unlock: 1215 mutex_unlock(&cscfg_mutex); 1216 return err; 1217 } 1218 1219 /* 1220 * Loading and unloading is generally on user discretion. 1221 * If exiting due to coresight module unload, we need to unload any configurations that remain, 1222 * before we unregister the configfs intrastructure. 1223 * 1224 * Do this by walking the load_owner list and taking appropriate action, depending on the load 1225 * owner type. 1226 */ 1227 static void cscfg_unload_cfgs_on_exit(void) 1228 { 1229 struct cscfg_load_owner_info *owner_info = NULL; 1230 1231 /* 1232 * grab the mutex - even though we are exiting, some configfs files 1233 * may still be live till we dump them, so ensure list data is 1234 * protected from a race condition. 1235 */ 1236 mutex_lock(&cscfg_mutex); 1237 while (!list_empty(&cscfg_mgr->load_order_list)) { 1238 1239 /* remove in reverse order of loading */ 1240 owner_info = list_last_entry(&cscfg_mgr->load_order_list, 1241 struct cscfg_load_owner_info, item); 1242 1243 /* action according to type */ 1244 switch (owner_info->type) { 1245 case CSCFG_OWNER_PRELOAD: 1246 /* 1247 * preloaded descriptors are statically allocated in 1248 * this module - just need to unload dynamic items from 1249 * csdev lists, and remove from configfs directories. 1250 */ 1251 pr_info("cscfg: unloading preloaded configurations\n"); 1252 break; 1253 1254 case CSCFG_OWNER_MODULE: 1255 /* 1256 * this is an error - the loadable module must have been unloaded prior 1257 * to the coresight module unload. Therefore that module has not 1258 * correctly unloaded configs in its own exit code. 1259 * Nothing to do other than emit an error string as the static descriptor 1260 * references we need to unload will have disappeared with the module. 1261 */ 1262 pr_err("cscfg: ERROR: prior module failed to unload configuration\n"); 1263 goto list_remove; 1264 } 1265 1266 /* remove from configfs - outside the scope of the list mutex */ 1267 mutex_unlock(&cscfg_mutex); 1268 cscfg_fs_unregister_cfgs_feats(owner_info); 1269 mutex_lock(&cscfg_mutex); 1270 1271 /* Next unload from csdev lists. */ 1272 cscfg_unload_owned_cfgs_feats(owner_info); 1273 1274 list_remove: 1275 /* remove from load order list */ 1276 list_del(&owner_info->item); 1277 } 1278 mutex_unlock(&cscfg_mutex); 1279 } 1280 1281 static void cscfg_clear_device(void) 1282 { 1283 cscfg_unload_cfgs_on_exit(); 1284 cscfg_configfs_release(cscfg_mgr); 1285 device_unregister(cscfg_device()); 1286 } 1287 1288 /* Initialise system config management API device */ 1289 int __init cscfg_init(void) 1290 { 1291 int err = 0; 1292 1293 /* create the device and init cscfg_mgr */ 1294 err = cscfg_create_device(); 1295 if (err) 1296 return err; 1297 1298 /* initialise configfs subsystem */ 1299 err = cscfg_configfs_init(cscfg_mgr); 1300 if (err) 1301 goto exit_err; 1302 1303 /* preload built-in configurations */ 1304 err = cscfg_preload(THIS_MODULE); 1305 if (err) 1306 goto exit_err; 1307 1308 dev_info(cscfg_device(), "CoreSight Configuration manager initialised"); 1309 return 0; 1310 1311 exit_err: 1312 cscfg_clear_device(); 1313 return err; 1314 } 1315 1316 void cscfg_exit(void) 1317 { 1318 cscfg_clear_device(); 1319 } 1320