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 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 */ 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 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 */ 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 254 /* add feature to any matching registered devices */ 255 err = cscfg_add_feat_to_csdevs(feat_desc); 256 if (err) 257 return err; 258 259 list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list); 260 return 0; 261 } 262 263 /* 264 * load config into the system - validate used features exist then add to 265 * config list. 266 */ 267 static int cscfg_load_config(struct cscfg_config_desc *config_desc) 268 { 269 int err; 270 271 /* validate features are present */ 272 err = cscfg_check_feat_for_cfg(config_desc); 273 if (err) 274 return err; 275 276 /* add config to any matching registered device */ 277 err = cscfg_add_cfg_to_csdevs(config_desc); 278 if (err) 279 return err; 280 281 /* add config to perf fs to allow selection */ 282 err = etm_perf_add_symlink_cscfg(cscfg_device(), config_desc); 283 if (err) 284 return err; 285 286 list_add(&config_desc->item, &cscfg_mgr->config_desc_list); 287 atomic_set(&config_desc->active_cnt, 0); 288 return 0; 289 } 290 291 /* get a feature descriptor by name */ 292 const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name) 293 { 294 const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item; 295 296 mutex_lock(&cscfg_mutex); 297 298 list_for_each_entry(feat_desc_item, &cscfg_mgr->feat_desc_list, item) { 299 if (strcmp(feat_desc_item->name, name) == 0) { 300 feat_desc = feat_desc_item; 301 break; 302 } 303 } 304 305 mutex_unlock(&cscfg_mutex); 306 return feat_desc; 307 } 308 309 /* called with cscfg_mutex held */ 310 static struct cscfg_feature_csdev * 311 cscfg_csdev_get_feat_from_desc(struct coresight_device *csdev, 312 struct cscfg_feature_desc *feat_desc) 313 { 314 struct cscfg_feature_csdev *feat_csdev; 315 316 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) { 317 if (feat_csdev->feat_desc == feat_desc) 318 return feat_csdev; 319 } 320 return NULL; 321 } 322 323 int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc, 324 int param_idx, u64 value) 325 { 326 int err = 0; 327 struct cscfg_feature_csdev *feat_csdev; 328 struct cscfg_registered_csdev *csdev_item; 329 330 mutex_lock(&cscfg_mutex); 331 332 /* check if any config active & return busy */ 333 if (atomic_read(&cscfg_mgr->sys_active_cnt)) { 334 err = -EBUSY; 335 goto unlock_exit; 336 } 337 338 /* set the value */ 339 if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) { 340 err = -EINVAL; 341 goto unlock_exit; 342 } 343 feat_desc->params_desc[param_idx].value = value; 344 345 /* update loaded instances.*/ 346 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 347 feat_csdev = cscfg_csdev_get_feat_from_desc(csdev_item->csdev, feat_desc); 348 if (feat_csdev) 349 feat_csdev->params_csdev[param_idx].current_value = value; 350 } 351 352 unlock_exit: 353 mutex_unlock(&cscfg_mutex); 354 return err; 355 } 356 357 /** 358 * cscfg_load_config_sets - API function to load feature and config sets. 359 * 360 * Take a 0 terminated array of feature descriptors and/or configuration 361 * descriptors and load into the system. 362 * Features are loaded first to ensure configuration dependencies can be met. 363 * 364 * @config_descs: 0 terminated array of configuration descriptors. 365 * @feat_descs: 0 terminated array of feature descriptors. 366 */ 367 int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, 368 struct cscfg_feature_desc **feat_descs) 369 { 370 int err, i = 0; 371 372 mutex_lock(&cscfg_mutex); 373 374 /* load features first */ 375 if (feat_descs) { 376 while (feat_descs[i]) { 377 err = cscfg_load_feat(feat_descs[i]); 378 if (!err) 379 err = cscfg_configfs_add_feature(feat_descs[i]); 380 if (err) { 381 pr_err("coresight-syscfg: Failed to load feature %s\n", 382 feat_descs[i]->name); 383 goto exit_unlock; 384 } 385 i++; 386 } 387 } 388 389 /* next any configurations to check feature dependencies */ 390 i = 0; 391 if (config_descs) { 392 while (config_descs[i]) { 393 err = cscfg_load_config(config_descs[i]); 394 if (!err) 395 err = cscfg_configfs_add_config(config_descs[i]); 396 if (err) { 397 pr_err("coresight-syscfg: Failed to load configuration %s\n", 398 config_descs[i]->name); 399 goto exit_unlock; 400 } 401 i++; 402 } 403 } 404 405 exit_unlock: 406 mutex_unlock(&cscfg_mutex); 407 return err; 408 } 409 EXPORT_SYMBOL_GPL(cscfg_load_config_sets); 410 411 /* Handle coresight device registration and add configs and features to devices */ 412 413 /* iterate through config lists and load matching configs to device */ 414 static int cscfg_add_cfgs_csdev(struct coresight_device *csdev) 415 { 416 struct cscfg_config_desc *config_desc; 417 int err = 0; 418 419 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 420 err = cscfg_add_csdev_cfg(csdev, config_desc); 421 if (err) 422 break; 423 } 424 return err; 425 } 426 427 /* iterate through feature lists and load matching features to device */ 428 static int cscfg_add_feats_csdev(struct coresight_device *csdev, 429 u32 match_flags, 430 struct cscfg_csdev_feat_ops *ops) 431 { 432 struct cscfg_feature_desc *feat_desc; 433 int err = 0; 434 435 if (!ops->load_feat) 436 return -EINVAL; 437 438 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) { 439 if (feat_desc->match_flags & match_flags) { 440 err = cscfg_load_feat_csdev(csdev, feat_desc, ops); 441 if (err) 442 break; 443 } 444 } 445 return err; 446 } 447 448 /* Add coresight device to list and copy its matching info */ 449 static int cscfg_list_add_csdev(struct coresight_device *csdev, 450 u32 match_flags, 451 struct cscfg_csdev_feat_ops *ops) 452 { 453 struct cscfg_registered_csdev *csdev_item; 454 455 /* allocate the list entry structure */ 456 csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL); 457 if (!csdev_item) 458 return -ENOMEM; 459 460 csdev_item->csdev = csdev; 461 csdev_item->match_flags = match_flags; 462 csdev_item->ops.load_feat = ops->load_feat; 463 list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list); 464 465 INIT_LIST_HEAD(&csdev->feature_csdev_list); 466 INIT_LIST_HEAD(&csdev->config_csdev_list); 467 spin_lock_init(&csdev->cscfg_csdev_lock); 468 469 return 0; 470 } 471 472 /* remove a coresight device from the list and free data */ 473 static void cscfg_list_remove_csdev(struct coresight_device *csdev) 474 { 475 struct cscfg_registered_csdev *csdev_item, *tmp; 476 477 list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) { 478 if (csdev_item->csdev == csdev) { 479 list_del(&csdev_item->item); 480 kfree(csdev_item); 481 break; 482 } 483 } 484 } 485 486 /** 487 * cscfg_register_csdev - register a coresight device with the syscfg manager. 488 * 489 * Registers the coresight device with the system. @match_flags used to check 490 * if the device is a match for registered features. Any currently registered 491 * configurations and features that match the device will be loaded onto it. 492 * 493 * @csdev: The coresight device to register. 494 * @match_flags: Matching information to load features. 495 * @ops: Standard operations supported by the device. 496 */ 497 int cscfg_register_csdev(struct coresight_device *csdev, 498 u32 match_flags, 499 struct cscfg_csdev_feat_ops *ops) 500 { 501 int ret = 0; 502 503 mutex_lock(&cscfg_mutex); 504 505 /* add device to list of registered devices */ 506 ret = cscfg_list_add_csdev(csdev, match_flags, ops); 507 if (ret) 508 goto reg_csdev_unlock; 509 510 /* now load any registered features and configs matching the device. */ 511 ret = cscfg_add_feats_csdev(csdev, match_flags, ops); 512 if (ret) { 513 cscfg_list_remove_csdev(csdev); 514 goto reg_csdev_unlock; 515 } 516 517 ret = cscfg_add_cfgs_csdev(csdev); 518 if (ret) { 519 cscfg_list_remove_csdev(csdev); 520 goto reg_csdev_unlock; 521 } 522 523 pr_info("CSCFG registered %s", dev_name(&csdev->dev)); 524 525 reg_csdev_unlock: 526 mutex_unlock(&cscfg_mutex); 527 return ret; 528 } 529 EXPORT_SYMBOL_GPL(cscfg_register_csdev); 530 531 /** 532 * cscfg_unregister_csdev - remove coresight device from syscfg manager. 533 * 534 * @csdev: Device to remove. 535 */ 536 void cscfg_unregister_csdev(struct coresight_device *csdev) 537 { 538 mutex_lock(&cscfg_mutex); 539 cscfg_list_remove_csdev(csdev); 540 mutex_unlock(&cscfg_mutex); 541 } 542 EXPORT_SYMBOL_GPL(cscfg_unregister_csdev); 543 544 /** 545 * cscfg_csdev_reset_feats - reset features for a CoreSight device. 546 * 547 * Resets all parameters and register values for any features loaded 548 * into @csdev to their default values. 549 * 550 * @csdev: The CoreSight device. 551 */ 552 void cscfg_csdev_reset_feats(struct coresight_device *csdev) 553 { 554 struct cscfg_feature_csdev *feat_csdev; 555 unsigned long flags; 556 557 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 558 if (list_empty(&csdev->feature_csdev_list)) 559 goto unlock_exit; 560 561 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) 562 cscfg_reset_feat(feat_csdev); 563 564 unlock_exit: 565 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 566 } 567 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats); 568 569 /** 570 * cscfg_activate_config - Mark a configuration descriptor as active. 571 * 572 * This will be seen when csdev devices are enabled in the system. 573 * Only activated configurations can be enabled on individual devices. 574 * Activation protects the configuration from alteration or removal while 575 * active. 576 * 577 * Selection by hash value - generated from the configuration name when it 578 * was loaded and added to the cs_etm/configurations file system for selection 579 * by perf. 580 * 581 * Increments the configuration descriptor active count and the global active 582 * count. 583 * 584 * @cfg_hash: Hash value of the selected configuration name. 585 */ 586 int cscfg_activate_config(unsigned long cfg_hash) 587 { 588 struct cscfg_config_desc *config_desc; 589 int err = -EINVAL; 590 591 mutex_lock(&cscfg_mutex); 592 593 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 594 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 595 /* 596 * increment the global active count - control changes to 597 * active configurations 598 */ 599 atomic_inc(&cscfg_mgr->sys_active_cnt); 600 601 /* 602 * mark the descriptor as active so enable config on a 603 * device instance will use it 604 */ 605 atomic_inc(&config_desc->active_cnt); 606 607 err = 0; 608 dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name); 609 break; 610 } 611 } 612 mutex_unlock(&cscfg_mutex); 613 614 return err; 615 } 616 EXPORT_SYMBOL_GPL(cscfg_activate_config); 617 618 /** 619 * cscfg_deactivate_config - Mark a config descriptor as inactive. 620 * 621 * Decrement the configuration and global active counts. 622 * 623 * @cfg_hash: Hash value of the selected configuration name. 624 */ 625 void cscfg_deactivate_config(unsigned long cfg_hash) 626 { 627 struct cscfg_config_desc *config_desc; 628 629 mutex_lock(&cscfg_mutex); 630 631 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 632 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 633 atomic_dec(&config_desc->active_cnt); 634 atomic_dec(&cscfg_mgr->sys_active_cnt); 635 dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); 636 break; 637 } 638 } 639 mutex_unlock(&cscfg_mutex); 640 } 641 EXPORT_SYMBOL_GPL(cscfg_deactivate_config); 642 643 /** 644 * cscfg_csdev_enable_active_config - Enable matching active configuration for device. 645 * 646 * Enables the configuration selected by @cfg_hash if the configuration is supported 647 * on the device and has been activated. 648 * 649 * If active and supported the CoreSight device @csdev will be programmed with the 650 * configuration, using @preset parameters. 651 * 652 * Should be called before driver hardware enable for the requested device, prior to 653 * programming and enabling the physical hardware. 654 * 655 * @csdev: CoreSight device to program. 656 * @cfg_hash: Selector for the configuration. 657 * @preset: Preset parameter values to use, 0 for current / default values. 658 */ 659 int cscfg_csdev_enable_active_config(struct coresight_device *csdev, 660 unsigned long cfg_hash, int preset) 661 { 662 struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item; 663 const struct cscfg_config_desc *config_desc; 664 unsigned long flags; 665 int err = 0; 666 667 /* quickly check global count */ 668 if (!atomic_read(&cscfg_mgr->sys_active_cnt)) 669 return 0; 670 671 /* 672 * Look for matching configuration - set the active configuration 673 * context if found. 674 */ 675 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 676 list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) { 677 config_desc = config_csdev_item->config_desc; 678 if ((atomic_read(&config_desc->active_cnt)) && 679 ((unsigned long)config_desc->event_ea->var == cfg_hash)) { 680 config_csdev_active = config_csdev_item; 681 csdev->active_cscfg_ctxt = (void *)config_csdev_active; 682 break; 683 } 684 } 685 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 686 687 /* 688 * If found, attempt to enable 689 */ 690 if (config_csdev_active) { 691 /* 692 * Call the generic routine that will program up the internal 693 * driver structures prior to programming up the hardware. 694 * This routine takes the driver spinlock saved in the configs. 695 */ 696 err = cscfg_csdev_enable_config(config_csdev_active, preset); 697 if (!err) { 698 /* 699 * Successful programming. Check the active_cscfg_ctxt 700 * pointer to ensure no pre-emption disabled it via 701 * cscfg_csdev_disable_active_config() before 702 * we could start. 703 * 704 * Set enabled if OK, err if not. 705 */ 706 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 707 if (csdev->active_cscfg_ctxt) 708 config_csdev_active->enabled = true; 709 else 710 err = -EBUSY; 711 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 712 } 713 } 714 return err; 715 } 716 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config); 717 718 /** 719 * cscfg_csdev_disable_active_config - disable an active config on the device. 720 * 721 * Disables the active configuration on the CoreSight device @csdev. 722 * Disable will save the values of any registers marked in the configurations 723 * as save on disable. 724 * 725 * Should be called after driver hardware disable for the requested device, 726 * after disabling the physical hardware and reading back registers. 727 * 728 * @csdev: The CoreSight device. 729 */ 730 void cscfg_csdev_disable_active_config(struct coresight_device *csdev) 731 { 732 struct cscfg_config_csdev *config_csdev; 733 unsigned long flags; 734 735 /* 736 * Check if we have an active config, and that it was successfully enabled. 737 * If it was not enabled, we have no work to do, otherwise mark as disabled. 738 * Clear the active config pointer. 739 */ 740 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags); 741 config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt; 742 if (config_csdev) { 743 if (!config_csdev->enabled) 744 config_csdev = NULL; 745 else 746 config_csdev->enabled = false; 747 } 748 csdev->active_cscfg_ctxt = NULL; 749 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags); 750 751 /* true if there was an enabled active config */ 752 if (config_csdev) 753 cscfg_csdev_disable_config(config_csdev); 754 } 755 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config); 756 757 /* Initialise system configuration management device. */ 758 759 struct device *cscfg_device(void) 760 { 761 return cscfg_mgr ? &cscfg_mgr->dev : NULL; 762 } 763 764 /* Must have a release function or the kernel will complain on module unload */ 765 static void cscfg_dev_release(struct device *dev) 766 { 767 kfree(cscfg_mgr); 768 cscfg_mgr = NULL; 769 } 770 771 /* a device is needed to "own" some kernel elements such as sysfs entries. */ 772 static int cscfg_create_device(void) 773 { 774 struct device *dev; 775 int err = -ENOMEM; 776 777 mutex_lock(&cscfg_mutex); 778 if (cscfg_mgr) { 779 err = -EINVAL; 780 goto create_dev_exit_unlock; 781 } 782 783 cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL); 784 if (!cscfg_mgr) 785 goto create_dev_exit_unlock; 786 787 /* setup the device */ 788 dev = cscfg_device(); 789 dev->release = cscfg_dev_release; 790 dev->init_name = "cs_system_cfg"; 791 792 err = device_register(dev); 793 if (err) 794 cscfg_dev_release(dev); 795 796 create_dev_exit_unlock: 797 mutex_unlock(&cscfg_mutex); 798 return err; 799 } 800 801 static void cscfg_clear_device(void) 802 { 803 struct cscfg_config_desc *cfg_desc; 804 805 mutex_lock(&cscfg_mutex); 806 list_for_each_entry(cfg_desc, &cscfg_mgr->config_desc_list, item) { 807 etm_perf_del_symlink_cscfg(cfg_desc); 808 } 809 cscfg_configfs_release(cscfg_mgr); 810 device_unregister(cscfg_device()); 811 mutex_unlock(&cscfg_mutex); 812 } 813 814 /* Initialise system config management API device */ 815 int __init cscfg_init(void) 816 { 817 int err = 0; 818 819 err = cscfg_create_device(); 820 if (err) 821 return err; 822 823 err = cscfg_configfs_init(cscfg_mgr); 824 if (err) 825 goto exit_err; 826 827 INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list); 828 INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list); 829 INIT_LIST_HEAD(&cscfg_mgr->config_desc_list); 830 atomic_set(&cscfg_mgr->sys_active_cnt, 0); 831 832 /* preload built-in configurations */ 833 err = cscfg_preload(); 834 if (err) 835 goto exit_err; 836 837 dev_info(cscfg_device(), "CoreSight Configuration manager initialised"); 838 return 0; 839 840 exit_err: 841 cscfg_clear_device(); 842 return err; 843 } 844 845 void cscfg_exit(void) 846 { 847 cscfg_clear_device(); 848 } 849