cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

coresight-syscfg.c (31260B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (c) 2020 Linaro Limited, All rights reserved.
      4 * Author: Mike Leach <mike.leach@linaro.org>
      5 */
      6
      7#include <linux/platform_device.h>
      8#include <linux/slab.h>
      9
     10#include "coresight-config.h"
     11#include "coresight-etm-perf.h"
     12#include "coresight-syscfg.h"
     13#include "coresight-syscfg-configfs.h"
     14
     15/*
     16 * cscfg_ API manages configurations and features for the entire coresight
     17 * infrastructure.
     18 *
     19 * It allows the loading of configurations and features, and loads these into
     20 * coresight devices as appropriate.
     21 */
     22
     23/* protect the cscsg_data and device */
     24static DEFINE_MUTEX(cscfg_mutex);
     25
     26/* only one of these */
     27static struct cscfg_manager *cscfg_mgr;
     28
     29/* load features and configuations into the lists */
     30
     31/* get name feature instance from a coresight device list of features */
     32static struct cscfg_feature_csdev *
     33cscfg_get_feat_csdev(struct coresight_device *csdev, const char *name)
     34{
     35	struct cscfg_feature_csdev *feat_csdev = NULL;
     36
     37	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
     38		if (strcmp(feat_csdev->feat_desc->name, name) == 0)
     39			return feat_csdev;
     40	}
     41	return NULL;
     42}
     43
     44/* allocate the device config instance - with max number of used features */
     45static struct cscfg_config_csdev *
     46cscfg_alloc_csdev_cfg(struct coresight_device *csdev, int nr_feats)
     47{
     48	struct cscfg_config_csdev *config_csdev = NULL;
     49	struct device *dev = csdev->dev.parent;
     50
     51	/* this is being allocated using the devm for the coresight device */
     52	config_csdev = devm_kzalloc(dev,
     53				    offsetof(struct cscfg_config_csdev, feats_csdev[nr_feats]),
     54				    GFP_KERNEL);
     55	if (!config_csdev)
     56		return NULL;
     57
     58	config_csdev->csdev = csdev;
     59	return config_csdev;
     60}
     61
     62/* Load a config into a device if there are any feature matches between config and device */
     63static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
     64			       struct cscfg_config_desc *config_desc)
     65{
     66	struct cscfg_config_csdev *config_csdev = NULL;
     67	struct cscfg_feature_csdev *feat_csdev;
     68	unsigned long flags;
     69	int i;
     70
     71	/* look at each required feature and see if it matches any feature on the device */
     72	for (i = 0; i < config_desc->nr_feat_refs; i++) {
     73		/* look for a matching name */
     74		feat_csdev = cscfg_get_feat_csdev(csdev, config_desc->feat_ref_names[i]);
     75		if (feat_csdev) {
     76			/*
     77			 * At least one feature on this device matches the config
     78			 * add a config instance to the device and a reference to the feature.
     79			 */
     80			if (!config_csdev) {
     81				config_csdev = cscfg_alloc_csdev_cfg(csdev,
     82								     config_desc->nr_feat_refs);
     83				if (!config_csdev)
     84					return -ENOMEM;
     85				config_csdev->config_desc = config_desc;
     86			}
     87			config_csdev->feats_csdev[config_csdev->nr_feat++] = feat_csdev;
     88		}
     89	}
     90	/* if matched features, add config to device.*/
     91	if (config_csdev) {
     92		spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
     93		list_add(&config_csdev->node, &csdev->config_csdev_list);
     94		spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
     95	}
     96
     97	return 0;
     98}
     99
    100/*
    101 * Add the config to the set of registered devices - call with mutex locked.
    102 * Iterates through devices - any device that matches one or more of the
    103 * configuration features will load it, the others will ignore it.
    104 */
    105static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *config_desc)
    106{
    107	struct cscfg_registered_csdev *csdev_item;
    108	int err;
    109
    110	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
    111		err = cscfg_add_csdev_cfg(csdev_item->csdev, config_desc);
    112		if (err)
    113			return err;
    114	}
    115	return 0;
    116}
    117
    118/*
    119 * Allocate a feature object for load into a csdev.
    120 * memory allocated using the csdev->dev object using devm managed allocator.
    121 */
    122static struct cscfg_feature_csdev *
    123cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
    124{
    125	struct cscfg_feature_csdev *feat_csdev = NULL;
    126	struct device *dev = csdev->dev.parent;
    127	int i;
    128
    129	feat_csdev = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL);
    130	if (!feat_csdev)
    131		return NULL;
    132
    133	/* parameters are optional - could be 0 */
    134	feat_csdev->nr_params = feat_desc->nr_params;
    135
    136	/*
    137	 * if we need parameters, zero alloc the space here, the load routine in
    138	 * the csdev device driver will fill out some information according to
    139	 * feature descriptor.
    140	 */
    141	if (feat_csdev->nr_params) {
    142		feat_csdev->params_csdev = devm_kcalloc(dev, feat_csdev->nr_params,
    143							sizeof(struct cscfg_parameter_csdev),
    144							GFP_KERNEL);
    145		if (!feat_csdev->params_csdev)
    146			return NULL;
    147
    148		/*
    149		 * fill in the feature reference in the param - other fields
    150		 * handled by loader in csdev.
    151		 */
    152		for (i = 0; i < feat_csdev->nr_params; i++)
    153			feat_csdev->params_csdev[i].feat_csdev = feat_csdev;
    154	}
    155
    156	/*
    157	 * Always have registers to program - again the load routine in csdev device
    158	 * will fill out according to feature descriptor and device requirements.
    159	 */
    160	feat_csdev->nr_regs = feat_desc->nr_regs;
    161	feat_csdev->regs_csdev = devm_kcalloc(dev, feat_csdev->nr_regs,
    162					      sizeof(struct cscfg_regval_csdev),
    163					      GFP_KERNEL);
    164	if (!feat_csdev->regs_csdev)
    165		return NULL;
    166
    167	/* load the feature default values */
    168	feat_csdev->feat_desc = feat_desc;
    169	feat_csdev->csdev = csdev;
    170
    171	return feat_csdev;
    172}
    173
    174/* load one feature into one coresight device */
    175static int cscfg_load_feat_csdev(struct coresight_device *csdev,
    176				 struct cscfg_feature_desc *feat_desc,
    177				 struct cscfg_csdev_feat_ops *ops)
    178{
    179	struct cscfg_feature_csdev *feat_csdev;
    180	unsigned long flags;
    181	int err;
    182
    183	if (!ops->load_feat)
    184		return -EINVAL;
    185
    186	feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
    187	if (!feat_csdev)
    188		return -ENOMEM;
    189
    190	/* load the feature into the device */
    191	err = ops->load_feat(csdev, feat_csdev);
    192	if (err)
    193		return err;
    194
    195	/* add to internal csdev feature list & initialise using reset call */
    196	cscfg_reset_feat(feat_csdev);
    197	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
    198	list_add(&feat_csdev->node, &csdev->feature_csdev_list);
    199	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
    200
    201	return 0;
    202}
    203
    204/*
    205 * Add feature to any matching devices - call with mutex locked.
    206 * Iterates through devices - any device that matches the feature will be
    207 * called to load it.
    208 */
    209static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
    210{
    211	struct cscfg_registered_csdev *csdev_item;
    212	int err;
    213
    214	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
    215		if (csdev_item->match_flags & feat_desc->match_flags) {
    216			err = cscfg_load_feat_csdev(csdev_item->csdev, feat_desc, &csdev_item->ops);
    217			if (err)
    218				return err;
    219		}
    220	}
    221	return 0;
    222}
    223
    224/* check feature list for a named feature - call with mutex locked. */
    225static bool cscfg_match_list_feat(const char *name)
    226{
    227	struct cscfg_feature_desc *feat_desc;
    228
    229	list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
    230		if (strcmp(feat_desc->name, name) == 0)
    231			return true;
    232	}
    233	return false;
    234}
    235
    236/* check all feat needed for cfg are in the list - call with mutex locked. */
    237static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *config_desc)
    238{
    239	int i;
    240
    241	for (i = 0; i < config_desc->nr_feat_refs; i++)
    242		if (!cscfg_match_list_feat(config_desc->feat_ref_names[i]))
    243			return -EINVAL;
    244	return 0;
    245}
    246
    247/*
    248 * load feature - add to feature list.
    249 */
    250static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc)
    251{
    252	int err;
    253	struct cscfg_feature_desc *feat_desc_exist;
    254
    255	/* new feature must have unique name */
    256	list_for_each_entry(feat_desc_exist, &cscfg_mgr->feat_desc_list, item) {
    257		if (!strcmp(feat_desc_exist->name, feat_desc->name))
    258			return -EEXIST;
    259	}
    260
    261	/* add feature to any matching registered devices */
    262	err = cscfg_add_feat_to_csdevs(feat_desc);
    263	if (err)
    264		return err;
    265
    266	list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list);
    267	return 0;
    268}
    269
    270/*
    271 * load config into the system - validate used features exist then add to
    272 * config list.
    273 */
    274static int cscfg_load_config(struct cscfg_config_desc *config_desc)
    275{
    276	int err;
    277	struct cscfg_config_desc *config_desc_exist;
    278
    279	/* new configuration must have a unique name */
    280	list_for_each_entry(config_desc_exist, &cscfg_mgr->config_desc_list, item) {
    281		if (!strcmp(config_desc_exist->name, config_desc->name))
    282			return -EEXIST;
    283	}
    284
    285	/* validate features are present */
    286	err = cscfg_check_feat_for_cfg(config_desc);
    287	if (err)
    288		return err;
    289
    290	/* add config to any matching registered device */
    291	err = cscfg_add_cfg_to_csdevs(config_desc);
    292	if (err)
    293		return err;
    294
    295	/* add config to perf fs to allow selection */
    296	err = etm_perf_add_symlink_cscfg(cscfg_device(), config_desc);
    297	if (err)
    298		return err;
    299
    300	list_add(&config_desc->item, &cscfg_mgr->config_desc_list);
    301	atomic_set(&config_desc->active_cnt, 0);
    302	return 0;
    303}
    304
    305/* get a feature descriptor by name */
    306const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name)
    307{
    308	const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item;
    309
    310	mutex_lock(&cscfg_mutex);
    311
    312	list_for_each_entry(feat_desc_item, &cscfg_mgr->feat_desc_list, item) {
    313		if (strcmp(feat_desc_item->name, name) == 0) {
    314			feat_desc = feat_desc_item;
    315			break;
    316		}
    317	}
    318
    319	mutex_unlock(&cscfg_mutex);
    320	return feat_desc;
    321}
    322
    323/* called with cscfg_mutex held */
    324static struct cscfg_feature_csdev *
    325cscfg_csdev_get_feat_from_desc(struct coresight_device *csdev,
    326			       struct cscfg_feature_desc *feat_desc)
    327{
    328	struct cscfg_feature_csdev *feat_csdev;
    329
    330	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
    331		if (feat_csdev->feat_desc == feat_desc)
    332			return feat_csdev;
    333	}
    334	return NULL;
    335}
    336
    337int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
    338				int param_idx, u64 value)
    339{
    340	int err = 0;
    341	struct cscfg_feature_csdev *feat_csdev;
    342	struct cscfg_registered_csdev *csdev_item;
    343
    344	mutex_lock(&cscfg_mutex);
    345
    346	/* check if any config active & return busy */
    347	if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
    348		err = -EBUSY;
    349		goto unlock_exit;
    350	}
    351
    352	/* set the value */
    353	if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) {
    354		err = -EINVAL;
    355		goto unlock_exit;
    356	}
    357	feat_desc->params_desc[param_idx].value = value;
    358
    359	/* update loaded instances.*/
    360	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
    361		feat_csdev = cscfg_csdev_get_feat_from_desc(csdev_item->csdev, feat_desc);
    362		if (feat_csdev)
    363			feat_csdev->params_csdev[param_idx].current_value = value;
    364	}
    365
    366unlock_exit:
    367	mutex_unlock(&cscfg_mutex);
    368	return err;
    369}
    370
    371/*
    372 * Conditionally up reference count on owner to prevent unload.
    373 *
    374 * module loaded configs need to be locked in to prevent premature unload.
    375 */
    376static int cscfg_owner_get(struct cscfg_load_owner_info *owner_info)
    377{
    378	if ((owner_info->type == CSCFG_OWNER_MODULE) &&
    379	    (!try_module_get(owner_info->owner_handle)))
    380		return -EINVAL;
    381	return 0;
    382}
    383
    384/* conditionally lower ref count on an owner */
    385static void cscfg_owner_put(struct cscfg_load_owner_info *owner_info)
    386{
    387	if (owner_info->type == CSCFG_OWNER_MODULE)
    388		module_put(owner_info->owner_handle);
    389}
    390
    391static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, void *load_owner)
    392{
    393	struct cscfg_config_csdev *config_csdev, *tmp;
    394
    395	if (list_empty(&csdev->config_csdev_list))
    396		return;
    397
    398	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);
    401	}
    402}
    403
    404static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
    405{
    406	struct cscfg_feature_csdev *feat_csdev, *tmp;
    407
    408	if (list_empty(&csdev->feature_csdev_list))
    409		return;
    410
    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);
    414	}
    415}
    416
    417/*
    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
    421 * devices.
    422 */
    423static void cscfg_unload_owned_cfgs_feats(void *load_owner)
    424{
    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;
    428
    429	/* remove from each csdev instance feature and config lists */
    430	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
    431		/*
    432		 * for each csdev, check the loaded lists and remove if
    433		 * referenced descriptor is owned
    434		 */
    435		cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner);
    436		cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner);
    437	}
    438
    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);
    445		}
    446	}
    447
    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);
    453		}
    454	}
    455}
    456
    457/**
    458 * cscfg_load_config_sets - API function to load feature and config sets.
    459 *
    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.
    463 *
    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.
    470 *
    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.
    474 */
    475int 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)
    478{
    479	int err = 0, i = 0;
    480
    481	mutex_lock(&cscfg_mutex);
    482
    483	/* load features first */
    484	if (feat_descs) {
    485		while (feat_descs[i]) {
    486			err = cscfg_load_feat(feat_descs[i]);
    487			if (!err)
    488				err = cscfg_configfs_add_feature(feat_descs[i]);
    489			if (err) {
    490				pr_err("coresight-syscfg: Failed to load feature %s\n",
    491				       feat_descs[i]->name);
    492				cscfg_unload_owned_cfgs_feats(owner_info);
    493				goto exit_unlock;
    494			}
    495			feat_descs[i]->load_owner = owner_info;
    496			i++;
    497		}
    498	}
    499
    500	/* next any configurations to check feature dependencies */
    501	i = 0;
    502	if (config_descs) {
    503		while (config_descs[i]) {
    504			err = cscfg_load_config(config_descs[i]);
    505			if (!err)
    506				err = cscfg_configfs_add_config(config_descs[i]);
    507			if (err) {
    508				pr_err("coresight-syscfg: Failed to load configuration %s\n",
    509				       config_descs[i]->name);
    510				cscfg_unload_owned_cfgs_feats(owner_info);
    511				goto exit_unlock;
    512			}
    513			config_descs[i]->load_owner = owner_info;
    514			i++;
    515		}
    516	}
    517
    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));
    523		if (err) {
    524			cscfg_unload_owned_cfgs_feats(owner_info);
    525			list_del(&owner_info->item);
    526		}
    527	}
    528
    529exit_unlock:
    530	mutex_unlock(&cscfg_mutex);
    531	return err;
    532}
    533EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
    534
    535/**
    536 * cscfg_unload_config_sets - unload a set of configurations by owner.
    537 *
    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.
    541 *
    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.
    545 *
    546 * @owner_info:	Information on owner for set being unloaded.
    547 */
    548int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info)
    549{
    550	int err = 0;
    551	struct cscfg_load_owner_info *load_list_item = NULL;
    552
    553	mutex_lock(&cscfg_mutex);
    554
    555	/* cannot unload if anything is active */
    556	if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
    557		err = -EBUSY;
    558		goto exit_unlock;
    559	}
    560
    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;
    567	}
    568
    569	if (!load_list_item) {
    570		err = -EINVAL;
    571		goto exit_unlock;
    572	}
    573
    574	/* unload all belonging to load_owner */
    575	cscfg_unload_owned_cfgs_feats(owner_info);
    576
    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));
    581	}
    582	list_del(&owner_info->item);
    583
    584exit_unlock:
    585	mutex_unlock(&cscfg_mutex);
    586	return err;
    587}
    588EXPORT_SYMBOL_GPL(cscfg_unload_config_sets);
    589
    590/* Handle coresight device registration and add configs and features to devices */
    591
    592/* iterate through config lists and load matching configs to device */
    593static int cscfg_add_cfgs_csdev(struct coresight_device *csdev)
    594{
    595	struct cscfg_config_desc *config_desc;
    596	int err = 0;
    597
    598	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
    599		err = cscfg_add_csdev_cfg(csdev, config_desc);
    600		if (err)
    601			break;
    602	}
    603	return err;
    604}
    605
    606/* iterate through feature lists and load matching features to device */
    607static int cscfg_add_feats_csdev(struct coresight_device *csdev,
    608				 u32 match_flags,
    609				 struct cscfg_csdev_feat_ops *ops)
    610{
    611	struct cscfg_feature_desc *feat_desc;
    612	int err = 0;
    613
    614	if (!ops->load_feat)
    615		return -EINVAL;
    616
    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);
    620			if (err)
    621				break;
    622		}
    623	}
    624	return err;
    625}
    626
    627/* Add coresight device to list and copy its matching info */
    628static int cscfg_list_add_csdev(struct coresight_device *csdev,
    629				u32 match_flags,
    630				struct cscfg_csdev_feat_ops *ops)
    631{
    632	struct cscfg_registered_csdev *csdev_item;
    633
    634	/* allocate the list entry structure */
    635	csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL);
    636	if (!csdev_item)
    637		return -ENOMEM;
    638
    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);
    643
    644	INIT_LIST_HEAD(&csdev->feature_csdev_list);
    645	INIT_LIST_HEAD(&csdev->config_csdev_list);
    646	spin_lock_init(&csdev->cscfg_csdev_lock);
    647
    648	return 0;
    649}
    650
    651/* remove a coresight device from the list and free data */
    652static void cscfg_list_remove_csdev(struct coresight_device *csdev)
    653{
    654	struct cscfg_registered_csdev *csdev_item, *tmp;
    655
    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);
    659			kfree(csdev_item);
    660			break;
    661		}
    662	}
    663}
    664
    665/**
    666 * cscfg_register_csdev - register a coresight device with the syscfg manager.
    667 *
    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.
    671 *
    672 * @csdev:		The coresight device to register.
    673 * @match_flags:	Matching information to load features.
    674 * @ops:		Standard operations supported by the device.
    675 */
    676int cscfg_register_csdev(struct coresight_device *csdev,
    677			 u32 match_flags,
    678			 struct cscfg_csdev_feat_ops *ops)
    679{
    680	int ret = 0;
    681
    682	mutex_lock(&cscfg_mutex);
    683
    684	/* add device to list of registered devices  */
    685	ret = cscfg_list_add_csdev(csdev, match_flags, ops);
    686	if (ret)
    687		goto reg_csdev_unlock;
    688
    689	/* now load any registered features and configs matching the device. */
    690	ret = cscfg_add_feats_csdev(csdev, match_flags, ops);
    691	if (ret) {
    692		cscfg_list_remove_csdev(csdev);
    693		goto reg_csdev_unlock;
    694	}
    695
    696	ret = cscfg_add_cfgs_csdev(csdev);
    697	if (ret) {
    698		cscfg_list_remove_csdev(csdev);
    699		goto reg_csdev_unlock;
    700	}
    701
    702	pr_info("CSCFG registered %s", dev_name(&csdev->dev));
    703
    704reg_csdev_unlock:
    705	mutex_unlock(&cscfg_mutex);
    706	return ret;
    707}
    708EXPORT_SYMBOL_GPL(cscfg_register_csdev);
    709
    710/**
    711 * cscfg_unregister_csdev - remove coresight device from syscfg manager.
    712 *
    713 * @csdev: Device to remove.
    714 */
    715void cscfg_unregister_csdev(struct coresight_device *csdev)
    716{
    717	mutex_lock(&cscfg_mutex);
    718	cscfg_list_remove_csdev(csdev);
    719	mutex_unlock(&cscfg_mutex);
    720}
    721EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
    722
    723/**
    724 * cscfg_csdev_reset_feats - reset features for a CoreSight device.
    725 *
    726 * Resets all parameters and register values for any features loaded
    727 * into @csdev to their default values.
    728 *
    729 * @csdev: The CoreSight device.
    730 */
    731void cscfg_csdev_reset_feats(struct coresight_device *csdev)
    732{
    733	struct cscfg_feature_csdev *feat_csdev;
    734	unsigned long flags;
    735
    736	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
    737	if (list_empty(&csdev->feature_csdev_list))
    738		goto unlock_exit;
    739
    740	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
    741		cscfg_reset_feat(feat_csdev);
    742
    743unlock_exit:
    744	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
    745}
    746EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
    747
    748/*
    749 * This activate configuration for either perf or sysfs. Perf can have multiple
    750 * active configs, selected per event, sysfs is limited to one.
    751 *
    752 * Increments the configuration descriptor active count and the global active
    753 * count.
    754 *
    755 * @cfg_hash: Hash value of the selected configuration name.
    756 */
    757static int _cscfg_activate_config(unsigned long cfg_hash)
    758{
    759	struct cscfg_config_desc *config_desc;
    760	int err = -EINVAL;
    761
    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);
    766			if (err)
    767				break;
    768			/*
    769			 * increment the global active count - control changes to
    770			 * active configurations
    771			 */
    772			atomic_inc(&cscfg_mgr->sys_active_cnt);
    773
    774			/*
    775			 * mark the descriptor as active so enable config on a
    776			 * device instance will use it
    777			 */
    778			atomic_inc(&config_desc->active_cnt);
    779
    780			err = 0;
    781			dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
    782			break;
    783		}
    784	}
    785	return err;
    786}
    787
    788static void _cscfg_deactivate_config(unsigned long cfg_hash)
    789{
    790	struct cscfg_config_desc *config_desc;
    791
    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);
    798			break;
    799		}
    800	}
    801}
    802
    803/*
    804 * called from configfs to set/clear the active configuration for use when
    805 * using sysfs to control trace.
    806 */
    807int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate)
    808{
    809	unsigned long cfg_hash;
    810	int err = 0;
    811
    812	mutex_lock(&cscfg_mutex);
    813
    814	cfg_hash = (unsigned long)config_desc->event_ea->var;
    815
    816	if (activate) {
    817		/* cannot be a current active value to activate this */
    818		if (cscfg_mgr->sysfs_active_config) {
    819			err = -EBUSY;
    820			goto exit_unlock;
    821		}
    822		err = _cscfg_activate_config(cfg_hash);
    823		if (!err)
    824			cscfg_mgr->sysfs_active_config = cfg_hash;
    825	} else {
    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;
    830		} else
    831			err = -EINVAL;
    832	}
    833
    834exit_unlock:
    835	mutex_unlock(&cscfg_mutex);
    836	return err;
    837}
    838
    839/* set the sysfs preset value */
    840void cscfg_config_sysfs_set_preset(int preset)
    841{
    842	mutex_lock(&cscfg_mutex);
    843	cscfg_mgr->sysfs_active_preset = preset;
    844	mutex_unlock(&cscfg_mutex);
    845}
    846
    847/*
    848 * Used by a device to get the config and preset selected as active in configfs,
    849 * when using sysfs to control trace.
    850 */
    851void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset)
    852{
    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);
    857}
    858EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg);
    859
    860/**
    861 * cscfg_activate_config -  Mark a configuration descriptor as active.
    862 *
    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
    866 * active.
    867 *
    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
    870 * by perf.
    871 *
    872 * @cfg_hash: Hash value of the selected configuration name.
    873 */
    874int cscfg_activate_config(unsigned long cfg_hash)
    875{
    876	int err = 0;
    877
    878	mutex_lock(&cscfg_mutex);
    879	err = _cscfg_activate_config(cfg_hash);
    880	mutex_unlock(&cscfg_mutex);
    881
    882	return err;
    883}
    884EXPORT_SYMBOL_GPL(cscfg_activate_config);
    885
    886/**
    887 * cscfg_deactivate_config -  Mark a config descriptor as inactive.
    888 *
    889 * Decrement the configuration and global active counts.
    890 *
    891 * @cfg_hash: Hash value of the selected configuration name.
    892 */
    893void cscfg_deactivate_config(unsigned long cfg_hash)
    894{
    895	mutex_lock(&cscfg_mutex);
    896	_cscfg_deactivate_config(cfg_hash);
    897	mutex_unlock(&cscfg_mutex);
    898}
    899EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
    900
    901/**
    902 * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
    903 *
    904 * Enables the configuration selected by @cfg_hash if the configuration is supported
    905 * on the device and has been activated.
    906 *
    907 * If active and supported the CoreSight device @csdev will be programmed with the
    908 * configuration, using @preset parameters.
    909 *
    910 * Should be called before driver hardware enable for the requested device, prior to
    911 * programming and enabling the physical hardware.
    912 *
    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.
    916 */
    917int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
    918				     unsigned long cfg_hash, int preset)
    919{
    920	struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
    921	const struct cscfg_config_desc *config_desc;
    922	unsigned long flags;
    923	int err = 0;
    924
    925	/* quickly check global count */
    926	if (!atomic_read(&cscfg_mgr->sys_active_cnt))
    927		return 0;
    928
    929	/*
    930	 * Look for matching configuration - set the active configuration
    931	 * context if found.
    932	 */
    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;
    940			break;
    941		}
    942	}
    943	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
    944
    945	/*
    946	 * If found, attempt to enable
    947	 */
    948	if (config_csdev_active) {
    949		/*
    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.
    953		 */
    954		err = cscfg_csdev_enable_config(config_csdev_active, preset);
    955		if (!err) {
    956			/*
    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
    960			 * we could start.
    961			 *
    962			 * Set enabled if OK, err if not.
    963			 */
    964			spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
    965			if (csdev->active_cscfg_ctxt)
    966				config_csdev_active->enabled = true;
    967			else
    968				err = -EBUSY;
    969			spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
    970		}
    971	}
    972	return err;
    973}
    974EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
    975
    976/**
    977 * cscfg_csdev_disable_active_config - disable an active config on the device.
    978 *
    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.
    982 *
    983 * Should be called after driver hardware disable for the requested device,
    984 * after disabling the physical hardware and reading back registers.
    985 *
    986 * @csdev: The CoreSight device.
    987 */
    988void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
    989{
    990	struct cscfg_config_csdev *config_csdev;
    991	unsigned long flags;
    992
    993	/*
    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.
    997	 */
    998	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
    999	config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
   1000	if (config_csdev) {
   1001		if (!config_csdev->enabled)
   1002			config_csdev = NULL;
   1003		else
   1004			config_csdev->enabled = false;
   1005	}
   1006	csdev->active_cscfg_ctxt = NULL;
   1007	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
   1008
   1009	/* true if there was an enabled active config */
   1010	if (config_csdev)
   1011		cscfg_csdev_disable_config(config_csdev);
   1012}
   1013EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
   1014
   1015/* Initialise system configuration management device. */
   1016
   1017struct device *cscfg_device(void)
   1018{
   1019	return cscfg_mgr ? &cscfg_mgr->dev : NULL;
   1020}
   1021
   1022/* Must have a release function or the kernel will complain on module unload */
   1023static void cscfg_dev_release(struct device *dev)
   1024{
   1025	kfree(cscfg_mgr);
   1026	cscfg_mgr = NULL;
   1027}
   1028
   1029/* a device is needed to "own" some kernel elements such as sysfs entries.  */
   1030static int cscfg_create_device(void)
   1031{
   1032	struct device *dev;
   1033	int err = -ENOMEM;
   1034
   1035	mutex_lock(&cscfg_mutex);
   1036	if (cscfg_mgr) {
   1037		err = -EINVAL;
   1038		goto create_dev_exit_unlock;
   1039	}
   1040
   1041	cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
   1042	if (!cscfg_mgr)
   1043		goto create_dev_exit_unlock;
   1044
   1045	/* setup the device */
   1046	dev = cscfg_device();
   1047	dev->release = cscfg_dev_release;
   1048	dev->init_name = "cs_system_cfg";
   1049
   1050	err = device_register(dev);
   1051	if (err)
   1052		put_device(dev);
   1053
   1054create_dev_exit_unlock:
   1055	mutex_unlock(&cscfg_mutex);
   1056	return err;
   1057}
   1058
   1059static void cscfg_clear_device(void)
   1060{
   1061	struct cscfg_config_desc *cfg_desc;
   1062
   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);
   1066	}
   1067	cscfg_configfs_release(cscfg_mgr);
   1068	device_unregister(cscfg_device());
   1069	mutex_unlock(&cscfg_mutex);
   1070}
   1071
   1072/* Initialise system config management API device  */
   1073int __init cscfg_init(void)
   1074{
   1075	int err = 0;
   1076
   1077	err = cscfg_create_device();
   1078	if (err)
   1079		return err;
   1080
   1081	err = cscfg_configfs_init(cscfg_mgr);
   1082	if (err)
   1083		goto exit_err;
   1084
   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);
   1090
   1091	/* preload built-in configurations */
   1092	err = cscfg_preload(THIS_MODULE);
   1093	if (err)
   1094		goto exit_err;
   1095
   1096	dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
   1097	return 0;
   1098
   1099exit_err:
   1100	cscfg_clear_device();
   1101	return err;
   1102}
   1103
   1104void cscfg_exit(void)
   1105{
   1106	cscfg_clear_device();
   1107}