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