[RFC PATCH 4/8] coresight: configfs: Allow configfs to activate configuration.
Mike Leach
mike.leach at linaro.org
Wed May 19 02:47:09 PDT 2021
Hi Mathieu,
On Tue, 18 May 2021 at 20:36, Mathieu Poirier
<mathieu.poirier at linaro.org> wrote:
>
> Please remove the '.' on every patch header.
>
Sorry - will do. Correct punctuation seems to be a habit that is hard to break!
> On Wed, May 12, 2021 at 10:17:48PM +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 | 5 +
> > .../coresight/coresight-syscfg-configfs.c | 67 +++++++++
> > .../coresight/coresight-syscfg-configfs.h | 2 +
> > .../hwtracing/coresight/coresight-syscfg.c | 129 ++++++++++++++----
> > .../hwtracing/coresight/coresight-syscfg.h | 7 +-
> > 5 files changed, 182 insertions(+), 28 deletions(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > index b7a4aeaa2bc7..2637096c4621 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > @@ -688,6 +688,11 @@ static int etm4_enable_sysfs(struct coresight_device *csdev)
> > struct etm4_enable_arg arg = { };
> > int ret;
> >
> > + /* enable any config activated by configfs */
> > + ret = cscfg_csdev_enable_active_config(csdev, 0, 0);
> > + 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..ae79ae8b1d7e 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_activation(fs_config->config_desc, val);
> > + if (!err) {
> > + fs_config->active = val;
> > + if (val)
> > + cscfg_config_sysfs_preset(fs_config->preset);
> > + }
> > + return err ? err : count;
> > +}
> > +CONFIGFS_ATTR(cscfg_cfg_, activate);
> > +
> > +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_preset(fs_config->preset);
> > + }
> > + return err ? err : count;
> > +}
> > +CONFIGFS_ATTR(cscfg_cfg_, active_preset);
> > +
> > 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 26c1a244c2b1..ab74e33b892b 100644
> > --- a/drivers/hwtracing/coresight/coresight-syscfg.c
> > +++ b/drivers/hwtracing/coresight/coresight-syscfg.c
> > @@ -743,32 +743,23 @@ 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) {
> > +
>
> Spurious newline
>
> > /* must ensure that config cannot be unloaded in use */
> > err = cscfg_owner_get(config_desc->load_owner);
> > if (err)
> > @@ -790,6 +781,88 @@ 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_activation(struct cscfg_config_desc *config_desc, bool activate)
> > +{
> > + unsigned long cfg_hash_desc;
> > + int err = 0;
> > +
> > + mutex_lock(&cscfg_mutex);
> > +
> > + cfg_hash_desc = (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_desc);
> > + if (!err)
> > + cscfg_mgr->sysfs_active_config = cfg_hash_desc;
> > + } else {
> > + /* disable if matching current value */
> > + if (cscfg_mgr->sysfs_active_config == cfg_hash_desc) {
> > + _cscfg_deactivate_config(cfg_hash_desc);
> > + 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_preset(int preset)
> > +{
> > + mutex_lock(&cscfg_mutex);
> > + cscfg_mgr->sysfs_active_preset = preset;
> > + mutex_unlock(&cscfg_mutex);
> > +}
> > +
> > +/**
> > + * 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;
> > @@ -805,19 +878,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);
> > @@ -826,7 +888,8 @@ EXPORT_SYMBOL_GPL(cscfg_deactivate_config);
> > * cscfg_csdev_enable_active_config - Enable matching active configuration for device.
> > *
> > * Enables the configuration selected by @cfg_hash if the configuration is supported
> > - * on the device and has been activated.
> > + * on the device and has been activated. A @cfg_hash value of 0 is used if the device
> > + * is being programmed from sysfs, to select the current sysfs active config.
> > *
> > * If active and supported the CoreSight device @csdev will be programmed with the
> > * configuration, using @preset parameters.
> > @@ -850,6 +913,16 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > return 0;
> >
> > mutex_lock(&cscfg_csdev_mutex);
> > +
> > + /* sysfs controlled coresight will call with cfg_hash == 0 */
> > + if (!cfg_hash) {
> > + if (!cscfg_mgr->sysfs_active_config)
> > + goto exit_unlock;
> > +
> > + cfg_hash = cscfg_mgr->sysfs_active_config;
> > + preset = cscfg_mgr->sysfs_active_preset;
> > + }
>
> I'm worried about this snippet. For the time being it works but the function is
> now entangled with the "if (attr->config2 ...) of etm4_parse_event_config().
> That being said I spent a fair amount of time trying to find a better solution
> and I can't come up with one. The best option is probably to keep it for now.
>
>
> > +
> > list_for_each_entry(config_csdev_item, &csdev->config_csdev_list, node) {
> > config_desc = config_csdev_item->config_desc;
> > if ((atomic_read(&config_desc->active_cnt)) &&
> > @@ -863,6 +936,8 @@ int cscfg_csdev_enable_active_config(struct coresight_device *csdev,
> > if (!err)
> > csdev->active_cscfg_ctxt = (void *)config_csdev_active;
> > }
> > +
> > +exit_unlock:
> > mutex_unlock(&cscfg_csdev_mutex);
> > return err;
> > }
> > diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
> > index 1da37874f70f..e07e1b872806 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_activation(struct cscfg_config_desc *cfg_desc, bool activate);
> > +void cscfg_config_sysfs_preset(int preset);
>
> With the above:
>
> Reviewed-by: Mathieu Poirier <mathieu.poirier at linaro.org>
>
Thanks.
Regards
Mike
> >
> > /* syscfg manager external API */
> > int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
> > --
> > 2.17.1
> >
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
More information about the linux-arm-kernel
mailing list