[PATCH v2 4/5] coresight: configfs: Allow configfs to activate configuration
Mathieu Poirier
mathieu.poirier at linaro.org
Thu Nov 11 09:23:31 PST 2021
Good day Mike,
On Tue, Oct 19, 2021 at 08:13:50PM +0100, Mike Leach wrote:
> 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 at linaro.org>
> ---
> .../coresight/coresight-etm4x-core.c | 11 +-
> .../coresight/coresight-syscfg-configfs.c | 67 ++++++++++
> .../coresight/coresight-syscfg-configfs.h | 2 +
> .../hwtracing/coresight/coresight-syscfg.c | 126 ++++++++++++++----
> .../hwtracing/coresight/coresight-syscfg.h | 8 +-
> 5 files changed, 186 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> index 86a313857b58..bf18128cf5de 100644
> --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> @@ -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);
>
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> index 345a62f1b728..c388a77a2683 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
> @@ -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_activate_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_activate_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_, activate);
I would call this "enable" to follow what is already done for coresight in
sysfs.
> +
> +static ssize_t cscfg_cfg_active_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_active_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_, active_preset);
And I would call this "preset" since this is what is used on the perf cmd line.
Please add a new "Using Configurations from configfs" section in [1] to
show how "enable" and "preset" should be used.
With that:
Reviewed-by: Mathieu Poirier <mathieu.poirier at linaro.org>
[1]. Documentation/trace/coresight/coresight-config.rst
> +
> static struct configfs_attribute *cscfg_config_view_attrs[] = {
> &cscfg_cfg_attr_description,
> &cscfg_cfg_attr_feature_refs,
> + &cscfg_cfg_attr_activate,
> + &cscfg_cfg_attr_active_preset,
> NULL,
> };
>
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
> index ea1e54d29f7f..373d84d43268 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
> +++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
> @@ -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 */
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
> index 4b91d8d9bc37..759c32889efd 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg.c
> +++ b/drivers/hwtracing/coresight/coresight-syscfg.c
> @@ -744,30 +744,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 */
> @@ -791,6 +781,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;
> @@ -806,19 +891,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);
> diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
> index 1da37874f70f..9106ffab4833 100644
> --- a/drivers/hwtracing/coresight/coresight-syscfg.h
> +++ b/drivers/hwtracing/coresight/coresight-syscfg.h
> @@ -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 */
> --
> 2.17.1
>
More information about the linux-arm-kernel
mailing list