Message ID | 20210512211752.4103-5-mike.leach@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | coresight: syscfg: dynamic load, resource management | expand |
Please remove the '.' on every patch header. 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@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@linaro.org> > > /* syscfg manager external API */ > int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > -- > 2.17.1 >
Hi Mathieu, On Tue, 18 May 2021 at 20:36, Mathieu Poirier <mathieu.poirier@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@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@linaro.org> > Thanks. Regards Mike > > > > /* syscfg manager external API */ > > int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs, > > -- > > 2.17.1 > >
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) { + /* 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; + } + 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); /* syscfg manager external API */ int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
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> --- .../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(-)