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;} elseerr = -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