Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'coresight-next-v5.17' of gitolite.kernel.org:pub/scm/linux/kernel/git/coresight/linux into char-misc-next

Mathieu writes:

Coresight changes for v5.17

This pull request includes:

- A patch that uses devm_bitmap_zalloc() instead of the open-coded
equivalent.

- Work to make coresight complex configuration loadable via modules.

- Some coresight documentation updates.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>

* tag 'coresight-next-v5.17' of gitolite.kernel.org:pub/scm/linux/kernel/git/coresight/linux:
coresight: core: Fix typo in a comment
Documentation: coresight: Update coresight configuration docs
coresight: configfs: Allow configfs to activate configuration
coresight: syscfg: Example CoreSight configuration loadable module
coresight: syscfg: Update load API for config loadable modules
coresight: configuration: Update API to permit dynamic load/unload
coresight: configuration: Update API to introduce load owner concept
Documentation: coresight: Fix documentation issue
coresight: Use devm_bitmap_zalloc when applicable

+595 -57
+64 -14
Documentation/trace/coresight/coresight-config.rst
··· 155 155 autofdo 156 156 $ cd autofdo/ 157 157 $ ls 158 - description preset1 preset3 preset5 preset7 preset9 159 - feature_refs preset2 preset4 preset6 preset8 158 + description feature_refs preset1 preset3 preset5 preset7 preset9 159 + enable preset preset2 preset4 preset6 preset8 160 160 $ cat description 161 161 Setup ETMs with strobing for autofdo 162 162 $ cat feature_refs 163 163 strobing 164 164 165 - Each preset declared has a preset<n> subdirectory declared. The values for 165 + Each preset declared has a 'preset<n>' subdirectory declared. The values for 166 166 the preset can be examined:: 167 167 168 168 $ cat preset1/values 169 169 strobing.window = 0x1388 strobing.period = 0x2 170 170 $ cat preset2/values 171 171 strobing.window = 0x1388 strobing.period = 0x4 172 + 173 + The 'enable' and 'preset' files allow the control of a configuration when 174 + using CoreSight with sysfs. 172 175 173 176 The features referenced by the configuration can be examined in the features 174 177 directory:: ··· 214 211 be selected when running trace under perf:: 215 212 216 213 $ ls /sys/devices/cs_etm 217 - configurations format perf_event_mux_interval_ms sinks type 218 - events nr_addr_filters power 214 + cpu0 cpu2 events nr_addr_filters power subsystem uevent 215 + cpu1 cpu3 format perf_event_mux_interval_ms sinks type 219 216 220 - Key directories here are 'configurations' - which lists the loaded 221 - configurations, and 'events' - a generic perf directory which allows 222 - selection on the perf command line.:: 217 + The key directory here is 'events' - a generic perf directory which allows 218 + selection on the perf command line. As with the sinks entries, this provides 219 + a hash of the configuration name. 223 220 224 - $ ls configurations/ 225 - autofdo 226 - $ cat configurations/autofdo 227 - 0xa7c3dddd 228 - 229 - As with the sinks entries, this provides a hash of the configuration name. 230 221 The entry in the 'events' directory uses perfs built in syntax generator 231 222 to substitute the syntax for the name when evaluating the command:: 232 223 ··· 239 242 240 243 When configurations are selected in this way, then the trace sink used is 241 244 automatically selected. 245 + 246 + Using Configurations in sysfs 247 + ============================= 248 + 249 + Coresight can be controlled using sysfs. When this is in use then a configuration 250 + can be made active for the devices that are used in the sysfs session. 251 + 252 + In a configuration there are 'enable' and 'preset' files. 253 + 254 + To enable a configuration for use with sysfs:: 255 + 256 + $ cd configurations/autofdo 257 + $ echo 1 > enable 258 + 259 + This will then use any default parameter values in the features - which can be 260 + adjusted as described above. 261 + 262 + To use a preset<n> set of parameter values:: 263 + 264 + $ echo 3 > preset 265 + 266 + This will select preset3 for the configuration. 267 + The valid values for preset are 0 - to deselect presets, and any value of 268 + <n> where a preset<n> sub-directory is present. 269 + 270 + Note that the active sysfs configuration is a global parameter, therefore 271 + only a single configuration can be active for sysfs at any one time. 272 + Attempting to enable a second configuration will result in an error. 273 + Additionally, attempting to disable the configuration while in use will 274 + also result in an error. 275 + 276 + The use of the active configuration by sysfs is independent of the configuration 277 + used in perf. 278 + 279 + 280 + Creating and Loading Custom Configurations 281 + ========================================== 282 + 283 + Custom configurations and / or features can be dynamically loaded into the 284 + system by using a loadable module. 285 + 286 + An example of a custom configuration is found in ./samples/coresight. 287 + 288 + This creates a new configuration that uses the existing built in 289 + strobing feature, but provides a different set of presets. 290 + 291 + When the module is loaded, then the configuration appears in the configfs 292 + file system and is selectable in the same way as the built in configuration 293 + described above. 294 + 295 + Configurations can use previously loaded features. The system will ensure 296 + that it is not possible to unload a feature that is currently in use, by 297 + enforcing the unload order as the strict reverse of the load order.
+1
MAINTAINERS
··· 1890 1890 F: drivers/hwtracing/coresight/* 1891 1891 F: include/dt-bindings/arm/coresight-cti-dt.h 1892 1892 F: include/linux/coresight* 1893 + F: samples/coresight/* 1893 1894 F: tools/perf/arch/arm/util/auxtrace.c 1894 1895 F: tools/perf/arch/arm/util/cs-etm.c 1895 1896 F: tools/perf/arch/arm/util/cs-etm.h
+7 -2
drivers/hwtracing/coresight/coresight-cfg-preload.c
··· 24 24 NULL 25 25 }; 26 26 27 + static struct cscfg_load_owner_info preload_owner = { 28 + .type = CSCFG_OWNER_PRELOAD, 29 + }; 30 + 27 31 /* preload called on initialisation */ 28 - int cscfg_preload(void) 32 + int cscfg_preload(void *owner_handle) 29 33 { 30 - return cscfg_load_config_sets(preload_cfgs, preload_feats); 34 + preload_owner.owner_handle = owner_handle; 35 + return cscfg_load_config_sets(preload_cfgs, preload_feats, &preload_owner); 31 36 }
+8 -1
drivers/hwtracing/coresight/coresight-config.h
··· 97 97 * @params_desc: array of parameters used. 98 98 * @nr_regs: number of registers used. 99 99 * @regs_desc: array of registers used. 100 + * @load_owner: handle to load owner for dynamic load and unload of features. 101 + * @fs_group: reference to configfs group for dynamic unload. 100 102 */ 101 103 struct cscfg_feature_desc { 102 104 const char *name; ··· 109 107 struct cscfg_parameter_desc *params_desc; 110 108 int nr_regs; 111 109 struct cscfg_regval_desc *regs_desc; 110 + void *load_owner; 111 + struct config_group *fs_group; 112 112 }; 113 113 114 114 /** ··· 132 128 * @presets: Array of preset values. 133 129 * @event_ea: Extended attribute for perf event value 134 130 * @active_cnt: ref count for activate on this configuration. 135 - * 131 + * @load_owner: handle to load owner for dynamic load and unload of configs. 132 + * @fs_group: reference to configfs group for dynamic unload. 136 133 */ 137 134 struct cscfg_config_desc { 138 135 const char *name; ··· 146 141 const u64 *presets; /* nr_presets * nr_total_params */ 147 142 struct dev_ext_attribute *event_ea; 148 143 atomic_t active_cnt; 144 + void *load_owner; 145 + struct config_group *fs_group; 149 146 }; 150 147 151 148 /**
+1 -1
drivers/hwtracing/coresight/coresight-core.c
··· 729 729 * coresight_grab_device - Power up this device and any of the helper 730 730 * devices connected to it for trace operation. Since the helper devices 731 731 * don't appear on the trace path, they should be handled along with the 732 - * the master device. 732 + * master device. 733 733 */ 734 734 static int coresight_grab_device(struct coresight_device *csdev) 735 735 {
+10 -1
drivers/hwtracing/coresight/coresight-etm4x-core.c
··· 722 722 { 723 723 struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 724 724 struct etm4_enable_arg arg = { }; 725 - int ret; 725 + unsigned long cfg_hash; 726 + int ret, preset; 727 + 728 + /* enable any config activated by configfs */ 729 + cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset); 730 + if (cfg_hash) { 731 + ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset); 732 + if (ret) 733 + return ret; 734 + } 726 735 727 736 spin_lock(&drvdata->spinlock); 728 737
+3 -7
drivers/hwtracing/coresight/coresight-stm.c
··· 856 856 { 857 857 int ret; 858 858 void __iomem *base; 859 - unsigned long *guaranteed; 860 859 struct device *dev = &adev->dev; 861 860 struct coresight_platform_data *pdata = NULL; 862 861 struct stm_drvdata *drvdata; 863 862 struct resource *res = &adev->res; 864 863 struct resource ch_res; 865 - size_t bitmap_size; 866 864 struct coresight_desc desc = { 0 }; 867 865 868 866 desc.name = coresight_alloc_device_name(&stm_devs, dev); ··· 902 904 else 903 905 drvdata->numsp = stm_num_stimulus_port(drvdata); 904 906 905 - bitmap_size = BITS_TO_LONGS(drvdata->numsp) * sizeof(long); 906 - 907 - guaranteed = devm_kzalloc(dev, bitmap_size, GFP_KERNEL); 908 - if (!guaranteed) 907 + drvdata->chs.guaranteed = devm_bitmap_zalloc(dev, drvdata->numsp, 908 + GFP_KERNEL); 909 + if (!drvdata->chs.guaranteed) 909 910 return -ENOMEM; 910 - drvdata->chs.guaranteed = guaranteed; 911 911 912 912 spin_lock_init(&drvdata->spinlock); 913 913
+87
drivers/hwtracing/coresight/coresight-syscfg-configfs.c
··· 6 6 7 7 #include <linux/configfs.h> 8 8 9 + #include "coresight-config.h" 9 10 #include "coresight-syscfg-configfs.h" 10 11 11 12 /* create a default ci_type. */ ··· 88 87 } 89 88 CONFIGFS_ATTR_RO(cscfg_cfg_, values); 90 89 90 + static ssize_t cscfg_cfg_enable_show(struct config_item *item, char *page) 91 + { 92 + struct cscfg_fs_config *fs_config = container_of(to_config_group(item), 93 + struct cscfg_fs_config, group); 94 + 95 + return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->active); 96 + } 97 + 98 + static ssize_t cscfg_cfg_enable_store(struct config_item *item, 99 + const char *page, size_t count) 100 + { 101 + struct cscfg_fs_config *fs_config = container_of(to_config_group(item), 102 + struct cscfg_fs_config, group); 103 + int err; 104 + bool val; 105 + 106 + err = kstrtobool(page, &val); 107 + if (!err) 108 + err = cscfg_config_sysfs_activate(fs_config->config_desc, val); 109 + if (!err) { 110 + fs_config->active = val; 111 + if (val) 112 + cscfg_config_sysfs_set_preset(fs_config->preset); 113 + } 114 + return err ? err : count; 115 + } 116 + CONFIGFS_ATTR(cscfg_cfg_, enable); 117 + 118 + static ssize_t cscfg_cfg_preset_show(struct config_item *item, char *page) 119 + { 120 + struct cscfg_fs_config *fs_config = container_of(to_config_group(item), 121 + struct cscfg_fs_config, group); 122 + 123 + return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->preset); 124 + } 125 + 126 + static ssize_t cscfg_cfg_preset_store(struct config_item *item, 127 + const char *page, size_t count) 128 + { 129 + struct cscfg_fs_config *fs_config = container_of(to_config_group(item), 130 + struct cscfg_fs_config, group); 131 + int preset, err; 132 + 133 + err = kstrtoint(page, 0, &preset); 134 + if (!err) { 135 + /* 136 + * presets start at 1, and go up to max (15), 137 + * but the config may provide fewer. 138 + */ 139 + if ((preset < 1) || (preset > fs_config->config_desc->nr_presets)) 140 + err = -EINVAL; 141 + } 142 + 143 + if (!err) { 144 + /* set new value */ 145 + fs_config->preset = preset; 146 + /* set on system if active */ 147 + if (fs_config->active) 148 + cscfg_config_sysfs_set_preset(fs_config->preset); 149 + } 150 + return err ? err : count; 151 + } 152 + CONFIGFS_ATTR(cscfg_cfg_, preset); 153 + 91 154 static struct configfs_attribute *cscfg_config_view_attrs[] = { 92 155 &cscfg_cfg_attr_description, 93 156 &cscfg_cfg_attr_feature_refs, 157 + &cscfg_cfg_attr_enable, 158 + &cscfg_cfg_attr_preset, 94 159 NULL, 95 160 }; 96 161 ··· 401 334 if (IS_ERR(new_group)) 402 335 return PTR_ERR(new_group); 403 336 err = configfs_register_group(&cscfg_configs_grp, new_group); 337 + if (!err) 338 + config_desc->fs_group = new_group; 404 339 return err; 340 + } 341 + 342 + void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc) 343 + { 344 + if (config_desc->fs_group) { 345 + configfs_unregister_group(config_desc->fs_group); 346 + config_desc->fs_group = NULL; 347 + } 405 348 } 406 349 407 350 static struct config_item_type cscfg_features_type = { ··· 435 358 if (IS_ERR(new_group)) 436 359 return PTR_ERR(new_group); 437 360 err = configfs_register_group(&cscfg_features_grp, new_group); 361 + if (!err) 362 + feat_desc->fs_group = new_group; 438 363 return err; 364 + } 365 + 366 + void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc) 367 + { 368 + if (feat_desc->fs_group) { 369 + configfs_unregister_group(feat_desc->fs_group); 370 + feat_desc->fs_group = NULL; 371 + } 439 372 } 440 373 441 374 int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr)
+4
drivers/hwtracing/coresight/coresight-syscfg-configfs.h
··· 15 15 struct cscfg_fs_config { 16 16 struct cscfg_config_desc *config_desc; 17 17 struct config_group group; 18 + bool active; 19 + int preset; 18 20 }; 19 21 20 22 /* container for feature view */ ··· 43 41 void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr); 44 42 int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc); 45 43 int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc); 44 + void cscfg_configfs_del_config(struct cscfg_config_desc *config_desc); 45 + void cscfg_configfs_del_feature(struct cscfg_feature_desc *feat_desc); 46 46 47 47 #endif /* CORESIGHT_SYSCFG_CONFIGFS_H */
+287 -28
drivers/hwtracing/coresight/coresight-syscfg.c
··· 250 250 static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc) 251 251 { 252 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 + } 253 260 254 261 /* add feature to any matching registered devices */ 255 262 err = cscfg_add_feat_to_csdevs(feat_desc); ··· 274 267 static int cscfg_load_config(struct cscfg_config_desc *config_desc) 275 268 { 276 269 int err; 270 + struct cscfg_config_desc *config_desc_exist; 271 + 272 + /* new configuration must have a unique name */ 273 + list_for_each_entry(config_desc_exist, &cscfg_mgr->config_desc_list, item) { 274 + if (!strcmp(config_desc_exist->name, config_desc->name)) 275 + return -EEXIST; 276 + } 277 277 278 278 /* validate features are present */ 279 279 err = cscfg_check_feat_for_cfg(config_desc); ··· 368 354 return err; 369 355 } 370 356 357 + /* 358 + * Conditionally up reference count on owner to prevent unload. 359 + * 360 + * module loaded configs need to be locked in to prevent premature unload. 361 + */ 362 + static int cscfg_owner_get(struct cscfg_load_owner_info *owner_info) 363 + { 364 + if ((owner_info->type == CSCFG_OWNER_MODULE) && 365 + (!try_module_get(owner_info->owner_handle))) 366 + return -EINVAL; 367 + return 0; 368 + } 369 + 370 + /* conditionally lower ref count on an owner */ 371 + static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info) 372 + { 373 + if (owner_info->type == CSCFG_OWNER_MODULE) 374 + module_put(owner_info->owner_handle); 375 + } 376 + 377 + static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner) 378 + { 379 + struct cscfg_config_csdev *config_csdev, *tmp; 380 + 381 + if (list_empty(&csdev->config_csdev_list)) 382 + return; 383 + 384 + list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) { 385 + if (config_csdev->config_desc->load_owner == load_owner) 386 + list_del(&config_csdev->node); 387 + } 388 + } 389 + 390 + static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner) 391 + { 392 + struct cscfg_feature_csdev *feat_csdev, *tmp; 393 + 394 + if (list_empty(&csdev->feature_csdev_list)) 395 + return; 396 + 397 + list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) { 398 + if (feat_csdev->feat_desc->load_owner == load_owner) 399 + list_del(&feat_csdev->node); 400 + } 401 + } 402 + 403 + /* 404 + * removal is relatively easy - just remove from all lists, anything that 405 + * matches the owner. Memory for the descriptors will be managed by the owner, 406 + * memory for the csdev items is devm_ allocated with the individual csdev 407 + * devices. 408 + */ 409 + static void cscfg_unload_owned_cfgs_feats(void *load_owner) 410 + { 411 + struct cscfg_config_desc *config_desc, *cfg_tmp; 412 + struct cscfg_feature_desc *feat_desc, *feat_tmp; 413 + struct cscfg_registered_csdev *csdev_item; 414 + 415 + /* remove from each csdev instance feature and config lists */ 416 + list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) { 417 + /* 418 + * for each csdev, check the loaded lists and remove if 419 + * referenced descriptor is owned 420 + */ 421 + cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner); 422 + cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner); 423 + } 424 + 425 + /* remove from the config descriptor lists */ 426 + list_for_each_entry_safe(config_desc, cfg_tmp, &cscfg_mgr->config_desc_list, item) { 427 + if (config_desc->load_owner == load_owner) { 428 + cscfg_configfs_del_config(config_desc); 429 + etm_perf_del_symlink_cscfg(config_desc); 430 + list_del(&config_desc->item); 431 + } 432 + } 433 + 434 + /* remove from the feature descriptor lists */ 435 + list_for_each_entry_safe(feat_desc, feat_tmp, &cscfg_mgr->feat_desc_list, item) { 436 + if (feat_desc->load_owner == load_owner) { 437 + cscfg_configfs_del_feature(feat_desc); 438 + list_del(&feat_desc->item); 439 + } 440 + } 441 + } 442 + 371 443 /** 372 444 * cscfg_load_config_sets - API function to load feature and config sets. 373 445 * ··· 461 361 * descriptors and load into the system. 462 362 * Features are loaded first to ensure configuration dependencies can be met. 463 363 * 364 + * To facilitate dynamic loading and unloading, features and configurations 365 + * have a "load_owner", to allow later unload by the same owner. An owner may 366 + * be a loadable module or configuration dynamically created via configfs. 367 + * As later loaded configurations can use earlier loaded features, creating load 368 + * dependencies, a load order list is maintained. Unload is strictly in the 369 + * reverse order to load. 370 + * 464 371 * @config_descs: 0 terminated array of configuration descriptors. 465 372 * @feat_descs: 0 terminated array of feature descriptors. 373 + * @owner_info: Information on the owner of this set. 466 374 */ 467 375 int cscfg_load_config_sets(struct cscfg_config_desc **config_descs, 468 - struct cscfg_feature_desc **feat_descs) 376 + struct cscfg_feature_desc **feat_descs, 377 + struct cscfg_load_owner_info *owner_info) 469 378 { 470 - int err, i = 0; 379 + int err = 0, i = 0; 471 380 472 381 mutex_lock(&cscfg_mutex); 473 382 ··· 489 380 if (err) { 490 381 pr_err("coresight-syscfg: Failed to load feature %s\n", 491 382 feat_descs[i]->name); 383 + cscfg_unload_owned_cfgs_feats(owner_info); 492 384 goto exit_unlock; 493 385 } 386 + feat_descs[i]->load_owner = owner_info; 494 387 i++; 495 388 } 496 389 } ··· 507 396 if (err) { 508 397 pr_err("coresight-syscfg: Failed to load configuration %s\n", 509 398 config_descs[i]->name); 399 + cscfg_unload_owned_cfgs_feats(owner_info); 510 400 goto exit_unlock; 511 401 } 402 + config_descs[i]->load_owner = owner_info; 512 403 i++; 404 + } 405 + } 406 + 407 + /* add the load owner to the load order list */ 408 + list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list); 409 + if (!list_is_singular(&cscfg_mgr->load_order_list)) { 410 + /* lock previous item in load order list */ 411 + err = cscfg_owner_get(list_prev_entry(owner_info, item)); 412 + if (err) { 413 + cscfg_unload_owned_cfgs_feats(owner_info); 414 + list_del(&owner_info->item); 513 415 } 514 416 } 515 417 ··· 531 407 return err; 532 408 } 533 409 EXPORT_SYMBOL_GPL(cscfg_load_config_sets); 410 + 411 + /** 412 + * cscfg_unload_config_sets - unload a set of configurations by owner. 413 + * 414 + * Dynamic unload of configuration and feature sets is done on the basis of 415 + * the load owner of that set. Later loaded configurations can depend on 416 + * features loaded earlier. 417 + * 418 + * Therefore, unload is only possible if:- 419 + * 1) no configurations are active. 420 + * 2) the set being unloaded was the last to be loaded to maintain dependencies. 421 + * 422 + * @owner_info: Information on owner for set being unloaded. 423 + */ 424 + int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info) 425 + { 426 + int err = 0; 427 + struct cscfg_load_owner_info *load_list_item = NULL; 428 + 429 + mutex_lock(&cscfg_mutex); 430 + 431 + /* cannot unload if anything is active */ 432 + if (atomic_read(&cscfg_mgr->sys_active_cnt)) { 433 + err = -EBUSY; 434 + goto exit_unlock; 435 + } 436 + 437 + /* cannot unload if not last loaded in load order */ 438 + if (!list_empty(&cscfg_mgr->load_order_list)) { 439 + load_list_item = list_last_entry(&cscfg_mgr->load_order_list, 440 + struct cscfg_load_owner_info, item); 441 + if (load_list_item != owner_info) 442 + load_list_item = NULL; 443 + } 444 + 445 + if (!load_list_item) { 446 + err = -EINVAL; 447 + goto exit_unlock; 448 + } 449 + 450 + /* unload all belonging to load_owner */ 451 + cscfg_unload_owned_cfgs_feats(owner_info); 452 + 453 + /* remove from load order list */ 454 + if (!list_is_singular(&cscfg_mgr->load_order_list)) { 455 + /* unlock previous item in load order list */ 456 + cscfg_owner_put(list_prev_entry(owner_info, item)); 457 + } 458 + list_del(&owner_info->item); 459 + 460 + exit_unlock: 461 + mutex_unlock(&cscfg_mutex); 462 + return err; 463 + } 464 + EXPORT_SYMBOL_GPL(cscfg_unload_config_sets); 534 465 535 466 /* Handle coresight device registration and add configs and features to devices */ 536 467 ··· 745 566 } 746 567 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats); 747 568 748 - /** 749 - * cscfg_activate_config - Mark a configuration descriptor as active. 750 - * 751 - * This will be seen when csdev devices are enabled in the system. 752 - * Only activated configurations can be enabled on individual devices. 753 - * Activation protects the configuration from alteration or removal while 754 - * active. 755 - * 756 - * Selection by hash value - generated from the configuration name when it 757 - * was loaded and added to the cs_etm/configurations file system for selection 758 - * by perf. 569 + /* 570 + * This activate configuration for either perf or sysfs. Perf can have multiple 571 + * active configs, selected per event, sysfs is limited to one. 759 572 * 760 573 * Increments the configuration descriptor active count and the global active 761 574 * count. 762 575 * 763 576 * @cfg_hash: Hash value of the selected configuration name. 764 577 */ 765 - int cscfg_activate_config(unsigned long cfg_hash) 578 + static int _cscfg_activate_config(unsigned long cfg_hash) 766 579 { 767 580 struct cscfg_config_desc *config_desc; 768 581 int err = -EINVAL; 769 582 770 - mutex_lock(&cscfg_mutex); 771 - 772 583 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 773 584 if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 585 + /* must ensure that config cannot be unloaded in use */ 586 + err = cscfg_owner_get(config_desc->load_owner); 587 + if (err) 588 + break; 774 589 /* 775 590 * increment the global active count - control changes to 776 591 * active configurations ··· 782 609 break; 783 610 } 784 611 } 612 + return err; 613 + } 614 + 615 + static void _cscfg_deactivate_config(unsigned long cfg_hash) 616 + { 617 + struct cscfg_config_desc *config_desc; 618 + 619 + list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 620 + if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 621 + atomic_dec(&config_desc->active_cnt); 622 + atomic_dec(&cscfg_mgr->sys_active_cnt); 623 + cscfg_owner_put(config_desc->load_owner); 624 + dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); 625 + break; 626 + } 627 + } 628 + } 629 + 630 + /* 631 + * called from configfs to set/clear the active configuration for use when 632 + * using sysfs to control trace. 633 + */ 634 + int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate) 635 + { 636 + unsigned long cfg_hash; 637 + int err = 0; 638 + 639 + mutex_lock(&cscfg_mutex); 640 + 641 + cfg_hash = (unsigned long)config_desc->event_ea->var; 642 + 643 + if (activate) { 644 + /* cannot be a current active value to activate this */ 645 + if (cscfg_mgr->sysfs_active_config) { 646 + err = -EBUSY; 647 + goto exit_unlock; 648 + } 649 + err = _cscfg_activate_config(cfg_hash); 650 + if (!err) 651 + cscfg_mgr->sysfs_active_config = cfg_hash; 652 + } else { 653 + /* disable if matching current value */ 654 + if (cscfg_mgr->sysfs_active_config == cfg_hash) { 655 + _cscfg_deactivate_config(cfg_hash); 656 + cscfg_mgr->sysfs_active_config = 0; 657 + } else 658 + err = -EINVAL; 659 + } 660 + 661 + exit_unlock: 662 + mutex_unlock(&cscfg_mutex); 663 + return err; 664 + } 665 + 666 + /* set the sysfs preset value */ 667 + void cscfg_config_sysfs_set_preset(int preset) 668 + { 669 + mutex_lock(&cscfg_mutex); 670 + cscfg_mgr->sysfs_active_preset = preset; 671 + mutex_unlock(&cscfg_mutex); 672 + } 673 + 674 + /* 675 + * Used by a device to get the config and preset selected as active in configfs, 676 + * when using sysfs to control trace. 677 + */ 678 + void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset) 679 + { 680 + mutex_lock(&cscfg_mutex); 681 + *preset = cscfg_mgr->sysfs_active_preset; 682 + *cfg_hash = cscfg_mgr->sysfs_active_config; 683 + mutex_unlock(&cscfg_mutex); 684 + } 685 + EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg); 686 + 687 + /** 688 + * cscfg_activate_config - Mark a configuration descriptor as active. 689 + * 690 + * This will be seen when csdev devices are enabled in the system. 691 + * Only activated configurations can be enabled on individual devices. 692 + * Activation protects the configuration from alteration or removal while 693 + * active. 694 + * 695 + * Selection by hash value - generated from the configuration name when it 696 + * was loaded and added to the cs_etm/configurations file system for selection 697 + * by perf. 698 + * 699 + * @cfg_hash: Hash value of the selected configuration name. 700 + */ 701 + int cscfg_activate_config(unsigned long cfg_hash) 702 + { 703 + int err = 0; 704 + 705 + mutex_lock(&cscfg_mutex); 706 + err = _cscfg_activate_config(cfg_hash); 785 707 mutex_unlock(&cscfg_mutex); 786 708 787 709 return err; ··· 892 624 */ 893 625 void cscfg_deactivate_config(unsigned long cfg_hash) 894 626 { 895 - struct cscfg_config_desc *config_desc; 896 - 897 627 mutex_lock(&cscfg_mutex); 898 - 899 - list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) { 900 - if ((unsigned long)config_desc->event_ea->var == cfg_hash) { 901 - atomic_dec(&config_desc->active_cnt); 902 - atomic_dec(&cscfg_mgr->sys_active_cnt); 903 - dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name); 904 - break; 905 - } 906 - } 628 + _cscfg_deactivate_config(cfg_hash); 907 629 mutex_unlock(&cscfg_mutex); 908 630 } 909 631 EXPORT_SYMBOL_GPL(cscfg_deactivate_config); ··· 1085 827 INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list); 1086 828 INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list); 1087 829 INIT_LIST_HEAD(&cscfg_mgr->config_desc_list); 830 + INIT_LIST_HEAD(&cscfg_mgr->load_order_list); 1088 831 atomic_set(&cscfg_mgr->sys_active_cnt, 0); 1089 832 1090 833 /* preload built-in configurations */ 1091 - err = cscfg_preload(); 834 + err = cscfg_preload(THIS_MODULE); 1092 835 if (err) 1093 836 goto exit_err; 1094 837
+36 -3
drivers/hwtracing/coresight/coresight-syscfg.h
··· 25 25 * @csdev_desc_list: List of coresight devices registered with the configuration manager. 26 26 * @feat_desc_list: List of feature descriptors to load into registered devices. 27 27 * @config_desc_list: List of system configuration descriptors to load into registered devices. 28 + * @load_order_list: Ordered list of owners for dynamically loaded configurations. 28 29 * @sys_active_cnt: Total number of active config descriptor references. 29 30 * @cfgfs_subsys: configfs subsystem used to manage configurations. 31 + * @sysfs_active_config:Active config hash used if CoreSight controlled from sysfs. 32 + * @sysfs_active_preset:Active preset index used if CoreSight controlled from sysfs. 30 33 */ 31 34 struct cscfg_manager { 32 35 struct device dev; 33 36 struct list_head csdev_desc_list; 34 37 struct list_head feat_desc_list; 35 38 struct list_head config_desc_list; 39 + struct list_head load_order_list; 36 40 atomic_t sys_active_cnt; 37 41 struct configfs_subsystem cfgfs_subsys; 42 + u32 sysfs_active_config; 43 + int sysfs_active_preset; 38 44 }; 39 45 40 46 /* get reference to dev in cscfg_manager */ ··· 62 56 struct list_head item; 63 57 }; 64 58 59 + /* owner types for loading and unloading of config and feature sets */ 60 + enum cscfg_load_owner_type { 61 + CSCFG_OWNER_PRELOAD, 62 + CSCFG_OWNER_MODULE, 63 + }; 64 + 65 + /** 66 + * Load item - item to add to the load order list allowing dynamic load and 67 + * unload of configurations and features. Caller loading a config 68 + * set provides a context handle for unload. API ensures that 69 + * items unloaded strictly in reverse order from load to ensure 70 + * dependencies are respected. 71 + * 72 + * @item: list entry for load order list. 73 + * @type: type of owner - allows interpretation of owner_handle. 74 + * @owner_handle: load context - handle for owner of loaded configs. 75 + */ 76 + struct cscfg_load_owner_info { 77 + struct list_head item; 78 + int type; 79 + void *owner_handle; 80 + }; 81 + 65 82 /* internal core operations for cscfg */ 66 83 int __init cscfg_init(void); 67 84 void cscfg_exit(void); 68 - int cscfg_preload(void); 85 + int cscfg_preload(void *owner_handle); 69 86 const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name); 70 87 int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc, 71 88 int param_idx, u64 value); 72 - 89 + int cscfg_config_sysfs_activate(struct cscfg_config_desc *cfg_desc, bool activate); 90 + void cscfg_config_sysfs_set_preset(int preset); 73 91 74 92 /* syscfg manager external API */ 75 93 int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, 76 - struct cscfg_feature_desc **feat_descs); 94 + struct cscfg_feature_desc **feat_descs, 95 + struct cscfg_load_owner_info *owner_info); 96 + int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info); 77 97 int cscfg_register_csdev(struct coresight_device *csdev, u32 match_flags, 78 98 struct cscfg_csdev_feat_ops *ops); 79 99 void cscfg_unregister_csdev(struct coresight_device *csdev); ··· 109 77 int cscfg_csdev_enable_active_config(struct coresight_device *csdev, 110 78 unsigned long cfg_hash, int preset); 111 79 void cscfg_csdev_disable_active_config(struct coresight_device *csdev); 80 + void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset); 112 81 113 82 #endif /* CORESIGHT_SYSCFG_H */
+9
samples/Kconfig
··· 241 241 Build example userspace program to use the new mount_notify(), 242 242 sb_notify() syscalls and the KEYCTL_WATCH_KEY keyctl() function. 243 243 244 + config SAMPLE_CORESIGHT_SYSCFG 245 + tristate "Build example loadable module for CoreSight config" 246 + depends on CORESIGHT && m 247 + help 248 + Build an example loadable module that adds new CoreSight features 249 + and configuration using the CoreSight system configuration API. 250 + This demonstrates how a user may create their own CoreSight 251 + configurations and easily load them into the system at runtime. 252 + 244 253 endif # SAMPLES 245 254 246 255 config HAVE_SAMPLE_FTRACE_DIRECT
+1
samples/Makefile
··· 32 32 subdir-$(CONFIG_SAMPLE_WATCHDOG) += watchdog 33 33 subdir-$(CONFIG_SAMPLE_WATCH_QUEUE) += watch_queue 34 34 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak/ 35 + obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight/
+4
samples/coresight/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + 3 + obj-$(CONFIG_SAMPLE_CORESIGHT_SYSCFG) += coresight-cfg-sample.o 4 + ccflags-y += -I$(srctree)/drivers/hwtracing/coresight
+73
samples/coresight/coresight-cfg-sample.c
··· 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 "coresight-config.h" 8 + #include "coresight-syscfg.h" 9 + 10 + /* create an alternate autofdo configuration */ 11 + 12 + /* we will provide 4 sets of preset parameter values */ 13 + #define AFDO2_NR_PRESETS 4 14 + /* the total number of parameters in used features - strobing has 2 */ 15 + #define AFDO2_NR_PARAM_SUM 2 16 + 17 + static const char *afdo2_ref_names[] = { 18 + "strobing", 19 + }; 20 + 21 + /* 22 + * set of presets leaves strobing window constant while varying period to allow 23 + * experimentation with mark / space ratios for various workloads 24 + */ 25 + static u64 afdo2_presets[AFDO2_NR_PRESETS][AFDO2_NR_PARAM_SUM] = { 26 + { 1000, 100 }, 27 + { 1000, 1000 }, 28 + { 1000, 5000 }, 29 + { 1000, 10000 }, 30 + }; 31 + 32 + struct cscfg_config_desc afdo2 = { 33 + .name = "autofdo2", 34 + .description = "Setup ETMs with strobing for autofdo\n" 35 + "Supplied presets allow experimentation with mark-space ratio for various loads\n", 36 + .nr_feat_refs = ARRAY_SIZE(afdo2_ref_names), 37 + .feat_ref_names = afdo2_ref_names, 38 + .nr_presets = AFDO2_NR_PRESETS, 39 + .nr_total_params = AFDO2_NR_PARAM_SUM, 40 + .presets = &afdo2_presets[0][0], 41 + }; 42 + 43 + static struct cscfg_feature_desc *sample_feats[] = { 44 + NULL 45 + }; 46 + 47 + static struct cscfg_config_desc *sample_cfgs[] = { 48 + &afdo2, 49 + NULL 50 + }; 51 + 52 + static struct cscfg_load_owner_info mod_owner = { 53 + .type = CSCFG_OWNER_MODULE, 54 + .owner_handle = THIS_MODULE, 55 + }; 56 + 57 + /* module init and exit - just load and unload configs */ 58 + static int __init cscfg_sample_init(void) 59 + { 60 + return cscfg_load_config_sets(sample_cfgs, sample_feats, &mod_owner); 61 + } 62 + 63 + static void __exit cscfg_sample_exit(void) 64 + { 65 + cscfg_unload_config_sets(&mod_owner); 66 + } 67 + 68 + module_init(cscfg_sample_init); 69 + module_exit(cscfg_sample_exit); 70 + 71 + MODULE_LICENSE("GPL v2"); 72 + MODULE_AUTHOR("Mike Leach <mike.leach@linaro.org>"); 73 + MODULE_DESCRIPTION("CoreSight Syscfg Example");