1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2020 Linaro Limited, All rights reserved.
4  * Author: Mike Leach <mike.leach@linaro.org>
5  */
6 
7 #include <linux/platform_device.h>
8 #include <linux/slab.h>
9 
10 #include "coresight-config.h"
11 #include "coresight-etm-perf.h"
12 #include "coresight-syscfg.h"
13 #include "coresight-syscfg-configfs.h"
14 
15 /*
16  * cscfg_ API manages configurations and features for the entire coresight
17  * infrastructure.
18  *
19  * It allows the loading of configurations and features, and loads these into
20  * coresight devices as appropriate.
21  */
22 
23 /* protect the cscsg_data and device */
24 static DEFINE_MUTEX(cscfg_mutex);
25 
26 /* only one of these */
27 static struct cscfg_manager *cscfg_mgr;
28 
29 /* load features and configuations into the lists */
30 
31 /* get name feature instance from a coresight device list of features */
32 static struct cscfg_feature_csdev *
33 cscfg_get_feat_csdev(struct coresight_device *csdev, const char *name)
34 {
35 	struct cscfg_feature_csdev *feat_csdev = NULL;
36 
37 	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
38 		if (strcmp(feat_csdev->feat_desc->name, name) == 0)
39 			return feat_csdev;
40 	}
41 	return NULL;
42 }
43 
44 /* allocate the device config instance - with max number of used features */
45 static struct cscfg_config_csdev *
46 cscfg_alloc_csdev_cfg(struct coresight_device *csdev, int nr_feats)
47 {
48 	struct cscfg_config_csdev *config_csdev = NULL;
49 	struct device *dev = csdev->dev.parent;
50 
51 	/* this is being allocated using the devm for the coresight device */
52 	config_csdev = devm_kzalloc(dev,
53 				    offsetof(struct cscfg_config_csdev, feats_csdev[nr_feats]),
54 				    GFP_KERNEL);
55 	if (!config_csdev)
56 		return NULL;
57 
58 	config_csdev->csdev = csdev;
59 	return config_csdev;
60 }
61 
62 /* Load a config into a device if there are any feature matches between config and device */
63 static int cscfg_add_csdev_cfg(struct coresight_device *csdev,
64 			       struct cscfg_config_desc *config_desc)
65 {
66 	struct cscfg_config_csdev *config_csdev = NULL;
67 	struct cscfg_feature_csdev *feat_csdev;
68 	unsigned long flags;
69 	int i;
70 
71 	/* look at each required feature and see if it matches any feature on the device */
72 	for (i = 0; i < config_desc->nr_feat_refs; i++) {
73 		/* look for a matching name */
74 		feat_csdev = cscfg_get_feat_csdev(csdev, config_desc->feat_ref_names[i]);
75 		if (feat_csdev) {
76 			/*
77 			 * At least one feature on this device matches the config
78 			 * add a config instance to the device and a reference to the feature.
79 			 */
80 			if (!config_csdev) {
81 				config_csdev = cscfg_alloc_csdev_cfg(csdev,
82 								     config_desc->nr_feat_refs);
83 				if (!config_csdev)
84 					return -ENOMEM;
85 				config_csdev->config_desc = config_desc;
86 			}
87 			config_csdev->feats_csdev[config_csdev->nr_feat++] = feat_csdev;
88 		}
89 	}
90 	/* if matched features, add config to device.*/
91 	if (config_csdev) {
92 		spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
93 		list_add(&config_csdev->node, &csdev->config_csdev_list);
94 		spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
95 	}
96 
97 	return 0;
98 }
99 
100 /*
101  * Add the config to the set of registered devices - call with mutex locked.
102  * Iterates through devices - any device that matches one or more of the
103  * configuration features will load it, the others will ignore it.
104  */
105 static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *config_desc)
106 {
107 	struct cscfg_registered_csdev *csdev_item;
108 	int err;
109 
110 	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
111 		err = cscfg_add_csdev_cfg(csdev_item->csdev, config_desc);
112 		if (err)
113 			return err;
114 	}
115 	return 0;
116 }
117 
118 /*
119  * Allocate a feature object for load into a csdev.
120  * memory allocated using the csdev->dev object using devm managed allocator.
121  */
122 static struct cscfg_feature_csdev *
123 cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
124 {
125 	struct cscfg_feature_csdev *feat_csdev = NULL;
126 	struct device *dev = csdev->dev.parent;
127 	int i;
128 
129 	feat_csdev = devm_kzalloc(dev, sizeof(struct cscfg_feature_csdev), GFP_KERNEL);
130 	if (!feat_csdev)
131 		return NULL;
132 
133 	/* parameters are optional - could be 0 */
134 	feat_csdev->nr_params = feat_desc->nr_params;
135 
136 	/*
137 	 * if we need parameters, zero alloc the space here, the load routine in
138 	 * the csdev device driver will fill out some information according to
139 	 * feature descriptor.
140 	 */
141 	if (feat_csdev->nr_params) {
142 		feat_csdev->params_csdev = devm_kcalloc(dev, feat_csdev->nr_params,
143 							sizeof(struct cscfg_parameter_csdev),
144 							GFP_KERNEL);
145 		if (!feat_csdev->params_csdev)
146 			return NULL;
147 
148 		/*
149 		 * fill in the feature reference in the param - other fields
150 		 * handled by loader in csdev.
151 		 */
152 		for (i = 0; i < feat_csdev->nr_params; i++)
153 			feat_csdev->params_csdev[i].feat_csdev = feat_csdev;
154 	}
155 
156 	/*
157 	 * Always have registers to program - again the load routine in csdev device
158 	 * will fill out according to feature descriptor and device requirements.
159 	 */
160 	feat_csdev->nr_regs = feat_desc->nr_regs;
161 	feat_csdev->regs_csdev = devm_kcalloc(dev, feat_csdev->nr_regs,
162 					      sizeof(struct cscfg_regval_csdev),
163 					      GFP_KERNEL);
164 	if (!feat_csdev->regs_csdev)
165 		return NULL;
166 
167 	/* load the feature default values */
168 	feat_csdev->feat_desc = feat_desc;
169 	feat_csdev->csdev = csdev;
170 
171 	return feat_csdev;
172 }
173 
174 /* load one feature into one coresight device */
175 static int cscfg_load_feat_csdev(struct coresight_device *csdev,
176 				 struct cscfg_feature_desc *feat_desc,
177 				 struct cscfg_csdev_feat_ops *ops)
178 {
179 	struct cscfg_feature_csdev *feat_csdev;
180 	unsigned long flags;
181 	int err;
182 
183 	if (!ops->load_feat)
184 		return -EINVAL;
185 
186 	feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
187 	if (!feat_csdev)
188 		return -ENOMEM;
189 
190 	/* load the feature into the device */
191 	err = ops->load_feat(csdev, feat_csdev);
192 	if (err)
193 		return err;
194 
195 	/* add to internal csdev feature list & initialise using reset call */
196 	cscfg_reset_feat(feat_csdev);
197 	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
198 	list_add(&feat_csdev->node, &csdev->feature_csdev_list);
199 	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
200 
201 	return 0;
202 }
203 
204 /*
205  * Add feature to any matching devices - call with mutex locked.
206  * Iterates through devices - any device that matches the feature will be
207  * called to load it.
208  */
209 static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
210 {
211 	struct cscfg_registered_csdev *csdev_item;
212 	int err;
213 
214 	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
215 		if (csdev_item->match_flags & feat_desc->match_flags) {
216 			err = cscfg_load_feat_csdev(csdev_item->csdev, feat_desc, &csdev_item->ops);
217 			if (err)
218 				return err;
219 		}
220 	}
221 	return 0;
222 }
223 
224 /* check feature list for a named feature - call with mutex locked. */
225 static bool cscfg_match_list_feat(const char *name)
226 {
227 	struct cscfg_feature_desc *feat_desc;
228 
229 	list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
230 		if (strcmp(feat_desc->name, name) == 0)
231 			return true;
232 	}
233 	return false;
234 }
235 
236 /* check all feat needed for cfg are in the list - call with mutex locked. */
237 static int cscfg_check_feat_for_cfg(struct cscfg_config_desc *config_desc)
238 {
239 	int i;
240 
241 	for (i = 0; i < config_desc->nr_feat_refs; i++)
242 		if (!cscfg_match_list_feat(config_desc->feat_ref_names[i]))
243 			return -EINVAL;
244 	return 0;
245 }
246 
247 /*
248  * load feature - add to feature list.
249  */
250 static int cscfg_load_feat(struct cscfg_feature_desc *feat_desc)
251 {
252 	int err;
253 
254 	/* add feature to any matching registered devices */
255 	err = cscfg_add_feat_to_csdevs(feat_desc);
256 	if (err)
257 		return err;
258 
259 	list_add(&feat_desc->item, &cscfg_mgr->feat_desc_list);
260 	return 0;
261 }
262 
263 /*
264  * load config into the system - validate used features exist then add to
265  * config list.
266  */
267 static int cscfg_load_config(struct cscfg_config_desc *config_desc)
268 {
269 	int err;
270 
271 	/* validate features are present */
272 	err = cscfg_check_feat_for_cfg(config_desc);
273 	if (err)
274 		return err;
275 
276 	/* add config to any matching registered device */
277 	err = cscfg_add_cfg_to_csdevs(config_desc);
278 	if (err)
279 		return err;
280 
281 	/* add config to perf fs to allow selection */
282 	err = etm_perf_add_symlink_cscfg(cscfg_device(), config_desc);
283 	if (err)
284 		return err;
285 
286 	list_add(&config_desc->item, &cscfg_mgr->config_desc_list);
287 	atomic_set(&config_desc->active_cnt, 0);
288 	return 0;
289 }
290 
291 /* get a feature descriptor by name */
292 const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name)
293 {
294 	const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item;
295 
296 	mutex_lock(&cscfg_mutex);
297 
298 	list_for_each_entry(feat_desc_item, &cscfg_mgr->feat_desc_list, item) {
299 		if (strcmp(feat_desc_item->name, name) == 0) {
300 			feat_desc = feat_desc_item;
301 			break;
302 		}
303 	}
304 
305 	mutex_unlock(&cscfg_mutex);
306 	return feat_desc;
307 }
308 
309 /* called with cscfg_mutex held */
310 static struct cscfg_feature_csdev *
311 cscfg_csdev_get_feat_from_desc(struct coresight_device *csdev,
312 			       struct cscfg_feature_desc *feat_desc)
313 {
314 	struct cscfg_feature_csdev *feat_csdev;
315 
316 	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
317 		if (feat_csdev->feat_desc == feat_desc)
318 			return feat_csdev;
319 	}
320 	return NULL;
321 }
322 
323 int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
324 				int param_idx, u64 value)
325 {
326 	int err = 0;
327 	struct cscfg_feature_csdev *feat_csdev;
328 	struct cscfg_registered_csdev *csdev_item;
329 
330 	mutex_lock(&cscfg_mutex);
331 
332 	/* check if any config active & return busy */
333 	if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
334 		err = -EBUSY;
335 		goto unlock_exit;
336 	}
337 
338 	/* set the value */
339 	if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) {
340 		err = -EINVAL;
341 		goto unlock_exit;
342 	}
343 	feat_desc->params_desc[param_idx].value = value;
344 
345 	/* update loaded instances.*/
346 	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
347 		feat_csdev = cscfg_csdev_get_feat_from_desc(csdev_item->csdev, feat_desc);
348 		if (feat_csdev)
349 			feat_csdev->params_csdev[param_idx].current_value = value;
350 	}
351 
352 unlock_exit:
353 	mutex_unlock(&cscfg_mutex);
354 	return err;
355 }
356 
357 /**
358  * cscfg_load_config_sets - API function to load feature and config sets.
359  *
360  * Take a 0 terminated array of feature descriptors and/or configuration
361  * descriptors and load into the system.
362  * Features are loaded first to ensure configuration dependencies can be met.
363  *
364  * @config_descs: 0 terminated array of configuration descriptors.
365  * @feat_descs:   0 terminated array of feature descriptors.
366  */
367 int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
368 			   struct cscfg_feature_desc **feat_descs)
369 {
370 	int err, i = 0;
371 
372 	mutex_lock(&cscfg_mutex);
373 
374 	/* load features first */
375 	if (feat_descs) {
376 		while (feat_descs[i]) {
377 			err = cscfg_load_feat(feat_descs[i]);
378 			if (!err)
379 				err = cscfg_configfs_add_feature(feat_descs[i]);
380 			if (err) {
381 				pr_err("coresight-syscfg: Failed to load feature %s\n",
382 				       feat_descs[i]->name);
383 				goto exit_unlock;
384 			}
385 			i++;
386 		}
387 	}
388 
389 	/* next any configurations to check feature dependencies */
390 	i = 0;
391 	if (config_descs) {
392 		while (config_descs[i]) {
393 			err = cscfg_load_config(config_descs[i]);
394 			if (!err)
395 				err = cscfg_configfs_add_config(config_descs[i]);
396 			if (err) {
397 				pr_err("coresight-syscfg: Failed to load configuration %s\n",
398 				       config_descs[i]->name);
399 				goto exit_unlock;
400 			}
401 			i++;
402 		}
403 	}
404 
405 exit_unlock:
406 	mutex_unlock(&cscfg_mutex);
407 	return err;
408 }
409 EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
410 
411 /* Handle coresight device registration and add configs and features to devices */
412 
413 /* iterate through config lists and load matching configs to device */
414 static int cscfg_add_cfgs_csdev(struct coresight_device *csdev)
415 {
416 	struct cscfg_config_desc *config_desc;
417 	int err = 0;
418 
419 	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
420 		err = cscfg_add_csdev_cfg(csdev, config_desc);
421 		if (err)
422 			break;
423 	}
424 	return err;
425 }
426 
427 /* iterate through feature lists and load matching features to device */
428 static int cscfg_add_feats_csdev(struct coresight_device *csdev,
429 				 u32 match_flags,
430 				 struct cscfg_csdev_feat_ops *ops)
431 {
432 	struct cscfg_feature_desc *feat_desc;
433 	int err = 0;
434 
435 	if (!ops->load_feat)
436 		return -EINVAL;
437 
438 	list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
439 		if (feat_desc->match_flags & match_flags) {
440 			err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
441 			if (err)
442 				break;
443 		}
444 	}
445 	return err;
446 }
447 
448 /* Add coresight device to list and copy its matching info */
449 static int cscfg_list_add_csdev(struct coresight_device *csdev,
450 				u32 match_flags,
451 				struct cscfg_csdev_feat_ops *ops)
452 {
453 	struct cscfg_registered_csdev *csdev_item;
454 
455 	/* allocate the list entry structure */
456 	csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL);
457 	if (!csdev_item)
458 		return -ENOMEM;
459 
460 	csdev_item->csdev = csdev;
461 	csdev_item->match_flags = match_flags;
462 	csdev_item->ops.load_feat = ops->load_feat;
463 	list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list);
464 
465 	INIT_LIST_HEAD(&csdev->feature_csdev_list);
466 	INIT_LIST_HEAD(&csdev->config_csdev_list);
467 	spin_lock_init(&csdev->cscfg_csdev_lock);
468 
469 	return 0;
470 }
471 
472 /* remove a coresight device from the list and free data */
473 static void cscfg_list_remove_csdev(struct coresight_device *csdev)
474 {
475 	struct cscfg_registered_csdev *csdev_item, *tmp;
476 
477 	list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) {
478 		if (csdev_item->csdev == csdev) {
479 			list_del(&csdev_item->item);
480 			kfree(csdev_item);
481 			break;
482 		}
483 	}
484 }
485 
486 /**
487  * cscfg_register_csdev - register a coresight device with the syscfg manager.
488  *
489  * Registers the coresight device with the system. @match_flags used to check
490  * if the device is a match for registered features. Any currently registered
491  * configurations and features that match the device will be loaded onto it.
492  *
493  * @csdev:		The coresight device to register.
494  * @match_flags:	Matching information to load features.
495  * @ops:		Standard operations supported by the device.
496  */
497 int cscfg_register_csdev(struct coresight_device *csdev,
498 			 u32 match_flags,
499 			 struct cscfg_csdev_feat_ops *ops)
500 {
501 	int ret = 0;
502 
503 	mutex_lock(&cscfg_mutex);
504 
505 	/* add device to list of registered devices  */
506 	ret = cscfg_list_add_csdev(csdev, match_flags, ops);
507 	if (ret)
508 		goto reg_csdev_unlock;
509 
510 	/* now load any registered features and configs matching the device. */
511 	ret = cscfg_add_feats_csdev(csdev, match_flags, ops);
512 	if (ret) {
513 		cscfg_list_remove_csdev(csdev);
514 		goto reg_csdev_unlock;
515 	}
516 
517 	ret = cscfg_add_cfgs_csdev(csdev);
518 	if (ret) {
519 		cscfg_list_remove_csdev(csdev);
520 		goto reg_csdev_unlock;
521 	}
522 
523 	pr_info("CSCFG registered %s", dev_name(&csdev->dev));
524 
525 reg_csdev_unlock:
526 	mutex_unlock(&cscfg_mutex);
527 	return ret;
528 }
529 EXPORT_SYMBOL_GPL(cscfg_register_csdev);
530 
531 /**
532  * cscfg_unregister_csdev - remove coresight device from syscfg manager.
533  *
534  * @csdev: Device to remove.
535  */
536 void cscfg_unregister_csdev(struct coresight_device *csdev)
537 {
538 	mutex_lock(&cscfg_mutex);
539 	cscfg_list_remove_csdev(csdev);
540 	mutex_unlock(&cscfg_mutex);
541 }
542 EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
543 
544 /**
545  * cscfg_csdev_reset_feats - reset features for a CoreSight device.
546  *
547  * Resets all parameters and register values for any features loaded
548  * into @csdev to their default values.
549  *
550  * @csdev: The CoreSight device.
551  */
552 void cscfg_csdev_reset_feats(struct coresight_device *csdev)
553 {
554 	struct cscfg_feature_csdev *feat_csdev;
555 	unsigned long flags;
556 
557 	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
558 	if (list_empty(&csdev->feature_csdev_list))
559 		goto unlock_exit;
560 
561 	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
562 		cscfg_reset_feat(feat_csdev);
563 
564 unlock_exit:
565 	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
566 }
567 EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
568 
569 /**
570  * cscfg_activate_config -  Mark a configuration descriptor as active.
571  *
572  * This will be seen when csdev devices are enabled in the system.
573  * Only activated configurations can be enabled on individual devices.
574  * Activation protects the configuration from alteration or removal while
575  * active.
576  *
577  * Selection by hash value - generated from the configuration name when it
578  * was loaded and added to the cs_etm/configurations file system for selection
579  * by perf.
580  *
581  * Increments the configuration descriptor active count and the global active
582  * count.
583  *
584  * @cfg_hash: Hash value of the selected configuration name.
585  */
586 int cscfg_activate_config(unsigned long cfg_hash)
587 {
588 	struct cscfg_config_desc *config_desc;
589 	int err = -EINVAL;
590 
591 	mutex_lock(&cscfg_mutex);
592 
593 	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
594 		if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
595 			/*
596 			 * increment the global active count - control changes to
597 			 * active configurations
598 			 */
599 			atomic_inc(&cscfg_mgr->sys_active_cnt);
600 
601 			/*
602 			 * mark the descriptor as active so enable config on a
603 			 * device instance will use it
604 			 */
605 			atomic_inc(&config_desc->active_cnt);
606 
607 			err = 0;
608 			dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
609 			break;
610 		}
611 	}
612 	mutex_unlock(&cscfg_mutex);
613 
614 	return err;
615 }
616 EXPORT_SYMBOL_GPL(cscfg_activate_config);
617 
618 /**
619  * cscfg_deactivate_config -  Mark a config descriptor as inactive.
620  *
621  * Decrement the configuration and global active counts.
622  *
623  * @cfg_hash: Hash value of the selected configuration name.
624  */
625 void cscfg_deactivate_config(unsigned long cfg_hash)
626 {
627 	struct cscfg_config_desc *config_desc;
628 
629 	mutex_lock(&cscfg_mutex);
630 
631 	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
632 		if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
633 			atomic_dec(&config_desc->active_cnt);
634 			atomic_dec(&cscfg_mgr->sys_active_cnt);
635 			dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
636 			break;
637 		}
638 	}
639 	mutex_unlock(&cscfg_mutex);
640 }
641 EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
642 
643 /**
644  * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
645  *
646  * Enables the configuration selected by @cfg_hash if the configuration is supported
647  * on the device and has been activated.
648  *
649  * If active and supported the CoreSight device @csdev will be programmed with the
650  * configuration, using @preset parameters.
651  *
652  * Should be called before driver hardware enable for the requested device, prior to
653  * programming and enabling the physical hardware.
654  *
655  * @csdev:	CoreSight device to program.
656  * @cfg_hash:	Selector for the configuration.
657  * @preset:	Preset parameter values to use, 0 for current / default values.
658  */
659 int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
660 				     unsigned long cfg_hash, int preset)
661 {
662 	struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
663 	const struct cscfg_config_desc *config_desc;
664 	unsigned long flags;
665 	int err = 0;
666 
667 	/* quickly check global count */
668 	if (!atomic_read(&cscfg_mgr->sys_active_cnt))
669 		return 0;
670 
671 	/*
672 	 * Look for matching configuration - set the active configuration
673 	 * context if found.
674 	 */
675 	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
676 	list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
677 		config_desc = config_csdev_item->config_desc;
678 		if ((atomic_read(&config_desc->active_cnt)) &&
679 		    ((unsigned long)config_desc->event_ea->var == cfg_hash)) {
680 			config_csdev_active = config_csdev_item;
681 			csdev->active_cscfg_ctxt = (void *)config_csdev_active;
682 			break;
683 		}
684 	}
685 	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
686 
687 	/*
688 	 * If found, attempt to enable
689 	 */
690 	if (config_csdev_active) {
691 		/*
692 		 * Call the generic routine that will program up the internal
693 		 * driver structures prior to programming up the hardware.
694 		 * This routine takes the driver spinlock saved in the configs.
695 		 */
696 		err = cscfg_csdev_enable_config(config_csdev_active, preset);
697 		if (!err) {
698 			/*
699 			 * Successful programming. Check the active_cscfg_ctxt
700 			 * pointer to ensure no pre-emption disabled it via
701 			 * cscfg_csdev_disable_active_config() before
702 			 * we could start.
703 			 *
704 			 * Set enabled if OK, err if not.
705 			 */
706 			spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
707 			if (csdev->active_cscfg_ctxt)
708 				config_csdev_active->enabled = true;
709 			else
710 				err = -EBUSY;
711 			spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
712 		}
713 	}
714 	return err;
715 }
716 EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
717 
718 /**
719  * cscfg_csdev_disable_active_config - disable an active config on the device.
720  *
721  * Disables the active configuration on the CoreSight device @csdev.
722  * Disable will save the values of any registers marked in the configurations
723  * as save on disable.
724  *
725  * Should be called after driver hardware disable for the requested device,
726  * after disabling the physical hardware and reading back registers.
727  *
728  * @csdev: The CoreSight device.
729  */
730 void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
731 {
732 	struct cscfg_config_csdev *config_csdev;
733 	unsigned long flags;
734 
735 	/*
736 	 * Check if we have an active config, and that it was successfully enabled.
737 	 * If it was not enabled, we have no work to do, otherwise mark as disabled.
738 	 * Clear the active config pointer.
739 	 */
740 	spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
741 	config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
742 	if (config_csdev) {
743 		if (!config_csdev->enabled)
744 			config_csdev = NULL;
745 		else
746 			config_csdev->enabled = false;
747 	}
748 	csdev->active_cscfg_ctxt = NULL;
749 	spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
750 
751 	/* true if there was an enabled active config */
752 	if (config_csdev)
753 		cscfg_csdev_disable_config(config_csdev);
754 }
755 EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
756 
757 /* Initialise system configuration management device. */
758 
759 struct device *cscfg_device(void)
760 {
761 	return cscfg_mgr ? &cscfg_mgr->dev : NULL;
762 }
763 
764 /* Must have a release function or the kernel will complain on module unload */
765 static void cscfg_dev_release(struct device *dev)
766 {
767 	kfree(cscfg_mgr);
768 	cscfg_mgr = NULL;
769 }
770 
771 /* a device is needed to "own" some kernel elements such as sysfs entries.  */
772 static int cscfg_create_device(void)
773 {
774 	struct device *dev;
775 	int err = -ENOMEM;
776 
777 	mutex_lock(&cscfg_mutex);
778 	if (cscfg_mgr) {
779 		err = -EINVAL;
780 		goto create_dev_exit_unlock;
781 	}
782 
783 	cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
784 	if (!cscfg_mgr)
785 		goto create_dev_exit_unlock;
786 
787 	/* setup the device */
788 	dev = cscfg_device();
789 	dev->release = cscfg_dev_release;
790 	dev->init_name = "cs_system_cfg";
791 
792 	err = device_register(dev);
793 	if (err)
794 		cscfg_dev_release(dev);
795 
796 create_dev_exit_unlock:
797 	mutex_unlock(&cscfg_mutex);
798 	return err;
799 }
800 
801 static void cscfg_clear_device(void)
802 {
803 	struct cscfg_config_desc *cfg_desc;
804 
805 	mutex_lock(&cscfg_mutex);
806 	list_for_each_entry(cfg_desc, &cscfg_mgr->config_desc_list, item) {
807 		etm_perf_del_symlink_cscfg(cfg_desc);
808 	}
809 	cscfg_configfs_release(cscfg_mgr);
810 	device_unregister(cscfg_device());
811 	mutex_unlock(&cscfg_mutex);
812 }
813 
814 /* Initialise system config management API device  */
815 int __init cscfg_init(void)
816 {
817 	int err = 0;
818 
819 	err = cscfg_create_device();
820 	if (err)
821 		return err;
822 
823 	err = cscfg_configfs_init(cscfg_mgr);
824 	if (err)
825 		goto exit_err;
826 
827 	INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list);
828 	INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list);
829 	INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
830 	atomic_set(&cscfg_mgr->sys_active_cnt, 0);
831 
832 	/* preload built-in configurations */
833 	err = cscfg_preload();
834 	if (err)
835 		goto exit_err;
836 
837 	dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
838 	return 0;
839 
840 exit_err:
841 	cscfg_clear_device();
842 	return err;
843 }
844 
845 void cscfg_exit(void)
846 {
847 	cscfg_clear_device();
848 }
849