1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2020 Linaro Limited, All rights reserved.
4 * Author: Mike Leach <mike.leach@linaro.org>
7 #include <linux/platform_device.h>
8 #include <linux/slab.h>
10 #include "coresight-config.h"
11 #include "coresight-etm-perf.h"
12 #include "coresight-syscfg.h"
13 #include "coresight-syscfg-configfs.h"
16 * cscfg_ API manages configurations and features for the entire coresight
19 * It allows the loading of configurations and features, and loads these into
20 * coresight devices as appropriate.
23 /* protect the cscsg_data and device */
24 static DEFINE_MUTEX(cscfg_mutex);
26 /* only one of these */
27 static struct cscfg_manager *cscfg_mgr;
29 /* load features and configuations into the lists */
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)
35 struct cscfg_feature_csdev *feat_csdev = NULL;
37 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
38 if (strcmp(feat_csdev->feat_desc->name, name) == 0)
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)
48 struct cscfg_config_csdev *config_csdev = NULL;
49 struct device *dev = csdev->dev.parent;
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]),
58 config_csdev->csdev = csdev;
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)
66 struct cscfg_config_csdev *config_csdev = NULL;
67 struct cscfg_feature_csdev *feat_csdev;
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]);
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.
81 config_csdev = cscfg_alloc_csdev_cfg(csdev,
82 config_desc->nr_feat_refs);
85 config_csdev->config_desc = config_desc;
87 config_csdev->feats_csdev[config_csdev->nr_feat++] = feat_csdev;
90 /* if matched features, add config to device.*/
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);
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.
105 static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *config_desc)
107 struct cscfg_registered_csdev *csdev_item;
110 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
111 err = cscfg_add_csdev_cfg(csdev_item->csdev, config_desc);
119 * Allocate a feature object for load into a csdev.
120 * memory allocated using the csdev->dev object using devm managed allocator.
122 static struct cscfg_feature_csdev *
123 cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
125 struct cscfg_feature_csdev *feat_csdev = NULL;
126 struct device *dev = csdev->dev.parent;
129 feat_csdev = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL);
133 /* parameters are optional - could be 0 */
134 feat_csdev->nr_params = feat_desc->nr_params;
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.
141 if (feat_csdev->nr_params) {
142 feat_csdev->params_csdev = devm_kcalloc(dev, feat_csdev->nr_params,
143 sizeof(struct cscfg_parameter_csdev),
145 if (!feat_csdev->params_csdev)
149 * fill in the feature reference in the param - other fields
150 * handled by loader in csdev.
152 for (i = 0; i < feat_csdev->nr_params; i++)
153 feat_csdev->params_csdev[i].feat_csdev = feat_csdev;
157 * Always have registers to program - again the load routine in csdev device
158 * will fill out according to feature descriptor and device requirements.
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),
164 if (!feat_csdev->regs_csdev)
167 /* load the feature default values */
168 feat_csdev->feat_desc = feat_desc;
169 feat_csdev->csdev = csdev;
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)
179 struct cscfg_feature_csdev *feat_csdev;
186 feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
190 /* load the feature into the device */
191 err = ops->load_feat(csdev, feat_csdev);
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);
205 * Add feature to any matching devices - call with mutex locked.
206 * Iterates through devices - any device that matches the feature will be
209 static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
211 struct cscfg_registered_csdev *csdev_item;
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);
224 /* check feature list for a named feature - call with mutex locked. */
225 static bool cscfg_match_list_feat(const char *name)
227 struct cscfg_feature_desc *feat_desc;
229 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
230 if (strcmp(feat_desc->name, name) == 0)
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)
241 for (i = 0; i < config_desc->nr_feat_refs; i++)
242 if (!cscfg_match_list_feat(config_desc->feat_ref_names[i]))
248 * load feature - add to feature list.
250 static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc)
253 struct cscfg_feature_desc *feat_desc_exist;
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))
261 /* add feature to any matching registered devices */
262 err = cscfg_add_feat_to_csdevs(feat_desc);
266 list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list);
271 * load config into the system - validate used features exist then add to
274 static int cscfg_load_config(struct cscfg_config_desc *config_desc)
277 struct cscfg_config_desc *config_desc_exist;
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))
285 /* validate features are present */
286 err = cscfg_check_feat_for_cfg(config_desc);
290 /* add config to any matching registered device */
291 err = cscfg_add_cfg_to_csdevs(config_desc);
295 /* add config to perf fs to allow selection */
296 err = etm_perf_add_symlink_cscfg(cscfg_device(), config_desc);
300 list_add(&config_desc->item, &cscfg_mgr->config_desc_list);
301 atomic_set(&config_desc->active_cnt, 0);
305 /* get a feature descriptor by name */
306 const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name)
308 const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item;
310 mutex_lock(&cscfg_mutex);
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;
319 mutex_unlock(&cscfg_mutex);
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)
328 struct cscfg_feature_csdev *feat_csdev;
330 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
331 if (feat_csdev->feat_desc == feat_desc)
337 int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
338 int param_idx, u64 value)
341 struct cscfg_feature_csdev *feat_csdev;
342 struct cscfg_registered_csdev *csdev_item;
344 mutex_lock(&cscfg_mutex);
346 /* check if any config active & return busy */
347 if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
353 if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) {
357 feat_desc->params_desc[param_idx].value = value;
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);
363 feat_csdev->params_csdev[param_idx].current_value = value;
367 mutex_unlock(&cscfg_mutex);
372 * Conditionally up reference count on owner to prevent unload.
374 * module loaded configs need to be locked in to prevent premature unload.
376 static int cscfg_owner_get(struct cscfg_load_owner_info *owner_info)
378 if ((owner_info->type == CSCFG_OWNER_MODULE) &&
379 (!try_module_get(owner_info->owner_handle)))
384 /* conditionally lower ref count on an owner */
385 static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info)
387 if (owner_info->type == CSCFG_OWNER_MODULE)
388 module_put(owner_info->owner_handle);
391 static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner)
393 struct cscfg_config_csdev *config_csdev, *tmp;
395 if (list_empty(&csdev->config_csdev_list))
398 list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) {
399 if (config_csdev->config_desc->load_owner == load_owner)
400 list_del(&config_csdev->node);
404 static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
406 struct cscfg_feature_csdev *feat_csdev, *tmp;
408 if (list_empty(&csdev->feature_csdev_list))
411 list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) {
412 if (feat_csdev->feat_desc->load_owner == load_owner)
413 list_del(&feat_csdev->node);
418 * removal is relatively easy - just remove from all lists, anything that
419 * matches the owner. Memory for the descriptors will be managed by the owner,
420 * memory for the csdev items is devm_ allocated with the individual csdev
423 static void cscfg_unload_owned_cfgs_feats(void *load_owner)
425 struct cscfg_config_desc *config_desc, *cfg_tmp;
426 struct cscfg_feature_desc *feat_desc, *feat_tmp;
427 struct cscfg_registered_csdev *csdev_item;
429 /* remove from each csdev instance feature and config lists */
430 list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
432 * for each csdev, check the loaded lists and remove if
433 * referenced descriptor is owned
435 cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner);
436 cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner);
439 /* remove from the config descriptor lists */
440 list_for_each_entry_safe(config_desc, cfg_tmp, &cscfg_mgr->config_desc_list, item) {
441 if (config_desc->load_owner == load_owner) {
442 cscfg_configfs_del_config(config_desc);
443 etm_perf_del_symlink_cscfg(config_desc);
444 list_del(&config_desc->item);
448 /* remove from the feature descriptor lists */
449 list_for_each_entry_safe(feat_desc, feat_tmp, &cscfg_mgr->feat_desc_list, item) {
450 if (feat_desc->load_owner == load_owner) {
451 cscfg_configfs_del_feature(feat_desc);
452 list_del(&feat_desc->item);
458 * cscfg_load_config_sets - API function to load feature and config sets.
460 * Take a 0 terminated array of feature descriptors and/or configuration
461 * descriptors and load into the system.
462 * Features are loaded first to ensure configuration dependencies can be met.
464 * To facilitate dynamic loading and unloading, features and configurations
465 * have a "load_owner", to allow later unload by the same owner. An owner may
466 * be a loadable module or configuration dynamically created via configfs.
467 * As later loaded configurations can use earlier loaded features, creating load
468 * dependencies, a load order list is maintained. Unload is strictly in the
469 * reverse order to load.
471 * @config_descs: 0 terminated array of configuration descriptors.
472 * @feat_descs: 0 terminated array of feature descriptors.
473 * @owner_info: Information on the owner of this set.
475 int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
476 struct cscfg_feature_desc **feat_descs,
477 struct cscfg_load_owner_info *owner_info)
481 mutex_lock(&cscfg_mutex);
483 /* load features first */
485 while (feat_descs[i]) {
486 err = cscfg_load_feat(feat_descs[i]);
488 err = cscfg_configfs_add_feature(feat_descs[i]);
490 pr_err("coresight-syscfg: Failed to load feature %s\n",
491 feat_descs[i]->name);
492 cscfg_unload_owned_cfgs_feats(owner_info);
495 feat_descs[i]->load_owner = owner_info;
500 /* next any configurations to check feature dependencies */
503 while (config_descs[i]) {
504 err = cscfg_load_config(config_descs[i]);
506 err = cscfg_configfs_add_config(config_descs[i]);
508 pr_err("coresight-syscfg: Failed to load configuration %s\n",
509 config_descs[i]->name);
510 cscfg_unload_owned_cfgs_feats(owner_info);
513 config_descs[i]->load_owner = owner_info;
518 /* add the load owner to the load order list */
519 list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list);
520 if (!list_is_singular(&cscfg_mgr->load_order_list)) {
521 /* lock previous item in load order list */
522 err = cscfg_owner_get(list_prev_entry(owner_info, item));
524 cscfg_unload_owned_cfgs_feats(owner_info);
525 list_del(&owner_info->item);
530 mutex_unlock(&cscfg_mutex);
533 EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
536 * cscfg_unload_config_sets - unload a set of configurations by owner.
538 * Dynamic unload of configuration and feature sets is done on the basis of
539 * the load owner of that set. Later loaded configurations can depend on
540 * features loaded earlier.
542 * Therefore, unload is only possible if:-
543 * 1) no configurations are active.
544 * 2) the set being unloaded was the last to be loaded to maintain dependencies.
546 * @owner_info: Information on owner for set being unloaded.
548 int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info)
551 struct cscfg_load_owner_info *load_list_item = NULL;
553 mutex_lock(&cscfg_mutex);
555 /* cannot unload if anything is active */
556 if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
561 /* cannot unload if not last loaded in load order */
562 if (!list_empty(&cscfg_mgr->load_order_list)) {
563 load_list_item = list_last_entry(&cscfg_mgr->load_order_list,
564 struct cscfg_load_owner_info, item);
565 if (load_list_item != owner_info)
566 load_list_item = NULL;
569 if (!load_list_item) {
574 /* unload all belonging to load_owner */
575 cscfg_unload_owned_cfgs_feats(owner_info);
577 /* remove from load order list */
578 if (!list_is_singular(&cscfg_mgr->load_order_list)) {
579 /* unlock previous item in load order list */
580 cscfg_owner_put(list_prev_entry(owner_info, item));
582 list_del(&owner_info->item);
585 mutex_unlock(&cscfg_mutex);
588 EXPORT_SYMBOL_GPL(cscfg_unload_config_sets);
590 /* Handle coresight device registration and add configs and features to devices */
592 /* iterate through config lists and load matching configs to device */
593 static int cscfg_add_cfgs_csdev(struct coresight_device *csdev)
595 struct cscfg_config_desc *config_desc;
598 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
599 err = cscfg_add_csdev_cfg(csdev, config_desc);
606 /* iterate through feature lists and load matching features to device */
607 static int cscfg_add_feats_csdev(struct coresight_device *csdev,
609 struct cscfg_csdev_feat_ops *ops)
611 struct cscfg_feature_desc *feat_desc;
617 list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
618 if (feat_desc->match_flags & match_flags) {
619 err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
627 /* Add coresight device to list and copy its matching info */
628 static int cscfg_list_add_csdev(struct coresight_device *csdev,
630 struct cscfg_csdev_feat_ops *ops)
632 struct cscfg_registered_csdev *csdev_item;
634 /* allocate the list entry structure */
635 csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL);
639 csdev_item->csdev = csdev;
640 csdev_item->match_flags = match_flags;
641 csdev_item->ops.load_feat = ops->load_feat;
642 list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list);
644 INIT_LIST_HEAD(&csdev->feature_csdev_list);
645 INIT_LIST_HEAD(&csdev->config_csdev_list);
646 spin_lock_init(&csdev->cscfg_csdev_lock);
651 /* remove a coresight device from the list and free data */
652 static void cscfg_list_remove_csdev(struct coresight_device *csdev)
654 struct cscfg_registered_csdev *csdev_item, *tmp;
656 list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) {
657 if (csdev_item->csdev == csdev) {
658 list_del(&csdev_item->item);
666 * cscfg_register_csdev - register a coresight device with the syscfg manager.
668 * Registers the coresight device with the system. @match_flags used to check
669 * if the device is a match for registered features. Any currently registered
670 * configurations and features that match the device will be loaded onto it.
672 * @csdev: The coresight device to register.
673 * @match_flags: Matching information to load features.
674 * @ops: Standard operations supported by the device.
676 int cscfg_register_csdev(struct coresight_device *csdev,
678 struct cscfg_csdev_feat_ops *ops)
682 mutex_lock(&cscfg_mutex);
684 /* add device to list of registered devices */
685 ret = cscfg_list_add_csdev(csdev, match_flags, ops);
687 goto reg_csdev_unlock;
689 /* now load any registered features and configs matching the device. */
690 ret = cscfg_add_feats_csdev(csdev, match_flags, ops);
692 cscfg_list_remove_csdev(csdev);
693 goto reg_csdev_unlock;
696 ret = cscfg_add_cfgs_csdev(csdev);
698 cscfg_list_remove_csdev(csdev);
699 goto reg_csdev_unlock;
702 pr_info("CSCFG registered %s", dev_name(&csdev->dev));
705 mutex_unlock(&cscfg_mutex);
708 EXPORT_SYMBOL_GPL(cscfg_register_csdev);
711 * cscfg_unregister_csdev - remove coresight device from syscfg manager.
713 * @csdev: Device to remove.
715 void cscfg_unregister_csdev(struct coresight_device *csdev)
717 mutex_lock(&cscfg_mutex);
718 cscfg_list_remove_csdev(csdev);
719 mutex_unlock(&cscfg_mutex);
721 EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
724 * cscfg_csdev_reset_feats - reset features for a CoreSight device.
726 * Resets all parameters and register values for any features loaded
727 * into @csdev to their default values.
729 * @csdev: The CoreSight device.
731 void cscfg_csdev_reset_feats(struct coresight_device *csdev)
733 struct cscfg_feature_csdev *feat_csdev;
736 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
737 if (list_empty(&csdev->feature_csdev_list))
740 list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
741 cscfg_reset_feat(feat_csdev);
744 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
746 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
749 * This activate configuration for either perf or sysfs. Perf can have multiple
750 * active configs, selected per event, sysfs is limited to one.
752 * Increments the configuration descriptor active count and the global active
755 * @cfg_hash: Hash value of the selected configuration name.
757 static int _cscfg_activate_config(unsigned long cfg_hash)
759 struct cscfg_config_desc *config_desc;
762 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
763 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
764 /* must ensure that config cannot be unloaded in use */
765 err = cscfg_owner_get(config_desc->load_owner);
769 * increment the global active count - control changes to
770 * active configurations
772 atomic_inc(&cscfg_mgr->sys_active_cnt);
775 * mark the descriptor as active so enable config on a
776 * device instance will use it
778 atomic_inc(&config_desc->active_cnt);
781 dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
788 static void _cscfg_deactivate_config(unsigned long cfg_hash)
790 struct cscfg_config_desc *config_desc;
792 list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
793 if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
794 atomic_dec(&config_desc->active_cnt);
795 atomic_dec(&cscfg_mgr->sys_active_cnt);
796 cscfg_owner_put(config_desc->load_owner);
797 dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
804 * called from configfs to set/clear the active configuration for use when
805 * using sysfs to control trace.
807 int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate)
809 unsigned long cfg_hash;
812 mutex_lock(&cscfg_mutex);
814 cfg_hash = (unsigned long)config_desc->event_ea->var;
817 /* cannot be a current active value to activate this */
818 if (cscfg_mgr->sysfs_active_config) {
822 err = _cscfg_activate_config(cfg_hash);
824 cscfg_mgr->sysfs_active_config = cfg_hash;
826 /* disable if matching current value */
827 if (cscfg_mgr->sysfs_active_config == cfg_hash) {
828 _cscfg_deactivate_config(cfg_hash);
829 cscfg_mgr->sysfs_active_config = 0;
835 mutex_unlock(&cscfg_mutex);
839 /* set the sysfs preset value */
840 void cscfg_config_sysfs_set_preset(int preset)
842 mutex_lock(&cscfg_mutex);
843 cscfg_mgr->sysfs_active_preset = preset;
844 mutex_unlock(&cscfg_mutex);
848 * Used by a device to get the config and preset selected as active in configfs,
849 * when using sysfs to control trace.
851 void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset)
853 mutex_lock(&cscfg_mutex);
854 *preset = cscfg_mgr->sysfs_active_preset;
855 *cfg_hash = cscfg_mgr->sysfs_active_config;
856 mutex_unlock(&cscfg_mutex);
858 EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg);
861 * cscfg_activate_config - Mark a configuration descriptor as active.
863 * This will be seen when csdev devices are enabled in the system.
864 * Only activated configurations can be enabled on individual devices.
865 * Activation protects the configuration from alteration or removal while
868 * Selection by hash value - generated from the configuration name when it
869 * was loaded and added to the cs_etm/configurations file system for selection
872 * @cfg_hash: Hash value of the selected configuration name.
874 int cscfg_activate_config(unsigned long cfg_hash)
878 mutex_lock(&cscfg_mutex);
879 err = _cscfg_activate_config(cfg_hash);
880 mutex_unlock(&cscfg_mutex);
884 EXPORT_SYMBOL_GPL(cscfg_activate_config);
887 * cscfg_deactivate_config - Mark a config descriptor as inactive.
889 * Decrement the configuration and global active counts.
891 * @cfg_hash: Hash value of the selected configuration name.
893 void cscfg_deactivate_config(unsigned long cfg_hash)
895 mutex_lock(&cscfg_mutex);
896 _cscfg_deactivate_config(cfg_hash);
897 mutex_unlock(&cscfg_mutex);
899 EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
902 * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
904 * Enables the configuration selected by @cfg_hash if the configuration is supported
905 * on the device and has been activated.
907 * If active and supported the CoreSight device @csdev will be programmed with the
908 * configuration, using @preset parameters.
910 * Should be called before driver hardware enable for the requested device, prior to
911 * programming and enabling the physical hardware.
913 * @csdev: CoreSight device to program.
914 * @cfg_hash: Selector for the configuration.
915 * @preset: Preset parameter values to use, 0 for current / default values.
917 int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
918 unsigned long cfg_hash, int preset)
920 struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
921 const struct cscfg_config_desc *config_desc;
925 /* quickly check global count */
926 if (!atomic_read(&cscfg_mgr->sys_active_cnt))
930 * Look for matching configuration - set the active configuration
933 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
934 list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
935 config_desc = config_csdev_item->config_desc;
936 if ((atomic_read(&config_desc->active_cnt)) &&
937 ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
938 config_csdev_active = config_csdev_item;
939 csdev->active_cscfg_ctxt = (void *)config_csdev_active;
943 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
946 * If found, attempt to enable
948 if (config_csdev_active) {
950 * Call the generic routine that will program up the internal
951 * driver structures prior to programming up the hardware.
952 * This routine takes the driver spinlock saved in the configs.
954 err = cscfg_csdev_enable_config(config_csdev_active, preset);
957 * Successful programming. Check the active_cscfg_ctxt
958 * pointer to ensure no pre-emption disabled it via
959 * cscfg_csdev_disable_active_config() before
962 * Set enabled if OK, err if not.
964 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
965 if (csdev->active_cscfg_ctxt)
966 config_csdev_active->enabled = true;
969 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
974 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
977 * cscfg_csdev_disable_active_config - disable an active config on the device.
979 * Disables the active configuration on the CoreSight device @csdev.
980 * Disable will save the values of any registers marked in the configurations
981 * as save on disable.
983 * Should be called after driver hardware disable for the requested device,
984 * after disabling the physical hardware and reading back registers.
986 * @csdev: The CoreSight device.
988 void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
990 struct cscfg_config_csdev *config_csdev;
994 * Check if we have an active config, and that it was successfully enabled.
995 * If it was not enabled, we have no work to do, otherwise mark as disabled.
996 * Clear the active config pointer.
998 spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
999 config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
1001 if (!config_csdev->enabled)
1002 config_csdev = NULL;
1004 config_csdev->enabled = false;
1006 csdev->active_cscfg_ctxt = NULL;
1007 spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
1009 /* true if there was an enabled active config */
1011 cscfg_csdev_disable_config(config_csdev);
1013 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
1015 /* Initialise system configuration management device. */
1017 struct device *cscfg_device(void)
1019 return cscfg_mgr ? &cscfg_mgr->dev : NULL;
1022 /* Must have a release function or the kernel will complain on module unload */
1023 static void cscfg_dev_release(struct device *dev)
1029 /* a device is needed to "own" some kernel elements such as sysfs entries. */
1030 static int cscfg_create_device(void)
1035 mutex_lock(&cscfg_mutex);
1038 goto create_dev_exit_unlock;
1041 cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
1043 goto create_dev_exit_unlock;
1045 /* setup the device */
1046 dev = cscfg_device();
1047 dev->release = cscfg_dev_release;
1048 dev->init_name = "cs_system_cfg";
1050 err = device_register(dev);
1054 create_dev_exit_unlock:
1055 mutex_unlock(&cscfg_mutex);
1059 static void cscfg_clear_device(void)
1061 struct cscfg_config_desc *cfg_desc;
1063 mutex_lock(&cscfg_mutex);
1064 list_for_each_entry(cfg_desc, &cscfg_mgr->config_desc_list, item) {
1065 etm_perf_del_symlink_cscfg(cfg_desc);
1067 cscfg_configfs_release(cscfg_mgr);
1068 device_unregister(cscfg_device());
1069 mutex_unlock(&cscfg_mutex);
1072 /* Initialise system config management API device */
1073 int __init cscfg_init(void)
1077 err = cscfg_create_device();
1081 err = cscfg_configfs_init(cscfg_mgr);
1085 INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list);
1086 INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list);
1087 INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
1088 INIT_LIST_HEAD(&cscfg_mgr->load_order_list);
1089 atomic_set(&cscfg_mgr->sys_active_cnt, 0);
1091 /* preload built-in configurations */
1092 err = cscfg_preload(THIS_MODULE);
1096 dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
1100 cscfg_clear_device();
1104 void cscfg_exit(void)
1106 cscfg_clear_device();