mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 10:42:11 +00:00
coresight: configfs: Allow configfs to activate configuration
Adds configfs attributes to allow a configuration to be enabled for use when sysfs is used to control CoreSight. perf retains independent enabling of configurations. Signed-off-by: Mike Leach <mike.leach@linaro.org> Link: https://lore.kernel.org/r/20211124200038.28662-6-mike.leach@linaro.org Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
This commit is contained in:
parent
ede5bab874
commit
7ebd0ec6cf
@ -722,7 +722,16 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
|
||||
{
|
||||
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
|
||||
struct etm4_enable_arg arg = { };
|
||||
int ret;
|
||||
unsigned long cfg_hash;
|
||||
int ret, preset;
|
||||
|
||||
/* enable any config activated by configfs */
|
||||
cscfg_config_sysfs_get_active_cfg(&cfg_hash, &preset);
|
||||
if (cfg_hash) {
|
||||
ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_lock(&drvdata->spinlock);
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <linux/configfs.h>
|
||||
|
||||
#include "coresight-config.h"
|
||||
#include "coresight-syscfg-configfs.h"
|
||||
|
||||
/* create a default ci_type. */
|
||||
@ -87,9 +88,75 @@ static ssize_t cscfg_cfg_values_show(struct config_item *item, char *page)
|
||||
}
|
||||
CONFIGFS_ATTR_RO(cscfg_cfg_, values);
|
||||
|
||||
static ssize_t cscfg_cfg_enable_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
|
||||
struct cscfg_fs_config, group);
|
||||
|
||||
return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->active);
|
||||
}
|
||||
|
||||
static ssize_t cscfg_cfg_enable_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
|
||||
struct cscfg_fs_config, group);
|
||||
int err;
|
||||
bool val;
|
||||
|
||||
err = kstrtobool(page, &val);
|
||||
if (!err)
|
||||
err = cscfg_config_sysfs_activate(fs_config->config_desc, val);
|
||||
if (!err) {
|
||||
fs_config->active = val;
|
||||
if (val)
|
||||
cscfg_config_sysfs_set_preset(fs_config->preset);
|
||||
}
|
||||
return err ? err : count;
|
||||
}
|
||||
CONFIGFS_ATTR(cscfg_cfg_, enable);
|
||||
|
||||
static ssize_t cscfg_cfg_preset_show(struct config_item *item, char *page)
|
||||
{
|
||||
struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
|
||||
struct cscfg_fs_config, group);
|
||||
|
||||
return scnprintf(page, PAGE_SIZE, "%d\n", fs_config->preset);
|
||||
}
|
||||
|
||||
static ssize_t cscfg_cfg_preset_store(struct config_item *item,
|
||||
const char *page, size_t count)
|
||||
{
|
||||
struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
|
||||
struct cscfg_fs_config, group);
|
||||
int preset, err;
|
||||
|
||||
err = kstrtoint(page, 0, &preset);
|
||||
if (!err) {
|
||||
/*
|
||||
* presets start at 1, and go up to max (15),
|
||||
* but the config may provide fewer.
|
||||
*/
|
||||
if ((preset < 1) || (preset > fs_config->config_desc->nr_presets))
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
/* set new value */
|
||||
fs_config->preset = preset;
|
||||
/* set on system if active */
|
||||
if (fs_config->active)
|
||||
cscfg_config_sysfs_set_preset(fs_config->preset);
|
||||
}
|
||||
return err ? err : count;
|
||||
}
|
||||
CONFIGFS_ATTR(cscfg_cfg_, preset);
|
||||
|
||||
static struct configfs_attribute *cscfg_config_view_attrs[] = {
|
||||
&cscfg_cfg_attr_description,
|
||||
&cscfg_cfg_attr_feature_refs,
|
||||
&cscfg_cfg_attr_enable,
|
||||
&cscfg_cfg_attr_preset,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
struct cscfg_fs_config {
|
||||
struct cscfg_config_desc *config_desc;
|
||||
struct config_group group;
|
||||
bool active;
|
||||
int preset;
|
||||
};
|
||||
|
||||
/* container for feature view */
|
||||
|
@ -745,30 +745,20 @@ void cscfg_csdev_reset_feats(struct coresight_device *csdev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cscfg_csdev_reset_feats);
|
||||
|
||||
/**
|
||||
* cscfg_activate_config - Mark a configuration descriptor as active.
|
||||
*
|
||||
* This will be seen when csdev devices are enabled in the system.
|
||||
* Only activated configurations can be enabled on individual devices.
|
||||
* Activation protects the configuration from alteration or removal while
|
||||
* active.
|
||||
*
|
||||
* Selection by hash value - generated from the configuration name when it
|
||||
* was loaded and added to the cs_etm/configurations file system for selection
|
||||
* by perf.
|
||||
/*
|
||||
* This activate configuration for either perf or sysfs. Perf can have multiple
|
||||
* active configs, selected per event, sysfs is limited to one.
|
||||
*
|
||||
* Increments the configuration descriptor active count and the global active
|
||||
* count.
|
||||
*
|
||||
* @cfg_hash: Hash value of the selected configuration name.
|
||||
*/
|
||||
int cscfg_activate_config(unsigned long cfg_hash)
|
||||
static int _cscfg_activate_config(unsigned long cfg_hash)
|
||||
{
|
||||
struct cscfg_config_desc *config_desc;
|
||||
int err = -EINVAL;
|
||||
|
||||
mutex_lock(&cscfg_mutex);
|
||||
|
||||
list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
|
||||
if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
|
||||
/* must ensure that config cannot be unloaded in use */
|
||||
@ -792,6 +782,101 @@ int cscfg_activate_config(unsigned long cfg_hash)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void _cscfg_deactivate_config(unsigned long cfg_hash)
|
||||
{
|
||||
struct cscfg_config_desc *config_desc;
|
||||
|
||||
list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
|
||||
if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
|
||||
atomic_dec(&config_desc->active_cnt);
|
||||
atomic_dec(&cscfg_mgr->sys_active_cnt);
|
||||
cscfg_owner_put(config_desc->load_owner);
|
||||
dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* called from configfs to set/clear the active configuration for use when
|
||||
* using sysfs to control trace.
|
||||
*/
|
||||
int cscfg_config_sysfs_activate(struct cscfg_config_desc *config_desc, bool activate)
|
||||
{
|
||||
unsigned long cfg_hash;
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&cscfg_mutex);
|
||||
|
||||
cfg_hash = (unsigned long)config_desc->event_ea->var;
|
||||
|
||||
if (activate) {
|
||||
/* cannot be a current active value to activate this */
|
||||
if (cscfg_mgr->sysfs_active_config) {
|
||||
err = -EBUSY;
|
||||
goto exit_unlock;
|
||||
}
|
||||
err = _cscfg_activate_config(cfg_hash);
|
||||
if (!err)
|
||||
cscfg_mgr->sysfs_active_config = cfg_hash;
|
||||
} else {
|
||||
/* disable if matching current value */
|
||||
if (cscfg_mgr->sysfs_active_config == cfg_hash) {
|
||||
_cscfg_deactivate_config(cfg_hash);
|
||||
cscfg_mgr->sysfs_active_config = 0;
|
||||
} else
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
exit_unlock:
|
||||
mutex_unlock(&cscfg_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* set the sysfs preset value */
|
||||
void cscfg_config_sysfs_set_preset(int preset)
|
||||
{
|
||||
mutex_lock(&cscfg_mutex);
|
||||
cscfg_mgr->sysfs_active_preset = preset;
|
||||
mutex_unlock(&cscfg_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used by a device to get the config and preset selected as active in configfs,
|
||||
* when using sysfs to control trace.
|
||||
*/
|
||||
void cscfg_config_sysfs_get_active_cfg(unsigned long *cfg_hash, int *preset)
|
||||
{
|
||||
mutex_lock(&cscfg_mutex);
|
||||
*preset = cscfg_mgr->sysfs_active_preset;
|
||||
*cfg_hash = cscfg_mgr->sysfs_active_config;
|
||||
mutex_unlock(&cscfg_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cscfg_config_sysfs_get_active_cfg);
|
||||
|
||||
/**
|
||||
* cscfg_activate_config - Mark a configuration descriptor as active.
|
||||
*
|
||||
* This will be seen when csdev devices are enabled in the system.
|
||||
* Only activated configurations can be enabled on individual devices.
|
||||
* Activation protects the configuration from alteration or removal while
|
||||
* active.
|
||||
*
|
||||
* Selection by hash value - generated from the configuration name when it
|
||||
* was loaded and added to the cs_etm/configurations file system for selection
|
||||
* by perf.
|
||||
*
|
||||
* @cfg_hash: Hash value of the selected configuration name.
|
||||
*/
|
||||
int cscfg_activate_config(unsigned long cfg_hash)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
mutex_lock(&cscfg_mutex);
|
||||
err = _cscfg_activate_config(cfg_hash);
|
||||
mutex_unlock(&cscfg_mutex);
|
||||
|
||||
return err;
|
||||
@ -807,19 +892,8 @@ EXPORT_SYMBOL_GPL(cscfg_activate_config);
|
||||
*/
|
||||
void cscfg_deactivate_config(unsigned long cfg_hash)
|
||||
{
|
||||
struct cscfg_config_desc *config_desc;
|
||||
|
||||
mutex_lock(&cscfg_mutex);
|
||||
|
||||
list_for_each_entry(config_desc, &cscfg_mgr->config_desc_list, item) {
|
||||
if ((unsigned long)config_desc->event_ea->var == cfg_hash) {
|
||||
atomic_dec(&config_desc->active_cnt);
|
||||
atomic_dec(&cscfg_mgr->sys_active_cnt);
|
||||
cscfg_owner_put(config_desc->load_owner);
|
||||
dev_dbg(cscfg_device(), "Deactivate config %s.\n", config_desc->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
_cscfg_deactivate_config(cfg_hash);
|
||||
mutex_unlock(&cscfg_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
|
||||
|
@ -28,6 +28,8 @@
|
||||
* @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.
|
||||
*/
|
||||
struct cscfg_manager {
|
||||
struct device dev;
|
||||
@ -37,6 +39,8 @@ struct cscfg_manager {
|
||||
struct list_head load_order_list;
|
||||
atomic_t sys_active_cnt;
|
||||
struct configfs_subsystem cfgfs_subsys;
|
||||
u32 sysfs_active_config;
|
||||
int sysfs_active_preset;
|
||||
};
|
||||
|
||||
/* get reference to dev in cscfg_manager */
|
||||
@ -88,7 +92,8 @@ 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,
|
||||
@ -104,5 +109,6 @@ 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user