linux-stable/drivers/hwtracing/coresight/coresight-syscfg.h
Mike Leach 8add26f7ef coresight: syscfg: Update load and unload operations
The configfs system is a source of access to the config information in the
configuration and feature lists.

This can result in additional LOCKDEP issues as a result of the mutex
ordering between the config list mutex (cscfg_mutex) and the configfs
system mutexes.

As such we need to adjust how load/unload operations work to ensure correct
operation.

1) Previously the cscfg_mutex was held throughout the load/unload
operation. This is now only held during configuration list manipulations,
resulting in a multi-stage load/unload process.

2) All operations that manipulate the configfs representation of the
configurations and features are now separated out and run without the
cscfg_mutex being held. This avoids circular lock_dep issue with the
built-in configfs mutexes and semaphores

3) As the load and unload is now multi-stage, some parts under the
cscfg_mutex and others not:
i) A flag indicating a load / unload operation in progress is used to
serialise load / unload operations.
ii) activating any configuration not possible when unload is in progress.
iii) Configurations have an "available" flag set only after the last load
stage for the configuration is complete. Activation of the configuration
not possible till flag is set.

4) Following load/unload rules remain:
i) Unload prevented while any configuration is active remains.
ii) Unload in strict reverse order of load.
iii) Existing configurations can be activated while a new load operation
is underway. (by definition there can be no dependencies between an
existing configuration and a new loading one due to ii) above.)

Fixes: eb2ec49606 ("coresight: syscfg: Update load API for config loadable modules")
Reported-by: Suzuki Poulose <suzuki.poulose@arm.com>
Signed-off-by: Mike Leach <mike.leach@linaro.org>
Reviewed-and-tested-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20220628173004.30002-3-mike.leach@linaro.org
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
2022-06-29 09:35:58 -06:00

127 lines
4.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Coresight system configuration driver.
*/
#ifndef CORESIGHT_SYSCFG_H
#define CORESIGHT_SYSCFG_H
#include <linux/configfs.h>
#include <linux/coresight.h>
#include <linux/device.h>
#include "coresight-config.h"
/*
* Load operation types.
* When loading or unloading, another load operation cannot be run.
* When unloading configurations cannot be activated.
*/
enum cscfg_load_ops {
CSCFG_NONE,
CSCFG_LOAD,
CSCFG_UNLOAD
};
/**
* System configuration manager device.
*
* Contains lists of the loaded configurations and features, plus a list of CoreSight devices
* registered with the system as supporting configuration management.
*
* Need a device to 'own' some coresight system wide sysfs entries in
* perf events, configfs etc.
*
* @dev: The device.
* @csdev_desc_list: List of coresight devices registered with the configuration manager.
* @feat_desc_list: List of feature descriptors to load into registered devices.
* @config_desc_list: List of system configuration descriptors to load into registered devices.
* @load_order_list: Ordered list of owners for dynamically loaded configurations.
* @sys_active_cnt: Total number of active config descriptor references.
* @cfgfs_subsys: configfs subsystem used to manage configurations.
* @sysfs_active_config:Active config hash used if CoreSight controlled from sysfs.
* @sysfs_active_preset:Active preset index used if CoreSight controlled from sysfs.
* @load_state: A multi-stage load/unload operation is in progress.
*/
struct cscfg_manager {
struct device dev;
struct list_head csdev_desc_list;
struct list_head feat_desc_list;
struct list_head config_desc_list;
struct list_head load_order_list;
atomic_t sys_active_cnt;
struct configfs_subsystem cfgfs_subsys;
u32 sysfs_active_config;
int sysfs_active_preset;
enum cscfg_load_ops load_state;
};
/* get reference to dev in cscfg_manager */
struct device *cscfg_device(void);
/**
* List entry for Coresight devices that are registered as supporting complex
* config operations.
*
* @csdev: The registered device.
* @match_flags: The matching type information for adding features.
* @ops: Operations supported by the registered device.
* @item: list entry.
*/
struct cscfg_registered_csdev {
struct coresight_device *csdev;
u32 match_flags;
struct cscfg_csdev_feat_ops ops;
struct list_head item;
};
/* owner types for loading and unloading of config and feature sets */
enum cscfg_load_owner_type {
CSCFG_OWNER_PRELOAD,
CSCFG_OWNER_MODULE,
};
/**
* Load item - item to add to the load order list allowing dynamic load and
* unload of configurations and features. Caller loading a config
* set provides a context handle for unload. API ensures that
* items unloaded strictly in reverse order from load to ensure
* dependencies are respected.
*
* @item: list entry for load order list.
* @type: type of owner - allows interpretation of owner_handle.
* @owner_handle: load context - handle for owner of loaded configs.
*/
struct cscfg_load_owner_info {
struct list_head item;
int type;
void *owner_handle;
};
/* internal core operations for cscfg */
int __init cscfg_init(void);
void cscfg_exit(void);
int cscfg_preload(void *owner_handle);
const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name);
int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
int param_idx, u64 value);
int cscfg_config_sysfs_activate(struct cscfg_config_desc *cfg_desc, bool activate);
void cscfg_config_sysfs_set_preset(int preset);
/* syscfg manager external API */
int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
struct cscfg_feature_desc **feat_descs,
struct cscfg_load_owner_info *owner_info);
int cscfg_unload_config_sets(struct cscfg_load_owner_info *owner_info);
int cscfg_register_csdev(struct coresight_device *csdev, u32 match_flags,
struct cscfg_csdev_feat_ops *ops);
void cscfg_unregister_csdev(struct coresight_device *csdev);
int cscfg_activate_config(unsigned long cfg_hash);
void cscfg_deactivate_config(unsigned long cfg_hash);
void cscfg_csdev_reset_feats(struct coresight_device *csdev);
int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
unsigned long cfg_hash, int preset);
void cscfg_csdev_disable_active_config(struct coresight_device *csdev);
void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset);
#endif /* CORESIGHT_SYSCFG_H */