File Index
Files and directories
Sign in
FILE

coresight-syscfg.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwtracing/coresight/coresight-syscfg.c C
   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		raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
  93		list_add(&config_csdev->node, &csdev->config_csdev_list);
  94		raw_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	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 198	list_add(&feat_csdev->node, &csdev->feature_csdev_list);
 199	raw_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	guard(raw_spinlock_irqsave)(&csdev->cscfg_csdev_lock);
 399
 400	list_for_each_entry_safe(config_csdev, tmp, &csdev->config_csdev_list, node) {
 401		if (config_csdev->config_desc->load_owner == load_owner)
 402			list_del(&config_csdev->node);
 403	}
 404}
 405
 406static void cscfg_remove_owned_csdev_features(struct coresight_device *csdev, void *load_owner)
 407{
 408	struct cscfg_feature_csdev *feat_csdev, *tmp;
 409
 410	if (list_empty(&csdev->feature_csdev_list))
 411		return;
 412
 413	list_for_each_entry_safe(feat_csdev, tmp, &csdev->feature_csdev_list, node) {
 414		if (feat_csdev->feat_desc->load_owner == load_owner)
 415			list_del(&feat_csdev->node);
 416	}
 417}
 418
 419/*
 420 * Unregister all configuration and features from configfs owned by load_owner.
 421 * Although this is called without the list mutex being held, it is in the
 422 * context of an unload operation which are strictly serialised,
 423 * so the lists cannot change during this call.
 424 */
 425static void cscfg_fs_unregister_cfgs_feats(void *load_owner)
 426{
 427	struct cscfg_config_desc *config_desc;
 428	struct cscfg_feature_desc *feat_desc;
 429
 430	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
 431		if (config_desc->load_owner == load_owner)
 432			cscfg_configfs_del_config(config_desc);
 433	}
 434	list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
 435		if (feat_desc->load_owner == load_owner)
 436			cscfg_configfs_del_feature(feat_desc);
 437	}
 438}
 439
 440/*
 441 * removal is relatively easy - just remove from all lists, anything that
 442 * matches the owner. Memory for the descriptors will be managed by the owner,
 443 * memory for the csdev items is devm_ allocated with the individual csdev
 444 * devices.
 445 */
 446static void cscfg_unload_owned_cfgs_feats(void *load_owner)
 447{
 448	struct cscfg_config_desc *config_desc, *cfg_tmp;
 449	struct cscfg_feature_desc *feat_desc, *feat_tmp;
 450	struct cscfg_registered_csdev *csdev_item;
 451
 452	lockdep_assert_held(&cscfg_mutex);
 453
 454	/* remove from each csdev instance feature and config lists */
 455	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
 456		/*
 457		 * for each csdev, check the loaded lists and remove if
 458		 * referenced descriptor is owned
 459		 */
 460		cscfg_remove_owned_csdev_configs(csdev_item->csdev, load_owner);
 461		cscfg_remove_owned_csdev_features(csdev_item->csdev, load_owner);
 462	}
 463
 464	/* remove from the config descriptor lists */
 465	list_for_each_entry_safe(config_desc, cfg_tmp, &cscfg_mgr->config_desc_list, item) {
 466		if (config_desc->load_owner == load_owner) {
 467			etm_perf_del_symlink_cscfg(config_desc);
 468			list_del(&config_desc->item);
 469		}
 470	}
 471
 472	/* remove from the feature descriptor lists */
 473	list_for_each_entry_safe(feat_desc, feat_tmp, &cscfg_mgr->feat_desc_list, item) {
 474		if (feat_desc->load_owner == load_owner) {
 475			list_del(&feat_desc->item);
 476		}
 477	}
 478}
 479
 480/*
 481 * load the features and configs to the lists - called with list mutex held
 482 */
 483static int cscfg_load_owned_cfgs_feats(struct cscfg_config_desc **config_descs,
 484				       struct cscfg_feature_desc **feat_descs,
 485				       struct cscfg_load_owner_info *owner_info)
 486{
 487	int i, err;
 488
 489	lockdep_assert_held(&cscfg_mutex);
 490
 491	/* load features first */
 492	if (feat_descs) {
 493		for (i = 0; feat_descs[i]; i++) {
 494			err = cscfg_load_feat(feat_descs[i]);
 495			if (err) {
 496				pr_err("coresight-syscfg: Failed to load feature %s\n",
 497				       feat_descs[i]->name);
 498				return err;
 499			}
 500			feat_descs[i]->load_owner = owner_info;
 501		}
 502	}
 503
 504	/* next any configurations to check feature dependencies */
 505	if (config_descs) {
 506		for (i = 0; config_descs[i]; i++) {
 507			err = cscfg_load_config(config_descs[i]);
 508			if (err) {
 509				pr_err("coresight-syscfg: Failed to load configuration %s\n",
 510				       config_descs[i]->name);
 511				return err;
 512			}
 513			config_descs[i]->load_owner = owner_info;
 514			config_descs[i]->available = false;
 515		}
 516	}
 517	return 0;
 518}
 519
 520/* set configurations as available to activate at the end of the load process */
 521static void cscfg_set_configs_available(struct cscfg_config_desc **config_descs)
 522{
 523	int i;
 524
 525	lockdep_assert_held(&cscfg_mutex);
 526
 527	if (config_descs) {
 528		for (i = 0; config_descs[i]; i++)
 529			config_descs[i]->available = true;
 530	}
 531}
 532
 533/*
 534 * Create and register each of the configurations and features with configfs.
 535 * Called without mutex being held.
 536 */
 537static int cscfg_fs_register_cfgs_feats(struct cscfg_config_desc **config_descs,
 538					struct cscfg_feature_desc **feat_descs)
 539{
 540	int i, err;
 541
 542	if (feat_descs) {
 543		for (i = 0; feat_descs[i]; i++) {
 544			err = cscfg_configfs_add_feature(feat_descs[i]);
 545			if (err)
 546				return err;
 547		}
 548	}
 549	if (config_descs) {
 550		for (i = 0; config_descs[i]; i++) {
 551			err = cscfg_configfs_add_config(config_descs[i]);
 552			if (err)
 553				return err;
 554		}
 555	}
 556	return 0;
 557}
 558
 559/**
 560 * cscfg_load_config_sets - API function to load feature and config sets.
 561 *
 562 * Take a 0 terminated array of feature descriptors and/or configuration
 563 * descriptors and load into the system.
 564 * Features are loaded first to ensure configuration dependencies can be met.
 565 *
 566 * To facilitate dynamic loading and unloading, features and configurations
 567 * have a "load_owner", to allow later unload by the same owner. An owner may
 568 * be a loadable module or configuration dynamically created via configfs.
 569 * As later loaded configurations can use earlier loaded features, creating load
 570 * dependencies, a load order list is maintained. Unload is strictly in the
 571 * reverse order to load.
 572 *
 573 * @config_descs: 0 terminated array of configuration descriptors.
 574 * @feat_descs:   0 terminated array of feature descriptors.
 575 * @owner_info:	  Information on the owner of this set.
 576 */
 577int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
 578			   struct cscfg_feature_desc **feat_descs,
 579			   struct cscfg_load_owner_info *owner_info)
 580{
 581	int err = 0;
 582
 583	mutex_lock(&cscfg_mutex);
 584	if (cscfg_mgr->load_state != CSCFG_NONE) {
 585		mutex_unlock(&cscfg_mutex);
 586		return -EBUSY;
 587	}
 588	cscfg_mgr->load_state = CSCFG_LOAD;
 589
 590	/* first load and add to the lists */
 591	err = cscfg_load_owned_cfgs_feats(config_descs, feat_descs, owner_info);
 592	if (err)
 593		goto err_clean_load;
 594
 595	/* add the load owner to the load order list */
 596	list_add_tail(&owner_info->item, &cscfg_mgr->load_order_list);
 597	if (!list_is_singular(&cscfg_mgr->load_order_list)) {
 598		/* lock previous item in load order list */
 599		err = cscfg_owner_get(list_prev_entry(owner_info, item));
 600		if (err)
 601			goto err_clean_owner_list;
 602	}
 603
 604	/*
 605	 * make visible to configfs - configfs manipulation must occur outside
 606	 * the list mutex lock to avoid circular lockdep issues with configfs
 607	 * built in mutexes and semaphores. This is safe as it is not possible
 608	 * to start a new load/unload operation till the current one is done.
 609	 */
 610	mutex_unlock(&cscfg_mutex);
 611
 612	/* create the configfs elements */
 613	err = cscfg_fs_register_cfgs_feats(config_descs, feat_descs);
 614	mutex_lock(&cscfg_mutex);
 615
 616	if (err)
 617		goto err_clean_cfs;
 618
 619	/* mark any new configs as available for activation */
 620	cscfg_set_configs_available(config_descs);
 621	goto exit_unlock;
 622
 623err_clean_cfs:
 624	/* cleanup after error registering with configfs */
 625	cscfg_fs_unregister_cfgs_feats(owner_info);
 626
 627	if (!list_is_singular(&cscfg_mgr->load_order_list))
 628		cscfg_owner_put(list_prev_entry(owner_info, item));
 629
 630err_clean_owner_list:
 631	list_del(&owner_info->item);
 632
 633err_clean_load:
 634	cscfg_unload_owned_cfgs_feats(owner_info);
 635
 636exit_unlock:
 637	cscfg_mgr->load_state = CSCFG_NONE;
 638	mutex_unlock(&cscfg_mutex);
 639	return err;
 640}
 641EXPORT_SYMBOL_GPL(cscfg_load_config_sets);
 642
 643/**
 644 * cscfg_unload_config_sets - unload a set of configurations by owner.
 645 *
 646 * Dynamic unload of configuration and feature sets is done on the basis of
 647 * the load owner of that set. Later loaded configurations can depend on
 648 * features loaded earlier.
 649 *
 650 * Therefore, unload is only possible if:-
 651 * 1) no configurations are active.
 652 * 2) the set being unloaded was the last to be loaded to maintain dependencies.
 653 *
 654 * Once the unload operation commences, we disallow any configuration being
 655 * made active until it is complete.
 656 *
 657 * @owner_info:	Information on owner for set being unloaded.
 658 */
 659int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info)
 660{
 661	int err = 0;
 662	struct cscfg_load_owner_info *load_list_item = NULL;
 663
 664	mutex_lock(&cscfg_mutex);
 665	if (cscfg_mgr->load_state != CSCFG_NONE) {
 666		mutex_unlock(&cscfg_mutex);
 667		return -EBUSY;
 668	}
 669
 670	/* unload op in progress also prevents activation of any config */
 671	cscfg_mgr->load_state = CSCFG_UNLOAD;
 672
 673	/* cannot unload if anything is active */
 674	if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
 675		err = -EBUSY;
 676		goto exit_unlock;
 677	}
 678
 679	/* cannot unload if not last loaded in load order */
 680	if (!list_empty(&cscfg_mgr->load_order_list)) {
 681		load_list_item = list_last_entry(&cscfg_mgr->load_order_list,
 682						 struct cscfg_load_owner_info, item);
 683		if (load_list_item != owner_info)
 684			load_list_item = NULL;
 685	}
 686
 687	if (!load_list_item) {
 688		err = -EINVAL;
 689		goto exit_unlock;
 690	}
 691
 692	/* remove from configfs - again outside the scope of the list mutex */
 693	mutex_unlock(&cscfg_mutex);
 694	cscfg_fs_unregister_cfgs_feats(owner_info);
 695	mutex_lock(&cscfg_mutex);
 696
 697	/* unload everything from lists belonging to load_owner */
 698	cscfg_unload_owned_cfgs_feats(owner_info);
 699
 700	/* remove from load order list */
 701	if (!list_is_singular(&cscfg_mgr->load_order_list)) {
 702		/* unlock previous item in load order list */
 703		cscfg_owner_put(list_prev_entry(owner_info, item));
 704	}
 705	list_del(&owner_info->item);
 706
 707exit_unlock:
 708	cscfg_mgr->load_state = CSCFG_NONE;
 709	mutex_unlock(&cscfg_mutex);
 710	return err;
 711}
 712EXPORT_SYMBOL_GPL(cscfg_unload_config_sets);
 713
 714/* Handle coresight device registration and add configs and features to devices */
 715
 716/* iterate through config lists and load matching configs to device */
 717static int cscfg_add_cfgs_csdev(struct coresight_device *csdev)
 718{
 719	struct cscfg_config_desc *config_desc;
 720	int err = 0;
 721
 722	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
 723		err = cscfg_add_csdev_cfg(csdev, config_desc);
 724		if (err)
 725			break;
 726	}
 727	return err;
 728}
 729
 730/* iterate through feature lists and load matching features to device */
 731static int cscfg_add_feats_csdev(struct coresight_device *csdev,
 732				 u32 match_flags,
 733				 struct cscfg_csdev_feat_ops *ops)
 734{
 735	struct cscfg_feature_desc *feat_desc;
 736	int err = 0;
 737
 738	if (!ops->load_feat)
 739		return -EINVAL;
 740
 741	list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
 742		if (feat_desc->match_flags & match_flags) {
 743			err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
 744			if (err)
 745				break;
 746		}
 747	}
 748	return err;
 749}
 750
 751/* Add coresight device to list and copy its matching info */
 752static int cscfg_list_add_csdev(struct coresight_device *csdev,
 753				u32 match_flags,
 754				struct cscfg_csdev_feat_ops *ops)
 755{
 756	struct cscfg_registered_csdev *csdev_item;
 757
 758	/* allocate the list entry structure */
 759	csdev_item = kzalloc(sizeof(struct cscfg_registered_csdev), GFP_KERNEL);
 760	if (!csdev_item)
 761		return -ENOMEM;
 762
 763	csdev_item->csdev = csdev;
 764	csdev_item->match_flags = match_flags;
 765	csdev_item->ops.load_feat = ops->load_feat;
 766	list_add(&csdev_item->item, &cscfg_mgr->csdev_desc_list);
 767
 768	INIT_LIST_HEAD(&csdev->feature_csdev_list);
 769	INIT_LIST_HEAD(&csdev->config_csdev_list);
 770	raw_spin_lock_init(&csdev->cscfg_csdev_lock);
 771
 772	return 0;
 773}
 774
 775/* remove a coresight device from the list and free data */
 776static void cscfg_list_remove_csdev(struct coresight_device *csdev)
 777{
 778	struct cscfg_registered_csdev *csdev_item, *tmp;
 779
 780	list_for_each_entry_safe(csdev_item, tmp, &cscfg_mgr->csdev_desc_list, item) {
 781		if (csdev_item->csdev == csdev) {
 782			list_del(&csdev_item->item);
 783			kfree(csdev_item);
 784			break;
 785		}
 786	}
 787}
 788
 789/**
 790 * cscfg_register_csdev - register a coresight device with the syscfg manager.
 791 *
 792 * Registers the coresight device with the system. @match_flags used to check
 793 * if the device is a match for registered features. Any currently registered
 794 * configurations and features that match the device will be loaded onto it.
 795 *
 796 * @csdev:		The coresight device to register.
 797 * @match_flags:	Matching information to load features.
 798 * @ops:		Standard operations supported by the device.
 799 */
 800int cscfg_register_csdev(struct coresight_device *csdev,
 801			 u32 match_flags,
 802			 struct cscfg_csdev_feat_ops *ops)
 803{
 804	int ret = 0;
 805
 806	mutex_lock(&cscfg_mutex);
 807
 808	/* add device to list of registered devices  */
 809	ret = cscfg_list_add_csdev(csdev, match_flags, ops);
 810	if (ret)
 811		goto reg_csdev_unlock;
 812
 813	/* now load any registered features and configs matching the device. */
 814	ret = cscfg_add_feats_csdev(csdev, match_flags, ops);
 815	if (ret) {
 816		cscfg_list_remove_csdev(csdev);
 817		goto reg_csdev_unlock;
 818	}
 819
 820	ret = cscfg_add_cfgs_csdev(csdev);
 821	if (ret) {
 822		cscfg_list_remove_csdev(csdev);
 823		goto reg_csdev_unlock;
 824	}
 825
 826	pr_info("CSCFG registered %s", dev_name(&csdev->dev));
 827
 828reg_csdev_unlock:
 829	mutex_unlock(&cscfg_mutex);
 830	return ret;
 831}
 832EXPORT_SYMBOL_GPL(cscfg_register_csdev);
 833
 834/**
 835 * cscfg_unregister_csdev - remove coresight device from syscfg manager.
 836 *
 837 * @csdev: Device to remove.
 838 */
 839void cscfg_unregister_csdev(struct coresight_device *csdev)
 840{
 841	mutex_lock(&cscfg_mutex);
 842	cscfg_list_remove_csdev(csdev);
 843	mutex_unlock(&cscfg_mutex);
 844}
 845EXPORT_SYMBOL_GPL(cscfg_unregister_csdev);
 846
 847/**
 848 * cscfg_csdev_reset_feats - reset features for a CoreSight device.
 849 *
 850 * Resets all parameters and register values for any features loaded
 851 * into @csdev to their default values.
 852 *
 853 * @csdev: The CoreSight device.
 854 */
 855void cscfg_csdev_reset_feats(struct coresight_device *csdev)
 856{
 857	struct cscfg_feature_csdev *feat_csdev;
 858	unsigned long flags;
 859
 860	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
 861	if (list_empty(&csdev->feature_csdev_list))
 862		goto unlock_exit;
 863
 864	list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node)
 865		cscfg_reset_feat(feat_csdev);
 866
 867unlock_exit:
 868	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
 869}
 870EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
 871
 872static bool cscfg_config_desc_get(struct cscfg_config_desc *config_desc)
 873{
 874	if (!atomic_fetch_inc(&config_desc->active_cnt)) {
 875		/* must ensure that config cannot be unloaded in use */
 876		if (unlikely(cscfg_owner_get(config_desc->load_owner))) {
 877			atomic_dec(&config_desc->active_cnt);
 878			return false;
 879		}
 880	}
 881
 882	return true;
 883}
 884
 885static void cscfg_config_desc_put(struct cscfg_config_desc *config_desc)
 886{
 887	if (!atomic_dec_return(&config_desc->active_cnt))
 888		cscfg_owner_put(config_desc->load_owner);
 889}
 890
 891/*
 892 * This activate configuration for either perf or sysfs. Perf can have multiple
 893 * active configs, selected per event, sysfs is limited to one.
 894 *
 895 * Increments the configuration descriptor active count and the global active
 896 * count.
 897 *
 898 * @cfg_hash: Hash value of the selected configuration name.
 899 */
 900static int _cscfg_activate_config(unsigned long cfg_hash)
 901{
 902	struct cscfg_config_desc *config_desc;
 903	int err = -EINVAL;
 904
 905	if (cscfg_mgr->load_state == CSCFG_UNLOAD)
 906		return -EBUSY;
 907
 908	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
 909		if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
 910			/* if we happen upon a partly loaded config, can't use it */
 911			if (config_desc->available == false)
 912				return -EBUSY;
 913
 914			if (!cscfg_config_desc_get(config_desc)) {
 915				err = -EINVAL;
 916				break;
 917			}
 918
 919			/*
 920			 * increment the global active count - control changes to
 921			 * active configurations
 922			 */
 923			atomic_inc(&cscfg_mgr->sys_active_cnt);
 924
 925			err = 0;
 926			dev_dbg(cscfg_device(), "Activate config %s.\n", config_desc->name);
 927			break;
 928		}
 929	}
 930	return err;
 931}
 932
 933static void _cscfg_deactivate_config(unsigned long cfg_hash)
 934{
 935	struct cscfg_config_desc *config_desc;
 936
 937	list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
 938		if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
 939			atomic_dec(&cscfg_mgr->sys_active_cnt);
 940			cscfg_config_desc_put(config_desc);
 941			dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
 942			break;
 943		}
 944	}
 945}
 946
 947/*
 948 * called from configfs to set/clear the active configuration for use when
 949 * using sysfs to control trace.
 950 */
 951int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate)
 952{
 953	unsigned long cfg_hash;
 954	int err = 0;
 955
 956	mutex_lock(&cscfg_mutex);
 957
 958	cfg_hash = (unsigned long)config_desc->event_ea->var;
 959
 960	if (activate) {
 961		/* cannot be a current active value to activate this */
 962		if (cscfg_mgr->sysfs_active_config) {
 963			err = -EBUSY;
 964			goto exit_unlock;
 965		}
 966		err = _cscfg_activate_config(cfg_hash);
 967		if (!err)
 968			cscfg_mgr->sysfs_active_config = cfg_hash;
 969	} else {
 970		/* disable if matching current value */
 971		if (cscfg_mgr->sysfs_active_config == cfg_hash) {
 972			_cscfg_deactivate_config(cfg_hash);
 973			cscfg_mgr->sysfs_active_config = 0;
 974		} else
 975			err = -EINVAL;
 976	}
 977
 978exit_unlock:
 979	mutex_unlock(&cscfg_mutex);
 980	return err;
 981}
 982
 983/* set the sysfs preset value */
 984void cscfg_config_sysfs_set_preset(int preset)
 985{
 986	mutex_lock(&cscfg_mutex);
 987	cscfg_mgr->sysfs_active_preset = preset;
 988	mutex_unlock(&cscfg_mutex);
 989}
 990
 991/*
 992 * Used by a device to get the config and preset selected as active in configfs,
 993 * when using sysfs to control trace.
 994 */
 995void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset)
 996{
 997	mutex_lock(&cscfg_mutex);
 998	*preset = cscfg_mgr->sysfs_active_preset;
 999	*cfg_hash = cscfg_mgr->sysfs_active_config;
1000	mutex_unlock(&cscfg_mutex);
1001}
1002EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg);
1003
1004/**
1005 * cscfg_activate_config -  Mark a configuration descriptor as active.
1006 *
1007 * This will be seen when csdev devices are enabled in the system.
1008 * Only activated configurations can be enabled on individual devices.
1009 * Activation protects the configuration from alteration or removal while
1010 * active.
1011 *
1012 * Selection by hash value - generated from the configuration name when it
1013 * was loaded and added to the cs_etm/configurations file system for selection
1014 * by perf.
1015 *
1016 * @cfg_hash: Hash value of the selected configuration name.
1017 */
1018int cscfg_activate_config(unsigned long cfg_hash)
1019{
1020	int err = 0;
1021
1022	mutex_lock(&cscfg_mutex);
1023	err = _cscfg_activate_config(cfg_hash);
1024	mutex_unlock(&cscfg_mutex);
1025
1026	return err;
1027}
1028EXPORT_SYMBOL_GPL(cscfg_activate_config);
1029
1030/**
1031 * cscfg_deactivate_config -  Mark a config descriptor as inactive.
1032 *
1033 * Decrement the configuration and global active counts.
1034 *
1035 * @cfg_hash: Hash value of the selected configuration name.
1036 */
1037void cscfg_deactivate_config(unsigned long cfg_hash)
1038{
1039	mutex_lock(&cscfg_mutex);
1040	_cscfg_deactivate_config(cfg_hash);
1041	mutex_unlock(&cscfg_mutex);
1042}
1043EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
1044
1045/**
1046 * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
1047 *
1048 * Enables the configuration selected by @cfg_hash if the configuration is supported
1049 * on the device and has been activated.
1050 *
1051 * If active and supported the CoreSight device @csdev will be programmed with the
1052 * configuration, using @preset parameters.
1053 *
1054 * Should be called before driver hardware enable for the requested device, prior to
1055 * programming and enabling the physical hardware.
1056 *
1057 * @csdev:	CoreSight device to program.
1058 * @cfg_hash:	Selector for the configuration.
1059 * @preset:	Preset parameter values to use, 0 for current / default values.
1060 */
1061int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
1062				     unsigned long cfg_hash, int preset)
1063{
1064	struct cscfg_config_csdev *config_csdev_active = NULL, *config_csdev_item;
1065	struct cscfg_config_desc *config_desc;
1066	unsigned long flags;
1067	int err = 0;
1068
1069	/* quickly check global count */
1070	if (!atomic_read(&cscfg_mgr->sys_active_cnt))
1071		return 0;
1072
1073	/*
1074	 * Look for matching configuration - set the active configuration
1075	 * context if found.
1076	 */
1077	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
1078	list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
1079		config_desc = config_csdev_item->config_desc;
1080		if (((unsigned long)config_desc->event_ea->var == cfg_hash) &&
1081				cscfg_config_desc_get(config_desc)) {
1082			config_csdev_active = config_csdev_item;
1083			csdev->active_cscfg_ctxt = (void *)config_csdev_active;
1084			break;
1085		}
1086	}
1087	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
1088
1089	/*
1090	 * If found, attempt to enable
1091	 */
1092	if (config_csdev_active) {
1093		/*
1094		 * Call the generic routine that will program up the internal
1095		 * driver structures prior to programming up the hardware.
1096		 * This routine takes the driver spinlock saved in the configs.
1097		 */
1098		err = cscfg_csdev_enable_config(config_csdev_active, preset);
1099		if (!err) {
1100			/*
1101			 * Successful programming. Check the active_cscfg_ctxt
1102			 * pointer to ensure no pre-emption disabled it via
1103			 * cscfg_csdev_disable_active_config() before
1104			 * we could start.
1105			 *
1106			 * Set enabled if OK, err if not.
1107			 */
1108			raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
1109			if (csdev->active_cscfg_ctxt)
1110				config_csdev_active->enabled = true;
1111			else
1112				err = -EBUSY;
1113			raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
1114		}
1115
1116		if (err)
1117			cscfg_config_desc_put(config_desc);
1118	}
1119
1120	return err;
1121}
1122EXPORT_SYMBOL_GPL(cscfg_csdev_enable_active_config);
1123
1124/**
1125 * cscfg_csdev_disable_active_config - disable an active config on the device.
1126 *
1127 * Disables the active configuration on the CoreSight device @csdev.
1128 * Disable will save the values of any registers marked in the configurations
1129 * as save on disable.
1130 *
1131 * Should be called after driver hardware disable for the requested device,
1132 * after disabling the physical hardware and reading back registers.
1133 *
1134 * @csdev: The CoreSight device.
1135 */
1136void cscfg_csdev_disable_active_config(struct coresight_device *csdev)
1137{
1138	struct cscfg_config_csdev *config_csdev;
1139	unsigned long flags;
1140
1141	/*
1142	 * Check if we have an active config, and that it was successfully enabled.
1143	 * If it was not enabled, we have no work to do, otherwise mark as disabled.
1144	 * Clear the active config pointer.
1145	 */
1146	raw_spin_lock_irqsave(&csdev->cscfg_csdev_lock, flags);
1147	config_csdev = (struct cscfg_config_csdev *)csdev->active_cscfg_ctxt;
1148	if (config_csdev) {
1149		if (!config_csdev->enabled)
1150			config_csdev = NULL;
1151		else
1152			config_csdev->enabled = false;
1153	}
1154	csdev->active_cscfg_ctxt = NULL;
1155	raw_spin_unlock_irqrestore(&csdev->cscfg_csdev_lock, flags);
1156
1157	/* true if there was an enabled active config */
1158	if (config_csdev) {
1159		cscfg_csdev_disable_config(config_csdev);
1160		cscfg_config_desc_put(config_csdev->config_desc);
1161	}
1162}
1163EXPORT_SYMBOL_GPL(cscfg_csdev_disable_active_config);
1164
1165/* Initialise system configuration management device. */
1166
1167struct device *cscfg_device(void)
1168{
1169	return cscfg_mgr ? &cscfg_mgr->dev : NULL;
1170}
1171
1172/* Must have a release function or the kernel will complain on module unload */
1173static void cscfg_dev_release(struct device *dev)
1174{
1175	mutex_lock(&cscfg_mutex);
1176	kfree(cscfg_mgr);
1177	cscfg_mgr = NULL;
1178	mutex_unlock(&cscfg_mutex);
1179}
1180
1181/* a device is needed to "own" some kernel elements such as sysfs entries.  */
1182static int cscfg_create_device(void)
1183{
1184	struct device *dev;
1185	int err = -ENOMEM;
1186
1187	mutex_lock(&cscfg_mutex);
1188	if (cscfg_mgr) {
1189		err = -EINVAL;
1190		goto create_dev_exit_unlock;
1191	}
1192
1193	cscfg_mgr = kzalloc(sizeof(struct cscfg_manager), GFP_KERNEL);
1194	if (!cscfg_mgr)
1195		goto create_dev_exit_unlock;
1196
1197	/* initialise the cscfg_mgr structure */
1198	INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list);
1199	INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list);
1200	INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
1201	INIT_LIST_HEAD(&cscfg_mgr->load_order_list);
1202	atomic_set(&cscfg_mgr->sys_active_cnt, 0);
1203	cscfg_mgr->load_state = CSCFG_NONE;
1204
1205	/* setup the device */
1206	dev = cscfg_device();
1207	dev->release = cscfg_dev_release;
1208	dev->init_name = "cs_system_cfg";
1209
1210	err = device_register(dev);
1211	if (err)
1212		put_device(dev);
1213
1214create_dev_exit_unlock:
1215	mutex_unlock(&cscfg_mutex);
1216	return err;
1217}
1218
1219/*
1220 * Loading and unloading is generally on user discretion.
1221 * If exiting due to coresight module unload, we need to unload any configurations that remain,
1222 * before we unregister the configfs intrastructure.
1223 *
1224 * Do this by walking the load_owner list and taking appropriate action, depending on the load
1225 * owner type.
1226 */
1227static void cscfg_unload_cfgs_on_exit(void)
1228{
1229	struct cscfg_load_owner_info *owner_info = NULL;
1230
1231	/*
1232	 * grab the mutex - even though we are exiting, some configfs files
1233	 * may still be live till we dump them, so ensure list data is
1234	 * protected from a race condition.
1235	 */
1236	mutex_lock(&cscfg_mutex);
1237	while (!list_empty(&cscfg_mgr->load_order_list)) {
1238
1239		/* remove in reverse order of loading */
1240		owner_info = list_last_entry(&cscfg_mgr->load_order_list,
1241					     struct cscfg_load_owner_info, item);
1242
1243		/* action according to type */
1244		switch (owner_info->type) {
1245		case CSCFG_OWNER_PRELOAD:
1246			/*
1247			 * preloaded  descriptors are statically allocated in
1248			 * this module - just need to unload dynamic items from
1249			 * csdev lists, and remove from configfs directories.
1250			 */
1251			pr_info("cscfg: unloading preloaded configurations\n");
1252			break;
1253
1254		case  CSCFG_OWNER_MODULE:
1255			/*
1256			 * this is an error - the loadable module must have been unloaded prior
1257			 * to the coresight module unload. Therefore that module has not
1258			 * correctly unloaded configs in its own exit code.
1259			 * Nothing to do other than emit an error string as the static descriptor
1260			 * references we need to unload will have disappeared with the module.
1261			 */
1262			pr_err("cscfg: ERROR: prior module failed to unload configuration\n");
1263			goto list_remove;
1264		}
1265
1266		/* remove from configfs - outside the scope of the list mutex */
1267		mutex_unlock(&cscfg_mutex);
1268		cscfg_fs_unregister_cfgs_feats(owner_info);
1269		mutex_lock(&cscfg_mutex);
1270
1271		/* Next unload from csdev lists. */
1272		cscfg_unload_owned_cfgs_feats(owner_info);
1273
1274list_remove:
1275		/* remove from load order list */
1276		list_del(&owner_info->item);
1277	}
1278	mutex_unlock(&cscfg_mutex);
1279}
1280
1281static void cscfg_clear_device(void)
1282{
1283	cscfg_unload_cfgs_on_exit();
1284	cscfg_configfs_release(cscfg_mgr);
1285	device_unregister(cscfg_device());
1286}
1287
1288/* Initialise system config management API device  */
1289int __init cscfg_init(void)
1290{
1291	int err = 0;
1292
1293	/* create the device and init cscfg_mgr */
1294	err = cscfg_create_device();
1295	if (err)
1296		return err;
1297
1298	/* initialise configfs subsystem */
1299	err = cscfg_configfs_init(cscfg_mgr);
1300	if (err)
1301		goto exit_err;
1302
1303	/* preload built-in configurations */
1304	err = cscfg_preload(THIS_MODULE);
1305	if (err)
1306		goto exit_err;
1307
1308	dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
1309	return 0;
1310
1311exit_err:
1312	cscfg_clear_device();
1313	return err;
1314}
1315
1316void cscfg_exit(void)
1317{
1318	cscfg_clear_device();
1319}
~/ Read-only file preview.