]> Git Repo - J-linux.git/commitdiff
coresight: configfs: Allow configfs to activate configuration
authorMike Leach <[email protected]>
Wed, 24 Nov 2021 20:00:37 +0000 (20:00 +0000)
committerMathieu Poirier <[email protected]>
Fri, 26 Nov 2021 18:34:27 +0000 (11:34 -0700)
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 <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mathieu Poirier <[email protected]>
drivers/hwtracing/coresight/coresight-etm4x-core.c
drivers/hwtracing/coresight/coresight-syscfg-configfs.c
drivers/hwtracing/coresight/coresight-syscfg-configfs.h
drivers/hwtracing/coresight/coresight-syscfg.c
drivers/hwtracing/coresight/coresight-syscfg.h

index 86a313857b58463ee0457c2400c0c0fde92da806..bf18128cf5ded1a51c9460644326c6619cd47006 100644 (file)
@@ -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);
 
index 345a62f1b7280040ea7f169cb6a784d952d94d24..433ede94dd6399f157032dbb001be91a80bb91e4 100644 (file)
@@ -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,
 };
 
index ea1e54d29f7f3ea1bf5801bfd8ae30dccf33546c..373d84d43268f5454ee0114528c0dca29054a5db 100644 (file)
@@ -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 */
index 678ee8250d85eafbf5797d155fa9b58a500cd392..098fc34c482934b5b75afdbdd171e7cb6469b83d 100644 (file)
@@ -745,30 +745,20 @@ unlock_exit:
 }
 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);
index 1da37874f70fee55efa030957ae3761ce14fe120..9106ffab48337c9a0ccb325bd7d2675db8d685c4 100644 (file)
@@ -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 */
This page took 0.066767 seconds and 4 git commands to generate.