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 * Unregister all configuration and features from configfs owned by load_owner.
419 * Although this is called without the list mutex being held, it is in the
420 * context of an unload operation which are strictly serialised,
421 * so the lists cannot change during this call.
423 static void cscfg_fs_unregister_cfgs_feats(void *load_owner
)
425 struct cscfg_config_desc
*config_desc
;
426 struct cscfg_feature_desc
*feat_desc
;
428 list_for_each_entry(config_desc
, &cscfg_mgr
->config_desc_list
, item
) {
429 if (config_desc
->load_owner
== load_owner
)
430 cscfg_configfs_del_config(config_desc
);
432 list_for_each_entry(feat_desc
, &cscfg_mgr
->feat_desc_list
, item
) {
433 if (feat_desc
->load_owner
== load_owner
)
434 cscfg_configfs_del_feature(feat_desc
);
439 * removal is relatively easy - just remove from all lists, anything that
440 * matches the owner. Memory for the descriptors will be managed by the owner,
441 * memory for the csdev items is devm_ allocated with the individual csdev
444 static void cscfg_unload_owned_cfgs_feats(void *load_owner
)
446 struct cscfg_config_desc
*config_desc
, *cfg_tmp
;
447 struct cscfg_feature_desc
*feat_desc
, *feat_tmp
;
448 struct cscfg_registered_csdev
*csdev_item
;
450 lockdep_assert_held(&cscfg_mutex
);
452 /* remove from each csdev instance feature and config lists */
453 list_for_each_entry(csdev_item
, &cscfg_mgr
->csdev_desc_list
, item
) {
455 * for each csdev, check the loaded lists and remove if
456 * referenced descriptor is owned
458 cscfg_remove_owned_csdev_configs(csdev_item
->csdev
, load_owner
);
459 cscfg_remove_owned_csdev_features(csdev_item
->csdev
, load_owner
);
462 /* remove from the config descriptor lists */
463 list_for_each_entry_safe(config_desc
, cfg_tmp
, &cscfg_mgr
->config_desc_list
, item
) {
464 if (config_desc
->load_owner
== load_owner
) {
465 etm_perf_del_symlink_cscfg(config_desc
);
466 list_del(&config_desc
->item
);
470 /* remove from the feature descriptor lists */
471 list_for_each_entry_safe(feat_desc
, feat_tmp
, &cscfg_mgr
->feat_desc_list
, item
) {
472 if (feat_desc
->load_owner
== load_owner
) {
473 list_del(&feat_desc
->item
);
479 * load the features and configs to the lists - called with list mutex held
481 static int cscfg_load_owned_cfgs_feats(struct cscfg_config_desc
**config_descs
,
482 struct cscfg_feature_desc
**feat_descs
,
483 struct cscfg_load_owner_info
*owner_info
)
487 lockdep_assert_held(&cscfg_mutex
);
489 /* load features first */
491 for (i
= 0; feat_descs
[i
]; i
++) {
492 err
= cscfg_load_feat(feat_descs
[i
]);
494 pr_err("coresight-syscfg: Failed to load feature %s\n",
495 feat_descs
[i
]->name
);
498 feat_descs
[i
]->load_owner
= owner_info
;
502 /* next any configurations to check feature dependencies */
504 for (i
= 0; config_descs
[i
]; i
++) {
505 err
= cscfg_load_config(config_descs
[i
]);
507 pr_err("coresight-syscfg: Failed to load configuration %s\n",
508 config_descs
[i
]->name
);
511 config_descs
[i
]->load_owner
= owner_info
;
512 config_descs
[i
]->available
= false;
518 /* set configurations as available to activate at the end of the load process */
519 static void cscfg_set_configs_available(struct cscfg_config_desc
**config_descs
)
523 lockdep_assert_held(&cscfg_mutex
);
526 for (i
= 0; config_descs
[i
]; i
++)
527 config_descs
[i
]->available
= true;
532 * Create and register each of the configurations and features with configfs.
533 * Called without mutex being held.
535 static int cscfg_fs_register_cfgs_feats(struct cscfg_config_desc
**config_descs
,
536 struct cscfg_feature_desc
**feat_descs
)
541 for (i
= 0; feat_descs
[i
]; i
++) {
542 err
= cscfg_configfs_add_feature(feat_descs
[i
]);
548 for (i
= 0; config_descs
[i
]; i
++) {
549 err
= cscfg_configfs_add_config(config_descs
[i
]);
558 * cscfg_load_config_sets - API function to load feature and config sets.
560 * Take a 0 terminated array of feature descriptors and/or configuration
561 * descriptors and load into the system.
562 * Features are loaded first to ensure configuration dependencies can be met.
564 * To facilitate dynamic loading and unloading, features and configurations
565 * have a "load_owner", to allow later unload by the same owner. An owner may
566 * be a loadable module or configuration dynamically created via configfs.
567 * As later loaded configurations can use earlier loaded features, creating load
568 * dependencies, a load order list is maintained. Unload is strictly in the
569 * reverse order to load.
571 * @config_descs: 0 terminated array of configuration descriptors.
572 * @feat_descs: 0 terminated array of feature descriptors.
573 * @owner_info: Information on the owner of this set.
575 int cscfg_load_config_sets(struct cscfg_config_desc
**config_descs
,
576 struct cscfg_feature_desc
**feat_descs
,
577 struct cscfg_load_owner_info
*owner_info
)
581 mutex_lock(&cscfg_mutex
);
582 if (cscfg_mgr
->load_state
!= CSCFG_NONE
) {
583 mutex_unlock(&cscfg_mutex
);
586 cscfg_mgr
->load_state
= CSCFG_LOAD
;
588 /* first load and add to the lists */
589 err
= cscfg_load_owned_cfgs_feats(config_descs
, feat_descs
, owner_info
);
593 /* add the load owner to the load order list */
594 list_add_tail(&owner_info
->item
, &cscfg_mgr
->load_order_list
);
595 if (!list_is_singular(&cscfg_mgr
->load_order_list
)) {
596 /* lock previous item in load order list */
597 err
= cscfg_owner_get(list_prev_entry(owner_info
, item
));
599 goto err_clean_owner_list
;
603 * make visible to configfs - configfs manipulation must occur outside
604 * the list mutex lock to avoid circular lockdep issues with configfs
605 * built in mutexes and semaphores. This is safe as it is not possible
606 * to start a new load/unload operation till the current one is done.
608 mutex_unlock(&cscfg_mutex
);
610 /* create the configfs elements */
611 err
= cscfg_fs_register_cfgs_feats(config_descs
, feat_descs
);
612 mutex_lock(&cscfg_mutex
);
617 /* mark any new configs as available for activation */
618 cscfg_set_configs_available(config_descs
);
622 /* cleanup after error registering with configfs */
623 cscfg_fs_unregister_cfgs_feats(owner_info
);
625 if (!list_is_singular(&cscfg_mgr
->load_order_list
))
626 cscfg_owner_put(list_prev_entry(owner_info
, item
));
628 err_clean_owner_list
:
629 list_del(&owner_info
->item
);
632 cscfg_unload_owned_cfgs_feats(owner_info
);
635 cscfg_mgr
->load_state
= CSCFG_NONE
;
636 mutex_unlock(&cscfg_mutex
);
639 EXPORT_SYMBOL_GPL(cscfg_load_config_sets
);
642 * cscfg_unload_config_sets - unload a set of configurations by owner.
644 * Dynamic unload of configuration and feature sets is done on the basis of
645 * the load owner of that set. Later loaded configurations can depend on
646 * features loaded earlier.
648 * Therefore, unload is only possible if:-
649 * 1) no configurations are active.
650 * 2) the set being unloaded was the last to be loaded to maintain dependencies.
652 * Once the unload operation commences, we disallow any configuration being
653 * made active until it is complete.
655 * @owner_info: Information on owner for set being unloaded.
657 int cscfg_unload_config_sets(struct cscfg_load_owner_info
*owner_info
)
660 struct cscfg_load_owner_info
*load_list_item
= NULL
;
662 mutex_lock(&cscfg_mutex
);
663 if (cscfg_mgr
->load_state
!= CSCFG_NONE
) {
664 mutex_unlock(&cscfg_mutex
);
668 /* unload op in progress also prevents activation of any config */
669 cscfg_mgr
->load_state
= CSCFG_UNLOAD
;
671 /* cannot unload if anything is active */
672 if (atomic_read(&cscfg_mgr
->sys_active_cnt
)) {
677 /* cannot unload if not last loaded in load order */
678 if (!list_empty(&cscfg_mgr
->load_order_list
)) {
679 load_list_item
= list_last_entry(&cscfg_mgr
->load_order_list
,
680 struct cscfg_load_owner_info
, item
);
681 if (load_list_item
!= owner_info
)
682 load_list_item
= NULL
;
685 if (!load_list_item
) {
690 /* remove from configfs - again outside the scope of the list mutex */
691 mutex_unlock(&cscfg_mutex
);
692 cscfg_fs_unregister_cfgs_feats(owner_info
);
693 mutex_lock(&cscfg_mutex
);
695 /* unload everything from lists belonging to load_owner */
696 cscfg_unload_owned_cfgs_feats(owner_info
);
698 /* remove from load order list */
699 if (!list_is_singular(&cscfg_mgr
->load_order_list
)) {
700 /* unlock previous item in load order list */
701 cscfg_owner_put(list_prev_entry(owner_info
, item
));
703 list_del(&owner_info
->item
);
706 cscfg_mgr
->load_state
= CSCFG_NONE
;
707 mutex_unlock(&cscfg_mutex
);
710 EXPORT_SYMBOL_GPL(cscfg_unload_config_sets
);
712 /* Handle coresight device registration and add configs and features to devices */
714 /* iterate through config lists and load matching configs to device */
715 static int cscfg_add_cfgs_csdev(struct coresight_device
*csdev
)
717 struct cscfg_config_desc
*config_desc
;
720 list_for_each_entry(config_desc
, &cscfg_mgr
->config_desc_list
, item
) {
721 err
= cscfg_add_csdev_cfg(csdev
, config_desc
);
728 /* iterate through feature lists and load matching features to device */
729 static int cscfg_add_feats_csdev(struct coresight_device
*csdev
,
731 struct cscfg_csdev_feat_ops
*ops
)
733 struct cscfg_feature_desc
*feat_desc
;
739 list_for_each_entry(feat_desc
, &cscfg_mgr
->feat_desc_list
, item
) {
740 if (feat_desc
->match_flags
& match_flags
) {
741 err
= cscfg_load_feat_csdev(csdev
, feat_desc
, ops
);
749 /* Add coresight device to list and copy its matching info */
750 static int cscfg_list_add_csdev(struct coresight_device
*csdev
,
752 struct cscfg_csdev_feat_ops
*ops
)
754 struct cscfg_registered_csdev
*csdev_item
;
756 /* allocate the list entry structure */
757 csdev_item
= kzalloc(sizeof(struct cscfg_registered_csdev
), GFP_KERNEL
);
761 csdev_item
->csdev
= csdev
;
762 csdev_item
->match_flags
= match_flags
;
763 csdev_item
->ops
.load_feat
= ops
->load_feat
;
764 list_add(&csdev_item
->item
, &cscfg_mgr
->csdev_desc_list
);
766 INIT_LIST_HEAD(&csdev
->feature_csdev_list
);
767 INIT_LIST_HEAD(&csdev
->config_csdev_list
);
768 spin_lock_init(&csdev
->cscfg_csdev_lock
);
773 /* remove a coresight device from the list and free data */
774 static void cscfg_list_remove_csdev(struct coresight_device
*csdev
)
776 struct cscfg_registered_csdev
*csdev_item
, *tmp
;
778 list_for_each_entry_safe(csdev_item
, tmp
, &cscfg_mgr
->csdev_desc_list
, item
) {
779 if (csdev_item
->csdev
== csdev
) {
780 list_del(&csdev_item
->item
);
788 * cscfg_register_csdev - register a coresight device with the syscfg manager.
790 * Registers the coresight device with the system. @match_flags used to check
791 * if the device is a match for registered features. Any currently registered
792 * configurations and features that match the device will be loaded onto it.
794 * @csdev: The coresight device to register.
795 * @match_flags: Matching information to load features.
796 * @ops: Standard operations supported by the device.
798 int cscfg_register_csdev(struct coresight_device
*csdev
,
800 struct cscfg_csdev_feat_ops
*ops
)
804 mutex_lock(&cscfg_mutex
);
806 /* add device to list of registered devices */
807 ret
= cscfg_list_add_csdev(csdev
, match_flags
, ops
);
809 goto reg_csdev_unlock
;
811 /* now load any registered features and configs matching the device. */
812 ret
= cscfg_add_feats_csdev(csdev
, match_flags
, ops
);
814 cscfg_list_remove_csdev(csdev
);
815 goto reg_csdev_unlock
;
818 ret
= cscfg_add_cfgs_csdev(csdev
);
820 cscfg_list_remove_csdev(csdev
);
821 goto reg_csdev_unlock
;
824 pr_info("CSCFG registered %s", dev_name(&csdev
->dev
));
827 mutex_unlock(&cscfg_mutex
);
830 EXPORT_SYMBOL_GPL(cscfg_register_csdev
);
833 * cscfg_unregister_csdev - remove coresight device from syscfg manager.
835 * @csdev: Device to remove.
837 void cscfg_unregister_csdev(struct coresight_device
*csdev
)
839 mutex_lock(&cscfg_mutex
);
840 cscfg_list_remove_csdev(csdev
);
841 mutex_unlock(&cscfg_mutex
);
843 EXPORT_SYMBOL_GPL(cscfg_unregister_csdev
);
846 * cscfg_csdev_reset_feats - reset features for a CoreSight device.
848 * Resets all parameters and register values for any features loaded
849 * into @csdev to their default values.
851 * @csdev: The CoreSight device.
853 void cscfg_csdev_reset_feats(struct coresight_device
*csdev
)
855 struct cscfg_feature_csdev
*feat_csdev
;
858 spin_lock_irqsave(&csdev
->cscfg_csdev_lock
, flags
);
859 if (list_empty(&csdev
->feature_csdev_list
))
862 list_for_each_entry(feat_csdev
, &csdev
->feature_csdev_list
, node
)
863 cscfg_reset_feat(feat_csdev
);
866 spin_unlock_irqrestore(&csdev
->cscfg_csdev_lock
, flags
);
868 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats
);
871 * This activate configuration for either perf or sysfs. Perf can have multiple
872 * active configs, selected per event, sysfs is limited to one.
874 * Increments the configuration descriptor active count and the global active
877 * @cfg_hash: Hash value of the selected configuration name.
879 static int _cscfg_activate_config(unsigned long cfg_hash
)
881 struct cscfg_config_desc
*config_desc
;
884 if (cscfg_mgr
->load_state
== CSCFG_UNLOAD
)
887 list_for_each_entry(config_desc
, &cscfg_mgr
->config_desc_list
, item
) {
888 if ((unsigned long)config_desc
->event_ea
->var
== cfg_hash
) {
889 /* if we happen upon a partly loaded config, can't use it */
890 if (config_desc
->available
== false)
893 /* must ensure that config cannot be unloaded in use */
894 err
= cscfg_owner_get(config_desc
->load_owner
);
898 * increment the global active count - control changes to
899 * active configurations
901 atomic_inc(&cscfg_mgr
->sys_active_cnt
);
904 * mark the descriptor as active so enable config on a
905 * device instance will use it
907 atomic_inc(&config_desc
->active_cnt
);
910 dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc
->name
);
917 static void _cscfg_deactivate_config(unsigned long cfg_hash
)
919 struct cscfg_config_desc
*config_desc
;
921 list_for_each_entry(config_desc
, &cscfg_mgr
->config_desc_list
, item
) {
922 if ((unsigned long)config_desc
->event_ea
->var
== cfg_hash
) {
923 atomic_dec(&config_desc
->active_cnt
);
924 atomic_dec(&cscfg_mgr
->sys_active_cnt
);
925 cscfg_owner_put(config_desc
->load_owner
);
926 dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc
->name
);
933 * called from configfs to set/clear the active configuration for use when
934 * using sysfs to control trace.
936 int cscfg_config_sysfs_activate(struct cscfg_config_desc
*config_desc
, bool activate
)
938 unsigned long cfg_hash
;
941 mutex_lock(&cscfg_mutex
);
943 cfg_hash
= (unsigned long)config_desc
->event_ea
->var
;
946 /* cannot be a current active value to activate this */
947 if (cscfg_mgr
->sysfs_active_config
) {
951 err
= _cscfg_activate_config(cfg_hash
);
953 cscfg_mgr
->sysfs_active_config
= cfg_hash
;
955 /* disable if matching current value */
956 if (cscfg_mgr
->sysfs_active_config
== cfg_hash
) {
957 _cscfg_deactivate_config(cfg_hash
);
958 cscfg_mgr
->sysfs_active_config
= 0;
964 mutex_unlock(&cscfg_mutex
);
968 /* set the sysfs preset value */
969 void cscfg_config_sysfs_set_preset(int preset
)
971 mutex_lock(&cscfg_mutex
);
972 cscfg_mgr
->sysfs_active_preset
= preset
;
973 mutex_unlock(&cscfg_mutex
);
977 * Used by a device to get the config and preset selected as active in configfs,
978 * when using sysfs to control trace.
980 void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash
, int *preset
)
982 mutex_lock(&cscfg_mutex
);
983 *preset
= cscfg_mgr
->sysfs_active_preset
;
984 *cfg_hash
= cscfg_mgr
->sysfs_active_config
;
985 mutex_unlock(&cscfg_mutex
);
987 EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg
);
990 * cscfg_activate_config - Mark a configuration descriptor as active.
992 * This will be seen when csdev devices are enabled in the system.
993 * Only activated configurations can be enabled on individual devices.
994 * Activation protects the configuration from alteration or removal while
997 * Selection by hash value - generated from the configuration name when it
998 * was loaded and added to the cs_etm/configurations file system for selection
1001 * @cfg_hash: Hash value of the selected configuration name.
1003 int cscfg_activate_config(unsigned long cfg_hash
)
1007 mutex_lock(&cscfg_mutex
);
1008 err
= _cscfg_activate_config(cfg_hash
);
1009 mutex_unlock(&cscfg_mutex
);
1013 EXPORT_SYMBOL_GPL(cscfg_activate_config
);
1016 * cscfg_deactivate_config - Mark a config descriptor as inactive.
1018 * Decrement the configuration and global active counts.
1020 * @cfg_hash: Hash value of the selected configuration name.
1022 void cscfg_deactivate_config(unsigned long cfg_hash
)
1024 mutex_lock(&cscfg_mutex
);
1025 _cscfg_deactivate_config(cfg_hash
);
1026 mutex_unlock(&cscfg_mutex
);
1028 EXPORT_SYMBOL_GPL(cscfg_deactivate_config
);
1031 * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
1033 * Enables the configuration selected by @cfg_hash if the configuration is supported
1034 * on the device and has been activated.
1036 * If active and supported the CoreSight device @csdev will be programmed with the
1037 * configuration, using @preset parameters.
1039 * Should be called before driver hardware enable for the requested device, prior to
1040 * programming and enabling the physical hardware.
1042 * @csdev: CoreSight device to program.
1043 * @cfg_hash: Selector for the configuration.
1044 * @preset: Preset parameter values to use, 0 for current / default values.
1046 int cscfg_csdev_enable_active_config(struct coresight_device
*csdev
,
1047 unsigned long cfg_hash
, int preset
)
1049 struct cscfg_config_csdev
*config_csdev_active
= NULL
, *config_csdev_item
;
1050 const struct cscfg_config_desc
*config_desc
;
1051 unsigned long flags
;
1054 /* quickly check global count */
1055 if (!atomic_read(&cscfg_mgr
->sys_active_cnt
))
1059 * Look for matching configuration - set the active configuration
1062 spin_lock_irqsave(&csdev
->cscfg_csdev_lock
, flags
);
1063 list_for_each_entry(config_csdev_item
, &csdev
->config_csdev_list
, node
) {
1064 config_desc
= config_csdev_item
->config_desc
;
1065 if ((atomic_read(&config_desc
->active_cnt
)) &&
1066 ((unsigned long)config_desc
->event_ea
->var
== cfg_hash
)) {
1067 config_csdev_active
= config_csdev_item
;
1068 csdev
->active_cscfg_ctxt
= (void *)config_csdev_active
;
1072 spin_unlock_irqrestore(&csdev
->cscfg_csdev_lock
, flags
);
1075 * If found, attempt to enable
1077 if (config_csdev_active
) {
1079 * Call the generic routine that will program up the internal
1080 * driver structures prior to programming up the hardware.
1081 * This routine takes the driver spinlock saved in the configs.
1083 err
= cscfg_csdev_enable_config(config_csdev_active
, preset
);
1086 * Successful programming. Check the active_cscfg_ctxt
1087 * pointer to ensure no pre-emption disabled it via
1088 * cscfg_csdev_disable_active_config() before
1091 * Set enabled if OK, err if not.
1093 spin_lock_irqsave(&csdev
->cscfg_csdev_lock
, flags
);
1094 if (csdev
->active_cscfg_ctxt
)
1095 config_csdev_active
->enabled
= true;
1098 spin_unlock_irqrestore(&csdev
->cscfg_csdev_lock
, flags
);
1103 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config
);
1106 * cscfg_csdev_disable_active_config - disable an active config on the device.
1108 * Disables the active configuration on the CoreSight device @csdev.
1109 * Disable will save the values of any registers marked in the configurations
1110 * as save on disable.
1112 * Should be called after driver hardware disable for the requested device,
1113 * after disabling the physical hardware and reading back registers.
1115 * @csdev: The CoreSight device.
1117 void cscfg_csdev_disable_active_config(struct coresight_device
*csdev
)
1119 struct cscfg_config_csdev
*config_csdev
;
1120 unsigned long flags
;
1123 * Check if we have an active config, and that it was successfully enabled.
1124 * If it was not enabled, we have no work to do, otherwise mark as disabled.
1125 * Clear the active config pointer.
1127 spin_lock_irqsave(&csdev
->cscfg_csdev_lock
, flags
);
1128 config_csdev
= (struct cscfg_config_csdev
*)csdev
->active_cscfg_ctxt
;
1130 if (!config_csdev
->enabled
)
1131 config_csdev
= NULL
;
1133 config_csdev
->enabled
= false;
1135 csdev
->active_cscfg_ctxt
= NULL
;
1136 spin_unlock_irqrestore(&csdev
->cscfg_csdev_lock
, flags
);
1138 /* true if there was an enabled active config */
1140 cscfg_csdev_disable_config(config_csdev
);
1142 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config
);
1144 /* Initialise system configuration management device. */
1146 struct device
*cscfg_device(void)
1148 return cscfg_mgr
? &cscfg_mgr
->dev
: NULL
;
1151 /* Must have a release function or the kernel will complain on module unload */
1152 static void cscfg_dev_release(struct device
*dev
)
1154 mutex_lock(&cscfg_mutex
);
1157 mutex_unlock(&cscfg_mutex
);
1160 /* a device is needed to "own" some kernel elements such as sysfs entries. */
1161 static int cscfg_create_device(void)
1166 mutex_lock(&cscfg_mutex
);
1169 goto create_dev_exit_unlock
;
1172 cscfg_mgr
= kzalloc(sizeof(struct cscfg_manager
), GFP_KERNEL
);
1174 goto create_dev_exit_unlock
;
1176 /* initialise the cscfg_mgr structure */
1177 INIT_LIST_HEAD(&cscfg_mgr
->csdev_desc_list
);
1178 INIT_LIST_HEAD(&cscfg_mgr
->feat_desc_list
);
1179 INIT_LIST_HEAD(&cscfg_mgr
->config_desc_list
);
1180 INIT_LIST_HEAD(&cscfg_mgr
->load_order_list
);
1181 atomic_set(&cscfg_mgr
->sys_active_cnt
, 0);
1182 cscfg_mgr
->load_state
= CSCFG_NONE
;
1184 /* setup the device */
1185 dev
= cscfg_device();
1186 dev
->release
= cscfg_dev_release
;
1187 dev
->init_name
= "cs_system_cfg";
1189 err
= device_register(dev
);
1193 create_dev_exit_unlock
:
1194 mutex_unlock(&cscfg_mutex
);
1199 * Loading and unloading is generally on user discretion.
1200 * If exiting due to coresight module unload, we need to unload any configurations that remain,
1201 * before we unregister the configfs intrastructure.
1203 * Do this by walking the load_owner list and taking appropriate action, depending on the load
1206 static void cscfg_unload_cfgs_on_exit(void)
1208 struct cscfg_load_owner_info
*owner_info
= NULL
;
1211 * grab the mutex - even though we are exiting, some configfs files
1212 * may still be live till we dump them, so ensure list data is
1213 * protected from a race condition.
1215 mutex_lock(&cscfg_mutex
);
1216 while (!list_empty(&cscfg_mgr
->load_order_list
)) {
1218 /* remove in reverse order of loading */
1219 owner_info
= list_last_entry(&cscfg_mgr
->load_order_list
,
1220 struct cscfg_load_owner_info
, item
);
1222 /* action according to type */
1223 switch (owner_info
->type
) {
1224 case CSCFG_OWNER_PRELOAD
:
1226 * preloaded descriptors are statically allocated in
1227 * this module - just need to unload dynamic items from
1228 * csdev lists, and remove from configfs directories.
1230 pr_info("cscfg: unloading preloaded configurations\n");
1233 case CSCFG_OWNER_MODULE
:
1235 * this is an error - the loadable module must have been unloaded prior
1236 * to the coresight module unload. Therefore that module has not
1237 * correctly unloaded configs in its own exit code.
1238 * Nothing to do other than emit an error string as the static descriptor
1239 * references we need to unload will have disappeared with the module.
1241 pr_err("cscfg: ERROR: prior module failed to unload configuration\n");
1245 /* remove from configfs - outside the scope of the list mutex */
1246 mutex_unlock(&cscfg_mutex
);
1247 cscfg_fs_unregister_cfgs_feats(owner_info
);
1248 mutex_lock(&cscfg_mutex
);
1250 /* Next unload from csdev lists. */
1251 cscfg_unload_owned_cfgs_feats(owner_info
);
1254 /* remove from load order list */
1255 list_del(&owner_info
->item
);
1257 mutex_unlock(&cscfg_mutex
);
1260 static void cscfg_clear_device(void)
1262 cscfg_unload_cfgs_on_exit();
1263 cscfg_configfs_release(cscfg_mgr
);
1264 device_unregister(cscfg_device());
1267 /* Initialise system config management API device */
1268 int __init
cscfg_init(void)
1272 /* create the device and init cscfg_mgr */
1273 err
= cscfg_create_device();
1277 /* initialise configfs subsystem */
1278 err
= cscfg_configfs_init(cscfg_mgr
);
1282 /* preload built-in configurations */
1283 err
= cscfg_preload(THIS_MODULE
);
1287 dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
1291 cscfg_clear_device();
1295 void cscfg_exit(void)
1297 cscfg_clear_device();