2021-08-18 19:42:10

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 00/11] coresight: Patches for v5.15

Hi Greg,

This is what I picked up for the next merge window (v5.15). Please have
a look when time permits.

Applies cleanly on your char-misc-next branch (9e1b28b77388).

Thanks,
Mathieu

Mike Leach (10):
coresight: syscfg: Initial coresight system configuration
coresight: syscfg: Add registration and feature loading for cs devices
coresight: config: Add configuration and feature generic functions
coresight: etm-perf: Update to handle configuration selection
coresight: syscfg: Add API to activate and enable configurations
coresight: etm-perf: Update to activate selected configuration
coresight: etm4x: Add complex configuration handlers to etmv4
coresight: config: Add preloaded configurations
coresight: syscfg: Add initial configfs support
Documentation: coresight: Add documentation for CoreSight config

Sebastian Andrzej Siewior (1):
coresight: Replace deprecated CPU-hotplug functions.

.../trace/coresight/coresight-config.rst | 244 +++++
Documentation/trace/coresight/coresight.rst | 15 +
drivers/hwtracing/coresight/Kconfig | 1 +
drivers/hwtracing/coresight/Makefile | 7 +-
.../hwtracing/coresight/coresight-cfg-afdo.c | 153 ++++
.../coresight/coresight-cfg-preload.c | 31 +
.../coresight/coresight-cfg-preload.h | 13 +
.../hwtracing/coresight/coresight-config.c | 272 ++++++
.../hwtracing/coresight/coresight-config.h | 253 ++++++
drivers/hwtracing/coresight/coresight-core.c | 12 +-
.../hwtracing/coresight/coresight-cpu-debug.c | 4 +-
.../hwtracing/coresight/coresight-etm-perf.c | 150 +++-
.../hwtracing/coresight/coresight-etm-perf.h | 12 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 182 ++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 30 +
.../coresight/coresight-etm4x-core.c | 38 +-
.../coresight/coresight-etm4x-sysfs.c | 3 +
.../coresight/coresight-syscfg-configfs.c | 396 ++++++++
.../coresight/coresight-syscfg-configfs.h | 45 +
.../hwtracing/coresight/coresight-syscfg.c | 847 ++++++++++++++++++
.../hwtracing/coresight/coresight-syscfg.h | 81 ++
include/linux/coresight.h | 9 +
22 files changed, 2760 insertions(+), 38 deletions(-)
create mode 100644 Documentation/trace/coresight/coresight-config.rst
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-afdo.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.h
create mode 100644 drivers/hwtracing/coresight/coresight-config.c
create mode 100644 drivers/hwtracing/coresight/coresight-config.h
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.h
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg.h

--
2.25.1


2021-08-18 19:42:20

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 06/11] coresight: etm-perf: Update to activate selected configuration

From: Mike Leach <[email protected]>

Add calls to activate the selected configuration as perf starts
and stops the tracing session.

Signed-off-by: Mike Leach <[email protected]>
Reviewed-by: Suzuki K Poulose <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mathieu Poirier <[email protected]>
---
drivers/hwtracing/coresight/coresight-etm-perf.c | 14 +++++++++++++-
drivers/hwtracing/coresight/coresight-etm-perf.h | 2 ++
2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index e42ab919ddc3..8ebd728d3a80 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -215,6 +215,10 @@ static void free_event_data(struct work_struct *work)
/* Free the sink buffers, if there are any */
free_sink_buffer(event_data);

+ /* clear any configuration we were using */
+ if (event_data->cfg_hash)
+ cscfg_deactivate_config(event_data->cfg_hash);
+
for_each_cpu(cpu, mask) {
struct list_head **ppath;

@@ -292,7 +296,7 @@ static bool sinks_compatible(struct coresight_device *a,
static void *etm_setup_aux(struct perf_event *event, void **pages,
int nr_pages, bool overwrite)
{
- u32 id;
+ u32 id, cfg_hash;
int cpu = event->cpu;
cpumask_t *mask;
struct coresight_device *sink = NULL;
@@ -310,6 +314,14 @@ static void *etm_setup_aux(struct perf_event *event, void **pages,
sink = user_sink = coresight_get_sink_by_id(id);
}

+ /* check if user wants a coresight configuration selected */
+ cfg_hash = (u32)((event->attr.config2 & GENMASK_ULL(63, 32)) >> 32);
+ if (cfg_hash) {
+ if (cscfg_activate_config(cfg_hash))
+ goto err;
+ event_data->cfg_hash = cfg_hash;
+ }
+
mask = &event_data->mask;

/*
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h
index ba617fe2217e..468f7799ab4f 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.h
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.h
@@ -49,12 +49,14 @@ struct etm_filters {
* @work: Handle to free allocated memory outside IRQ context.
* @mask: Hold the CPU(s) this event was set for.
* @snk_config: The sink configuration.
+ * @cfg_hash: The hash id of any coresight config selected.
* @path: An array of path, each slot for one CPU.
*/
struct etm_event_data {
struct work_struct work;
cpumask_t mask;
void *snk_config;
+ u32 cfg_hash;
struct list_head * __percpu *path;
};

--
2.25.1

2021-08-18 19:42:30

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 07/11] coresight: etm4x: Add complex configuration handlers to etmv4

From: Mike Leach <[email protected]>

Adds in handlers to allow the ETMv4 to use the complex configuration
support. Features and configurations can be loaded and selected in the
device.

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/Makefile | 3 +-
.../hwtracing/coresight/coresight-etm4x-cfg.c | 182 ++++++++++++++++++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 15 ++
.../coresight/coresight-etm4x-core.c | 38 +++-
.../coresight/coresight-etm4x-sysfs.c | 3 +
5 files changed, 238 insertions(+), 3 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.c
create mode 100644 drivers/hwtracing/coresight/coresight-etm4x-cfg.h

diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 63ecfc3cf66d..9420d33b23ac 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -16,7 +16,8 @@ obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o
coresight-etm3x-y := coresight-etm3x-core.o coresight-etm-cp14.o \
coresight-etm3x-sysfs.o
obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o
-coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o
+coresight-etm4x-y := coresight-etm4x-core.o coresight-etm4x-sysfs.o \
+ coresight-etm4x-cfg.o
obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.c b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
new file mode 100644
index 000000000000..d2ea903231b2
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <[email protected]>
+ */
+
+#include "coresight-etm4x.h"
+#include "coresight-etm4x-cfg.h"
+#include "coresight-priv.h"
+#include "coresight-syscfg.h"
+
+/* defines to associate register IDs with driver data locations */
+#define CHECKREG(cval, elem) \
+ { \
+ if (offset == cval) { \
+ reg_csdev->driver_regval = &drvcfg->elem; \
+ err = 0; \
+ break; \
+ } \
+ }
+
+#define CHECKREGIDX(cval, elem, off_idx, mask) \
+ { \
+ if (mask == cval) { \
+ reg_csdev->driver_regval = &drvcfg->elem[off_idx]; \
+ err = 0; \
+ break; \
+ } \
+ }
+
+/**
+ * etm4_cfg_map_reg_offset - validate and map the register offset into a
+ * location in the driver config struct.
+ *
+ * Limits the number of registers that can be accessed and programmed in
+ * features, to those which are used to control the trace capture parameters.
+ *
+ * Omits or limits access to those which the driver must use exclusively.
+ *
+ * Invalid offsets will result in fail code return and feature load failure.
+ *
+ * @drvdata: driver data to map into.
+ * @reg: register to map.
+ * @offset: device offset for the register
+ */
+static int etm4_cfg_map_reg_offset(struct etmv4_drvdata *drvdata,
+ struct cscfg_regval_csdev *reg_csdev, u32 offset)
+{
+ int err = -EINVAL, idx;
+ struct etmv4_config *drvcfg = &drvdata->config;
+ u32 off_mask;
+
+ if (((offset >= TRCEVENTCTL0R) && (offset <= TRCVIPCSSCTLR)) ||
+ ((offset >= TRCSEQRSTEVR) && (offset <= TRCEXTINSELR)) ||
+ ((offset >= TRCCIDCCTLR0) && (offset <= TRCVMIDCCTLR1))) {
+ do {
+ CHECKREG(TRCEVENTCTL0R, eventctrl0);
+ CHECKREG(TRCEVENTCTL1R, eventctrl1);
+ CHECKREG(TRCSTALLCTLR, stall_ctrl);
+ CHECKREG(TRCTSCTLR, ts_ctrl);
+ CHECKREG(TRCSYNCPR, syncfreq);
+ CHECKREG(TRCCCCTLR, ccctlr);
+ CHECKREG(TRCBBCTLR, bb_ctrl);
+ CHECKREG(TRCVICTLR, vinst_ctrl);
+ CHECKREG(TRCVIIECTLR, viiectlr);
+ CHECKREG(TRCVISSCTLR, vissctlr);
+ CHECKREG(TRCVIPCSSCTLR, vipcssctlr);
+ CHECKREG(TRCSEQRSTEVR, seq_rst);
+ CHECKREG(TRCSEQSTR, seq_state);
+ CHECKREG(TRCEXTINSELR, ext_inp);
+ CHECKREG(TRCCIDCCTLR0, ctxid_mask0);
+ CHECKREG(TRCCIDCCTLR1, ctxid_mask1);
+ CHECKREG(TRCVMIDCCTLR0, vmid_mask0);
+ CHECKREG(TRCVMIDCCTLR1, vmid_mask1);
+ } while (0);
+ } else if ((offset & GENMASK(11, 4)) == TRCSEQEVRn(0)) {
+ /* sequencer state control registers */
+ idx = (offset & GENMASK(3, 0)) / 4;
+ if (idx < ETM_MAX_SEQ_STATES) {
+ reg_csdev->driver_regval = &drvcfg->seq_ctrl[idx];
+ err = 0;
+ }
+ } else if ((offset >= TRCSSCCRn(0)) && (offset <= TRCSSPCICRn(7))) {
+ /* 32 bit, 8 off indexed register sets */
+ idx = (offset & GENMASK(4, 0)) / 4;
+ off_mask = (offset & GENMASK(11, 5));
+ do {
+ CHECKREGIDX(TRCSSCCRn(0), ss_ctrl, idx, off_mask);
+ CHECKREGIDX(TRCSSCSRn(0), ss_status, idx, off_mask);
+ CHECKREGIDX(TRCSSPCICRn(0), ss_pe_cmp, idx, off_mask);
+ } while (0);
+ } else if ((offset >= TRCCIDCVRn(0)) && (offset <= TRCVMIDCVRn(7))) {
+ /* 64 bit, 8 off indexed register sets */
+ idx = (offset & GENMASK(5, 0)) / 8;
+ off_mask = (offset & GENMASK(11, 6));
+ do {
+ CHECKREGIDX(TRCCIDCVRn(0), ctxid_pid, idx, off_mask);
+ CHECKREGIDX(TRCVMIDCVRn(0), vmid_val, idx, off_mask);
+ } while (0);
+ } else if ((offset >= TRCRSCTLRn(2)) &&
+ (offset <= TRCRSCTLRn((ETM_MAX_RES_SEL - 1)))) {
+ /* 32 bit resource selection regs, 32 off, skip fixed 0,1 */
+ idx = (offset & GENMASK(6, 0)) / 4;
+ if (idx < ETM_MAX_RES_SEL) {
+ reg_csdev->driver_regval = &drvcfg->res_ctrl[idx];
+ err = 0;
+ }
+ } else if ((offset >= TRCACVRn(0)) &&
+ (offset <= TRCACATRn((ETM_MAX_SINGLE_ADDR_CMP - 1)))) {
+ /* 64 bit addr cmp regs, 16 off */
+ idx = (offset & GENMASK(6, 0)) / 8;
+ off_mask = offset & GENMASK(11, 7);
+ do {
+ CHECKREGIDX(TRCACVRn(0), addr_val, idx, off_mask);
+ CHECKREGIDX(TRCACATRn(0), addr_acc, idx, off_mask);
+ } while (0);
+ } else if ((offset >= TRCCNTRLDVRn(0)) &&
+ (offset <= TRCCNTVRn((ETMv4_MAX_CNTR - 1)))) {
+ /* 32 bit counter regs, 4 off (ETMv4_MAX_CNTR - 1) */
+ idx = (offset & GENMASK(3, 0)) / 4;
+ off_mask = offset & GENMASK(11, 4);
+ do {
+ CHECKREGIDX(TRCCNTRLDVRn(0), cntrldvr, idx, off_mask);
+ CHECKREGIDX(TRCCNTCTLRn(0), cntr_ctrl, idx, off_mask);
+ CHECKREGIDX(TRCCNTVRn(0), cntr_val, idx, off_mask);
+ } while (0);
+ }
+ return err;
+}
+
+/**
+ * etm4_cfg_load_feature - load a feature into a device instance.
+ *
+ * @csdev: An ETMv4 CoreSight device.
+ * @feat: The feature to be loaded.
+ *
+ * The function will load a feature instance into the device, checking that
+ * the register definitions are valid for the device.
+ *
+ * Parameter and register definitions will be converted into internal
+ * structures that are used to set the values in the driver when the
+ * feature is enabled for the device.
+ *
+ * The feature spinlock pointer is initialised to the same spinlock
+ * that the driver uses to protect the internal register values.
+ */
+static int etm4_cfg_load_feature(struct coresight_device *csdev,
+ struct cscfg_feature_csdev *feat_csdev)
+{
+ struct device *dev = csdev->dev.parent;
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
+ const struct cscfg_feature_desc *feat_desc = feat_csdev->feat_desc;
+ u32 offset;
+ int i = 0, err = 0;
+
+ /*
+ * essential we set the device spinlock - this is used in the generic
+ * programming routines when copying values into the drvdata structures
+ * via the pointers setup in etm4_cfg_map_reg_offset().
+ */
+ feat_csdev->drv_spinlock = &drvdata->spinlock;
+
+ /* process the register descriptions */
+ for (i = 0; i < feat_csdev->nr_regs && !err; i++) {
+ offset = feat_desc->regs_desc[i].offset;
+ err = etm4_cfg_map_reg_offset(drvdata, &feat_csdev->regs_csdev[i], offset);
+ }
+ return err;
+}
+
+/* match information when loading configurations */
+#define CS_CFG_ETM4_MATCH_FLAGS (CS_CFG_MATCH_CLASS_SRC_ALL | \
+ CS_CFG_MATCH_CLASS_SRC_ETM4)
+
+int etm4_cscfg_register(struct coresight_device *csdev)
+{
+ struct cscfg_csdev_feat_ops ops;
+
+ ops.load_feat = &etm4_cfg_load_feature;
+
+ return cscfg_register_csdev(csdev, CS_CFG_ETM4_MATCH_FLAGS, &ops);
+}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.h b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
new file mode 100644
index 000000000000..a204ad9a4792
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _CORESIGHT_ETM4X_CFG_H
+#define _CORESIGHT_ETM4X_CFG_H
+
+#include "coresight-config.h"
+#include "coresight-etm4x.h"
+
+/* ETMv4 specific config functions */
+int etm4_cscfg_register(struct coresight_device *csdev);
+
+#endif /* CORESIGHT_ETM4X_CFG_H */
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index da27cd4a3c38..e24252eaf8e4 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -39,6 +39,8 @@

#include "coresight-etm4x.h"
#include "coresight-etm-perf.h"
+#include "coresight-etm4x-cfg.h"
+#include "coresight-syscfg.h"

static int boot_enable;
module_param(boot_enable, int, 0444);
@@ -561,12 +563,15 @@ static int etm4_config_timestamp_event(struct etmv4_drvdata *drvdata)
return ret;
}

-static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
+static int etm4_parse_event_config(struct coresight_device *csdev,
struct perf_event *event)
{
int ret = 0;
+ struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct etmv4_config *config = &drvdata->config;
struct perf_event_attr *attr = &event->attr;
+ unsigned long cfg_hash;
+ int preset;

/* Clear configuration from previous run */
memset(config, 0, sizeof(struct etmv4_config));
@@ -632,6 +637,20 @@ static int etm4_parse_event_config(struct etmv4_drvdata *drvdata,
/* bit[12], Return stack enable bit */
config->cfg |= BIT(12);

+ /*
+ * Set any selected configuration and preset.
+ *
+ * This extracts the values of PMU_FORMAT_ATTR(configid) and PMU_FORMAT_ATTR(preset)
+ * in the perf attributes defined in coresight-etm-perf.c.
+ * configid uses bits 63:32 of attr->config2, preset uses bits 3:0 of attr->config.
+ * A zero configid means no configuration active, preset = 0 means no preset selected.
+ */
+ if (attr->config2 & GENMASK_ULL(63, 32)) {
+ cfg_hash = (u32)(attr->config2 >> 32);
+ preset = attr->config & 0xF;
+ ret = cscfg_csdev_enable_active_config(csdev, cfg_hash, preset);
+ }
+
out:
return ret;
}
@@ -648,7 +667,7 @@ static int etm4_enable_perf(struct coresight_device *csdev,
}

/* Configure the tracer based on the session's specifics */
- ret = etm4_parse_event_config(drvdata, event);
+ ret = etm4_parse_event_config(csdev, event);
if (ret)
goto out;
/* And enable it */
@@ -794,11 +813,18 @@ static int etm4_disable_perf(struct coresight_device *csdev,
u32 control;
struct etm_filters *filters = event->hw.addr_filters;
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ struct perf_event_attr *attr = &event->attr;

if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
return -EINVAL;

etm4_disable_hw(drvdata);
+ /*
+ * The config_id occupies bits 63:32 of the config2 perf event attr
+ * field. If this is non-zero then we will have enabled a config.
+ */
+ if (attr->config2 & GENMASK_ULL(63, 32))
+ cscfg_csdev_disable_active_config(csdev);

/*
* Check if the start/stop logic was active when the unit was stopped.
@@ -1939,6 +1965,13 @@ static int etm4_probe(struct device *dev, void __iomem *base, u32 etm_pid)
return ret;
}

+ /* register with config infrastructure & load any current features */
+ ret = etm4_cscfg_register(drvdata->csdev);
+ if (ret) {
+ coresight_unregister(drvdata->csdev);
+ return ret;
+ }
+
etmdrvdata[drvdata->cpu] = drvdata;

dev_info(&drvdata->csdev->dev, "CPU%d: %s v%d.%d initialized\n",
@@ -2025,6 +2058,7 @@ static int __exit etm4_remove_dev(struct etmv4_drvdata *drvdata)

cpus_read_unlock();

+ cscfg_unregister_csdev(drvdata->csdev);
coresight_unregister(drvdata->csdev);

return 0;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
index 007bad9e7ad8..a0640fa5c55b 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-sysfs.c
@@ -9,6 +9,7 @@
#include <linux/sysfs.h>
#include "coresight-etm4x.h"
#include "coresight-priv.h"
+#include "coresight-syscfg.h"

static int etm4_set_mode_exclude(struct etmv4_drvdata *drvdata, bool exclude)
{
@@ -269,6 +270,8 @@ static ssize_t reset_store(struct device *dev,

spin_unlock(&drvdata->spinlock);

+ cscfg_csdev_reset_feats(to_coresight_device(dev));
+
return size;
}
static DEVICE_ATTR_WO(reset);
--
2.25.1

2021-08-18 19:42:33

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 08/11] coresight: config: Add preloaded configurations

From: Mike Leach <[email protected]>

Preload set of configurations.

This patch creates a small set of preloaded configurations and features
that are available immediately after coresight has been initialised.

The current set provides a strobing feature for ETMv4, that creates a
periodic sampling of trace by switching trace generation on and off
using counters in the ETM.

A configuration called "autofdo" is also provided that uses the 'strobing'
feature and provides a couple of preset values, selectable on the perf
command line.

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/Makefile | 3 +-
.../hwtracing/coresight/coresight-cfg-afdo.c | 153 ++++++++++++++++++
.../coresight/coresight-cfg-preload.c | 31 ++++
.../coresight/coresight-cfg-preload.h | 13 ++
.../hwtracing/coresight/coresight-etm4x-cfg.h | 15 ++
.../hwtracing/coresight/coresight-syscfg.c | 9 ++
.../hwtracing/coresight/coresight-syscfg.h | 1 +
7 files changed, 224 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-afdo.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.c
create mode 100644 drivers/hwtracing/coresight/coresight-cfg-preload.h

diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 9420d33b23ac..ad44f0fe3069 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -4,7 +4,8 @@
#
obj-$(CONFIG_CORESIGHT) += coresight.o
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
- coresight-sysfs.o coresight-syscfg.o coresight-config.o
+ coresight-sysfs.o coresight-syscfg.o coresight-config.o \
+ coresight-cfg-preload.o coresight-cfg-afdo.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \
coresight-tmc-etr.o
diff --git a/drivers/hwtracing/coresight/coresight-cfg-afdo.c b/drivers/hwtracing/coresight/coresight-cfg-afdo.c
new file mode 100644
index 000000000000..84b31184252b
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-afdo.c
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <[email protected]>
+ */
+
+#include "coresight-config.h"
+
+/* ETMv4 includes and features */
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+#include "coresight-etm4x-cfg.h"
+
+/* preload configurations and features */
+
+/* preload in features for ETMv4 */
+
+/* strobe feature */
+static struct cscfg_parameter_desc strobe_params[] = {
+ {
+ .name = "window",
+ .value = 5000,
+ },
+ {
+ .name = "period",
+ .value = 10000,
+ },
+};
+
+static struct cscfg_regval_desc strobe_regs[] = {
+ /* resource selectors */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCRSCTLRn(2),
+ .hw_info = ETM4_CFG_RES_SEL,
+ .val32 = 0x20001,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCRSCTLRn(3),
+ .hw_info = ETM4_CFG_RES_SEQ,
+ .val32 = 0x20002,
+ },
+ /* strobe window counter 0 - reload from param 0 */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_SAVE,
+ .offset = TRCCNTVRn(0),
+ .hw_info = ETM4_CFG_RES_CTR,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_PARAM,
+ .offset = TRCCNTRLDVRn(0),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 0,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCCNTCTLRn(0),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 0x10001,
+ },
+ /* strobe period counter 1 - reload from param 1 */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_SAVE,
+ .offset = TRCCNTVRn(1),
+ .hw_info = ETM4_CFG_RES_CTR,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE | CS_CFG_REG_TYPE_VAL_PARAM,
+ .offset = TRCCNTRLDVRn(1),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 1,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCCNTCTLRn(1),
+ .hw_info = ETM4_CFG_RES_CTR,
+ .val32 = 0x8102,
+ },
+ /* sequencer */
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCSEQEVRn(0),
+ .hw_info = ETM4_CFG_RES_SEQ,
+ .val32 = 0x0081,
+ },
+ {
+ .type = CS_CFG_REG_TYPE_RESOURCE,
+ .offset = TRCSEQEVRn(1),
+ .hw_info = ETM4_CFG_RES_SEQ,
+ .val32 = 0x0000,
+ },
+ /* view-inst */
+ {
+ .type = CS_CFG_REG_TYPE_STD | CS_CFG_REG_TYPE_VAL_MASK,
+ .offset = TRCVICTLR,
+ .val32 = 0x0003,
+ .mask32 = 0x0003,
+ },
+ /* end of regs */
+};
+
+struct cscfg_feature_desc strobe_etm4x = {
+ .name = "strobing",
+ .description = "Generate periodic trace capture windows.\n"
+ "parameter \'window\': a number of CPU cycles (W)\n"
+ "parameter \'period\': trace enabled for W cycles every period x W cycles\n",
+ .match_flags = CS_CFG_MATCH_CLASS_SRC_ETM4,
+ .nr_params = ARRAY_SIZE(strobe_params),
+ .params_desc = strobe_params,
+ .nr_regs = ARRAY_SIZE(strobe_regs),
+ .regs_desc = strobe_regs,
+};
+
+/* create an autofdo configuration */
+
+/* we will provide 9 sets of preset parameter values */
+#define AFDO_NR_PRESETS 9
+/* the total number of parameters in used features */
+#define AFDO_NR_PARAMS ARRAY_SIZE(strobe_params)
+
+static const char *afdo_ref_names[] = {
+ "strobing",
+};
+
+/*
+ * set of presets leaves strobing window constant while varying period to allow
+ * experimentation with mark / space ratios for various workloads
+ */
+static u64 afdo_presets[AFDO_NR_PRESETS][AFDO_NR_PARAMS] = {
+ { 5000, 2 },
+ { 5000, 4 },
+ { 5000, 8 },
+ { 5000, 16 },
+ { 5000, 64 },
+ { 5000, 128 },
+ { 5000, 512 },
+ { 5000, 1024 },
+ { 5000, 4096 },
+};
+
+struct cscfg_config_desc afdo_etm4x = {
+ .name = "autofdo",
+ .description = "Setup ETMs with strobing for autofdo\n"
+ "Supplied presets allow experimentation with mark-space ratio for various loads\n",
+ .nr_feat_refs = ARRAY_SIZE(afdo_ref_names),
+ .feat_ref_names = afdo_ref_names,
+ .nr_presets = AFDO_NR_PRESETS,
+ .nr_total_params = AFDO_NR_PARAMS,
+ .presets = &afdo_presets[0][0],
+};
+
+/* end of ETM4x configurations */
+#endif /* IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X) */
diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.c b/drivers/hwtracing/coresight/coresight-cfg-preload.c
new file mode 100644
index 000000000000..751af3710d56
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-preload.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <[email protected]>
+ */
+
+#include "coresight-cfg-preload.h"
+#include "coresight-config.h"
+#include "coresight-syscfg.h"
+
+/* Basic features and configurations pre-loaded on initialisation */
+
+static struct cscfg_feature_desc *preload_feats[] = {
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+ &strobe_etm4x,
+#endif
+ NULL
+};
+
+static struct cscfg_config_desc *preload_cfgs[] = {
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+ &afdo_etm4x,
+#endif
+ NULL
+};
+
+/* preload called on initialisation */
+int cscfg_preload(void)
+{
+ return cscfg_load_config_sets(preload_cfgs, preload_feats);
+}
diff --git a/drivers/hwtracing/coresight/coresight-cfg-preload.h b/drivers/hwtracing/coresight/coresight-cfg-preload.h
new file mode 100644
index 000000000000..21299e175477
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-cfg-preload.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright(C) 2020 Linaro Limited. All rights reserved.
+ * Author: Mike Leach <[email protected]>
+ */
+
+/* declare preloaded configurations and features */
+
+/* from coresight-cfg-afdo.c - etm 4x features */
+#if IS_ENABLED(CONFIG_CORESIGHT_SOURCE_ETM4X)
+extern struct cscfg_feature_desc strobe_etm4x;
+extern struct cscfg_config_desc afdo_etm4x;
+#endif
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-cfg.h b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
index a204ad9a4792..32dab34c1dac 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x-cfg.h
@@ -9,6 +9,21 @@
#include "coresight-config.h"
#include "coresight-etm4x.h"

+/* ETMv4 specific config defines */
+
+/* resource IDs */
+
+#define ETM4_CFG_RES_CTR 0x001
+#define ETM4_CFG_RES_CMP 0x002
+#define ETM4_CFG_RES_CMP_PAIR0 0x003
+#define ETM4_CFG_RES_CMP_PAIR1 0x004
+#define ETM4_CFG_RES_SEL 0x005
+#define ETM4_CFG_RES_SEL_PAIR0 0x006
+#define ETM4_CFG_RES_SEL_PAIR1 0x007
+#define ETM4_CFG_RES_SEQ 0x008
+#define ETM4_CFG_RES_TS 0x009
+#define ETM4_CFG_RES_MASK 0x00F
+
/* ETMv4 specific config functions */
int etm4_cscfg_register(struct coresight_device *csdev);

diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index 795dba576fea..c0f764d85f20 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -752,8 +752,17 @@ int __init cscfg_init(void)
INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
atomic_set(&cscfg_mgr->sys_active_cnt, 0);

+ /* preload built-in configurations */
+ err = cscfg_preload();
+ if (err)
+ goto exit_err;
+
dev_info(cscfg_device(), "CoreSight Configuration manager initialised");
return 0;
+
+exit_err:
+ cscfg_clear_device();
+ return err;
}

void cscfg_exit(void)
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
index a52775890670..7bb8c8e497ba 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.h
+++ b/drivers/hwtracing/coresight/coresight-syscfg.h
@@ -56,6 +56,7 @@ struct cscfg_registered_csdev {
/* internal core operations for cscfg */
int __init cscfg_init(void);
void cscfg_exit(void);
+int cscfg_preload(void);

/* syscfg manager external API */
int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
--
2.25.1

2021-08-18 19:42:40

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 09/11] coresight: syscfg: Add initial configfs support

From: Mike Leach <[email protected]>

Adds configfs subsystem and attributes to the configuration manager
to enable the listing of loaded configurations and features.

The default values of feature parameters can be accessed and altered
from these attributes to affect all installed devices using the feature.

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/Kconfig | 1 +
drivers/hwtracing/coresight/Makefile | 3 +-
.../coresight/coresight-syscfg-configfs.c | 396 ++++++++++++++++++
.../coresight/coresight-syscfg-configfs.h | 45 ++
.../hwtracing/coresight/coresight-syscfg.c | 76 ++++
.../hwtracing/coresight/coresight-syscfg.h | 7 +
6 files changed, 527 insertions(+), 1 deletion(-)
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.c
create mode 100644 drivers/hwtracing/coresight/coresight-syscfg-configfs.h

diff --git a/drivers/hwtracing/coresight/Kconfig b/drivers/hwtracing/coresight/Kconfig
index 84530fd80998..f026e5c0e777 100644
--- a/drivers/hwtracing/coresight/Kconfig
+++ b/drivers/hwtracing/coresight/Kconfig
@@ -8,6 +8,7 @@ menuconfig CORESIGHT
depends on OF || ACPI
select ARM_AMBA
select PERF_EVENTS
+ select CONFIGFS_FS
help
This framework provides a kernel interface for the CoreSight debug
and trace drivers to register themselves with. It's intended to build
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index ad44f0fe3069..b6c4a48140ec 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -5,7 +5,8 @@
obj-$(CONFIG_CORESIGHT) += coresight.o
coresight-y := coresight-core.o coresight-etm-perf.o coresight-platform.o \
coresight-sysfs.o coresight-syscfg.o coresight-config.o \
- coresight-cfg-preload.o coresight-cfg-afdo.o
+ coresight-cfg-preload.o coresight-cfg-afdo.o \
+ coresight-syscfg-configfs.o
obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
coresight-tmc-y := coresight-tmc-core.o coresight-tmc-etf.o \
coresight-tmc-etr.o
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.c b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
new file mode 100644
index 000000000000..c547816b9000
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.c
@@ -0,0 +1,396 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Linaro Limited, All rights reserved.
+ * Author: Mike Leach <[email protected]>
+ */
+
+#include <linux/configfs.h>
+
+#include "coresight-syscfg-configfs.h"
+
+/* create a default ci_type. */
+static inline struct config_item_type *cscfg_create_ci_type(void)
+{
+ struct config_item_type *ci_type;
+
+ ci_type = devm_kzalloc(cscfg_device(), sizeof(*ci_type), GFP_KERNEL);
+ if (ci_type)
+ ci_type->ct_owner = THIS_MODULE;
+
+ return ci_type;
+}
+
+/* configurations sub-group */
+
+/* attributes for the config view group */
+static ssize_t cscfg_cfg_description_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, "%s", fs_config->config_desc->description);
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, description);
+
+static ssize_t cscfg_cfg_feature_refs_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_config *fs_config = container_of(to_config_group(item),
+ struct cscfg_fs_config, group);
+ const struct cscfg_config_desc *config_desc = fs_config->config_desc;
+ ssize_t ch_used = 0;
+ int i;
+
+ for (i = 0; i < config_desc->nr_feat_refs; i++)
+ ch_used += scnprintf(page + ch_used, PAGE_SIZE - ch_used,
+ "%s\n", config_desc->feat_ref_names[i]);
+ return ch_used;
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, feature_refs);
+
+/* list preset values in order of features and params */
+static ssize_t cscfg_cfg_values_show(struct config_item *item, char *page)
+{
+ const struct cscfg_feature_desc *feat_desc;
+ const struct cscfg_config_desc *config_desc;
+ struct cscfg_fs_preset *fs_preset;
+ int i, j, val_idx, preset_idx;
+ ssize_t used = 0;
+
+ fs_preset = container_of(to_config_group(item), struct cscfg_fs_preset, group);
+ config_desc = fs_preset->config_desc;
+
+ if (!config_desc->nr_presets)
+ return 0;
+
+ preset_idx = fs_preset->preset_num - 1;
+
+ /* start index on the correct array line */
+ val_idx = config_desc->nr_total_params * preset_idx;
+
+ /*
+ * A set of presets is the sum of all params in used features,
+ * in order of declaration of features and params in the features
+ */
+ for (i = 0; i < config_desc->nr_feat_refs; i++) {
+ feat_desc = cscfg_get_named_feat_desc(config_desc->feat_ref_names[i]);
+ for (j = 0; j < feat_desc->nr_params; j++) {
+ used += scnprintf(page + used, PAGE_SIZE - used,
+ "%s.%s = 0x%llx ",
+ feat_desc->name,
+ feat_desc->params_desc[j].name,
+ config_desc->presets[val_idx++]);
+ }
+ }
+ used += scnprintf(page + used, PAGE_SIZE - used, "\n");
+
+ return used;
+}
+CONFIGFS_ATTR_RO(cscfg_cfg_, values);
+
+static struct configfs_attribute *cscfg_config_view_attrs[] = {
+ &cscfg_cfg_attr_description,
+ &cscfg_cfg_attr_feature_refs,
+ NULL,
+};
+
+static struct config_item_type cscfg_config_view_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_config_view_attrs,
+};
+
+static struct configfs_attribute *cscfg_config_preset_attrs[] = {
+ &cscfg_cfg_attr_values,
+ NULL,
+};
+
+static struct config_item_type cscfg_config_preset_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_config_preset_attrs,
+};
+
+static int cscfg_add_preset_groups(struct cscfg_fs_config *cfg_view)
+{
+ int preset_num;
+ struct cscfg_fs_preset *cfg_fs_preset;
+ struct cscfg_config_desc *config_desc = cfg_view->config_desc;
+ char name[CONFIGFS_ITEM_NAME_LEN];
+
+ if (!config_desc->nr_presets)
+ return 0;
+
+ for (preset_num = 1; preset_num <= config_desc->nr_presets; preset_num++) {
+ cfg_fs_preset = devm_kzalloc(cscfg_device(),
+ sizeof(struct cscfg_fs_preset), GFP_KERNEL);
+
+ if (!cfg_fs_preset)
+ return -ENOMEM;
+
+ snprintf(name, CONFIGFS_ITEM_NAME_LEN, "preset%d", preset_num);
+ cfg_fs_preset->preset_num = preset_num;
+ cfg_fs_preset->config_desc = cfg_view->config_desc;
+ config_group_init_type_name(&cfg_fs_preset->group, name,
+ &cscfg_config_preset_type);
+ configfs_add_default_group(&cfg_fs_preset->group, &cfg_view->group);
+ }
+ return 0;
+}
+
+static struct config_group *cscfg_create_config_group(struct cscfg_config_desc *config_desc)
+{
+ struct cscfg_fs_config *cfg_view;
+ struct device *dev = cscfg_device();
+ int err;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ cfg_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_config), GFP_KERNEL);
+ if (!cfg_view)
+ return ERR_PTR(-ENOMEM);
+
+ cfg_view->config_desc = config_desc;
+ config_group_init_type_name(&cfg_view->group, config_desc->name, &cscfg_config_view_type);
+
+ /* add in a preset<n> dir for each preset */
+ err = cscfg_add_preset_groups(cfg_view);
+ if (err)
+ return ERR_PTR(err);
+
+ return &cfg_view->group;
+}
+
+/* attributes for features view */
+
+static ssize_t cscfg_feat_description_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
+ struct cscfg_fs_feature, group);
+
+ return scnprintf(page, PAGE_SIZE, "%s", fs_feat->feat_desc->description);
+}
+CONFIGFS_ATTR_RO(cscfg_feat_, description);
+
+static ssize_t cscfg_feat_matches_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
+ struct cscfg_fs_feature, group);
+ u32 match_flags = fs_feat->feat_desc->match_flags;
+ int used = 0;
+
+ if (match_flags & CS_CFG_MATCH_CLASS_SRC_ALL)
+ used = scnprintf(page, PAGE_SIZE, "SRC_ALL ");
+
+ if (match_flags & CS_CFG_MATCH_CLASS_SRC_ETM4)
+ used += scnprintf(page + used, PAGE_SIZE - used, "SRC_ETMV4 ");
+
+ used += scnprintf(page + used, PAGE_SIZE - used, "\n");
+ return used;
+}
+CONFIGFS_ATTR_RO(cscfg_feat_, matches);
+
+static ssize_t cscfg_feat_nr_params_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_feature *fs_feat = container_of(to_config_group(item),
+ struct cscfg_fs_feature, group);
+
+ return scnprintf(page, PAGE_SIZE, "%d\n", fs_feat->feat_desc->nr_params);
+}
+CONFIGFS_ATTR_RO(cscfg_feat_, nr_params);
+
+/* base feature desc attrib structures */
+static struct configfs_attribute *cscfg_feature_view_attrs[] = {
+ &cscfg_feat_attr_description,
+ &cscfg_feat_attr_matches,
+ &cscfg_feat_attr_nr_params,
+ NULL,
+};
+
+static struct config_item_type cscfg_feature_view_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_feature_view_attrs,
+};
+
+static ssize_t cscfg_param_value_show(struct config_item *item, char *page)
+{
+ struct cscfg_fs_param *param_item = container_of(to_config_group(item),
+ struct cscfg_fs_param, group);
+ u64 value = param_item->feat_desc->params_desc[param_item->param_idx].value;
+
+ return scnprintf(page, PAGE_SIZE, "0x%llx\n", value);
+}
+
+static ssize_t cscfg_param_value_store(struct config_item *item,
+ const char *page, size_t size)
+{
+ struct cscfg_fs_param *param_item = container_of(to_config_group(item),
+ struct cscfg_fs_param, group);
+ struct cscfg_feature_desc *feat_desc = param_item->feat_desc;
+ int param_idx = param_item->param_idx;
+ u64 value;
+ int err;
+
+ err = kstrtoull(page, 0, &value);
+ if (!err)
+ err = cscfg_update_feat_param_val(feat_desc, param_idx, value);
+
+ return err ? err : size;
+}
+CONFIGFS_ATTR(cscfg_param_, value);
+
+static struct configfs_attribute *cscfg_param_view_attrs[] = {
+ &cscfg_param_attr_value,
+ NULL,
+};
+
+static struct config_item_type cscfg_param_view_type = {
+ .ct_owner = THIS_MODULE,
+ .ct_attrs = cscfg_param_view_attrs,
+};
+
+/*
+ * configfs has far less functionality provided to add attributes dynamically than sysfs,
+ * and the show and store fns pass the enclosing config_item so the actual attribute cannot
+ * be determined. Therefore we add each item as a group directory, with a value attribute.
+ */
+static int cscfg_create_params_group_items(struct cscfg_feature_desc *feat_desc,
+ struct config_group *params_group)
+{
+ struct device *dev = cscfg_device();
+ struct cscfg_fs_param *param_item;
+ int i;
+
+ /* parameter items - as groups with default_value attribute */
+ for (i = 0; i < feat_desc->nr_params; i++) {
+ param_item = devm_kzalloc(dev, sizeof(struct cscfg_fs_param), GFP_KERNEL);
+ if (!param_item)
+ return -ENOMEM;
+ param_item->feat_desc = feat_desc;
+ param_item->param_idx = i;
+ config_group_init_type_name(&param_item->group,
+ feat_desc->params_desc[i].name,
+ &cscfg_param_view_type);
+ configfs_add_default_group(&param_item->group, params_group);
+ }
+ return 0;
+}
+
+static struct config_group *cscfg_create_feature_group(struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_fs_feature *feat_view;
+ struct config_item_type *params_group_type;
+ struct config_group *params_group = NULL;
+ struct device *dev = cscfg_device();
+ int item_err;
+
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
+ feat_view = devm_kzalloc(dev, sizeof(struct cscfg_fs_feature), GFP_KERNEL);
+ if (!feat_view)
+ return ERR_PTR(-ENOMEM);
+
+ if (feat_desc->nr_params) {
+ params_group = devm_kzalloc(dev, sizeof(struct config_group), GFP_KERNEL);
+ if (!params_group)
+ return ERR_PTR(-ENOMEM);
+
+ params_group_type = cscfg_create_ci_type();
+ if (!params_group_type)
+ return ERR_PTR(-ENOMEM);
+ }
+
+ feat_view->feat_desc = feat_desc;
+ config_group_init_type_name(&feat_view->group,
+ feat_desc->name,
+ &cscfg_feature_view_type);
+ if (params_group) {
+ config_group_init_type_name(params_group, "params", params_group_type);
+ configfs_add_default_group(params_group, &feat_view->group);
+ item_err = cscfg_create_params_group_items(feat_desc, params_group);
+ if (item_err)
+ return ERR_PTR(item_err);
+ }
+ return &feat_view->group;
+}
+
+static struct config_item_type cscfg_configs_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group cscfg_configs_grp = {
+ .cg_item = {
+ .ci_namebuf = "configurations",
+ .ci_type = &cscfg_configs_type,
+ },
+};
+
+/* add configuration to configurations group */
+int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc)
+{
+ struct config_group *new_group;
+ int err;
+
+ new_group = cscfg_create_config_group(config_desc);
+ if (IS_ERR(new_group))
+ return PTR_ERR(new_group);
+ err = configfs_register_group(&cscfg_configs_grp, new_group);
+ return err;
+}
+
+static struct config_item_type cscfg_features_type = {
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group cscfg_features_grp = {
+ .cg_item = {
+ .ci_namebuf = "features",
+ .ci_type = &cscfg_features_type,
+ },
+};
+
+/* add feature to features group */
+int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc)
+{
+ struct config_group *new_group;
+ int err;
+
+ new_group = cscfg_create_feature_group(feat_desc);
+ if (IS_ERR(new_group))
+ return PTR_ERR(new_group);
+ err = configfs_register_group(&cscfg_features_grp, new_group);
+ return err;
+}
+
+int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr)
+{
+ struct configfs_subsystem *subsys;
+ struct config_item_type *ci_type;
+
+ if (!cscfg_mgr)
+ return -EINVAL;
+
+ ci_type = cscfg_create_ci_type();
+ if (!ci_type)
+ return -ENOMEM;
+
+ subsys = &cscfg_mgr->cfgfs_subsys;
+ config_item_set_name(&subsys->su_group.cg_item, CSCFG_FS_SUBSYS_NAME);
+ subsys->su_group.cg_item.ci_type = ci_type;
+
+ config_group_init(&subsys->su_group);
+ mutex_init(&subsys->su_mutex);
+
+ /* Add default groups to subsystem */
+ config_group_init(&cscfg_configs_grp);
+ configfs_add_default_group(&cscfg_configs_grp, &subsys->su_group);
+
+ config_group_init(&cscfg_features_grp);
+ configfs_add_default_group(&cscfg_features_grp, &subsys->su_group);
+
+ return configfs_register_subsystem(subsys);
+}
+
+void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr)
+{
+ configfs_unregister_subsystem(&cscfg_mgr->cfgfs_subsys);
+}
diff --git a/drivers/hwtracing/coresight/coresight-syscfg-configfs.h b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
new file mode 100644
index 000000000000..7d6ffe35ca4c
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-syscfg-configfs.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Coresight system configuration driver - support for configfs.
+ */
+
+#ifndef CORESIGHT_SYSCFG_CONFIGFS_H
+#define CORESIGHT_SYSCFG_CONFIGFS_H
+
+#include <linux/configfs.h>
+#include "coresight-syscfg.h"
+
+#define CSCFG_FS_SUBSYS_NAME "cs-syscfg"
+
+/* container for configuration view */
+struct cscfg_fs_config {
+ struct cscfg_config_desc *config_desc;
+ struct config_group group;
+};
+
+/* container for feature view */
+struct cscfg_fs_feature {
+ struct cscfg_feature_desc *feat_desc;
+ struct config_group group;
+};
+
+/* container for parameter view */
+struct cscfg_fs_param {
+ int param_idx;
+ struct cscfg_feature_desc *feat_desc;
+ struct config_group group;
+};
+
+/* container for preset view */
+struct cscfg_fs_preset {
+ int preset_num;
+ struct cscfg_config_desc *config_desc;
+ struct config_group group;
+};
+
+int cscfg_configfs_init(struct cscfg_manager *cscfg_mgr);
+void cscfg_configfs_release(struct cscfg_manager *cscfg_mgr);
+int cscfg_configfs_add_config(struct cscfg_config_desc *config_desc);
+int cscfg_configfs_add_feature(struct cscfg_feature_desc *feat_desc);
+
+#endif /* CORESIGHT_SYSCFG_CONFIGFS_H */
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index c0f764d85f20..fc0760f55c53 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -9,6 +9,7 @@
#include "coresight-config.h"
#include "coresight-etm-perf.h"
#include "coresight-syscfg.h"
+#include "coresight-syscfg-configfs.h"

/*
* cscfg_ API manages configurations and features for the entire coresight
@@ -286,6 +287,72 @@ static int cscfg_load_config(struct cscfg_config_desc *config_desc)
return 0;
}

+/* get a feature descriptor by name */
+const struct cscfg_feature_desc *cscfg_get_named_feat_desc(const char *name)
+{
+ const struct cscfg_feature_desc *feat_desc = NULL, *feat_desc_item;
+
+ mutex_lock(&cscfg_mutex);
+
+ list_for_each_entry(feat_desc_item, &cscfg_mgr->feat_desc_list, item) {
+ if (strcmp(feat_desc_item->name, name) == 0) {
+ feat_desc = feat_desc_item;
+ break;
+ }
+ }
+
+ mutex_unlock(&cscfg_mutex);
+ return feat_desc;
+}
+
+/* called with cscfg_mutex held */
+static struct cscfg_feature_csdev *
+cscfg_csdev_get_feat_from_desc(struct coresight_device *csdev,
+ struct cscfg_feature_desc *feat_desc)
+{
+ struct cscfg_feature_csdev *feat_csdev;
+
+ list_for_each_entry(feat_csdev, &csdev->feature_csdev_list, node) {
+ if (feat_csdev->feat_desc == feat_desc)
+ return feat_csdev;
+ }
+ return NULL;
+}
+
+int cscfg_update_feat_param_val(struct cscfg_feature_desc *feat_desc,
+ int param_idx, u64 value)
+{
+ int err = 0;
+ struct cscfg_feature_csdev *feat_csdev;
+ struct cscfg_registered_csdev *csdev_item;
+
+ mutex_lock(&cscfg_mutex);
+
+ /* check if any config active & return busy */
+ if (atomic_read(&cscfg_mgr->sys_active_cnt)) {
+ err = -EBUSY;
+ goto unlock_exit;
+ }
+
+ /* set the value */
+ if ((param_idx < 0) || (param_idx >= feat_desc->nr_params)) {
+ err = -EINVAL;
+ goto unlock_exit;
+ }
+ feat_desc->params_desc[param_idx].value = value;
+
+ /* update loaded instances.*/
+ list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
+ feat_csdev = cscfg_csdev_get_feat_from_desc(csdev_item->csdev, feat_desc);
+ if (feat_csdev)
+ feat_csdev->params_csdev[param_idx].current_value = value;
+ }
+
+unlock_exit:
+ mutex_unlock(&cscfg_mutex);
+ return err;
+}
+
/**
* cscfg_load_config_sets - API function to load feature and config sets.
*
@@ -307,6 +374,8 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
if (feat_descs) {
while (feat_descs[i]) {
err = cscfg_load_feat(feat_descs[i]);
+ if (!err)
+ err = cscfg_configfs_add_feature(feat_descs[i]);
if (err) {
pr_err("coresight-syscfg: Failed to load feature %s\n",
feat_descs[i]->name);
@@ -321,6 +390,8 @@ int cscfg_load_config_sets(struct cscfg_config_desc **config_descs,
if (config_descs) {
while (config_descs[i]) {
err = cscfg_load_config(config_descs[i]);
+ if (!err)
+ err = cscfg_configfs_add_config(config_descs[i]);
if (err) {
pr_err("coresight-syscfg: Failed to load configuration %s\n",
config_descs[i]->name);
@@ -734,6 +805,7 @@ static void cscfg_clear_device(void)
list_for_each_entry(cfg_desc, &cscfg_mgr->config_desc_list, item) {
etm_perf_del_symlink_cscfg(cfg_desc);
}
+ cscfg_configfs_release(cscfg_mgr);
device_unregister(cscfg_device());
mutex_unlock(&cscfg_mutex);
}
@@ -747,6 +819,10 @@ int __init cscfg_init(void)
if (err)
return err;

+ err = cscfg_configfs_init(cscfg_mgr);
+ if (err)
+ goto exit_err;
+
INIT_LIST_HEAD(&cscfg_mgr->csdev_desc_list);
INIT_LIST_HEAD(&cscfg_mgr->feat_desc_list);
INIT_LIST_HEAD(&cscfg_mgr->config_desc_list);
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.h b/drivers/hwtracing/coresight/coresight-syscfg.h
index 7bb8c8e497ba..8d018efd6ead 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.h
+++ b/drivers/hwtracing/coresight/coresight-syscfg.h
@@ -6,6 +6,7 @@
#ifndef CORESIGHT_SYSCFG_H
#define CORESIGHT_SYSCFG_H

+#include <linux/configfs.h>
#include <linux/coresight.h>
#include <linux/device.h>

@@ -25,6 +26,7 @@
* @feat_desc_list: List of feature descriptors to load into registered devices.
* @config_desc_list: List of system configuration descriptors to load into registered devices.
* @sys_active_cnt: Total number of active config descriptor references.
+ * @cfgfs_subsys: configfs subsystem used to manage configurations.
*/
struct cscfg_manager {
struct device dev;
@@ -32,6 +34,7 @@ struct cscfg_manager {
struct list_head feat_desc_list;
struct list_head config_desc_list;
atomic_t sys_active_cnt;
+ struct configfs_subsystem cfgfs_subsys;
};

/* get reference to dev in cscfg_manager */
@@ -57,6 +60,10 @@ struct cscfg_registered_csdev {
int __init cscfg_init(void);
void cscfg_exit(void);
int cscfg_preload(void);
+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);
+

/* syscfg manager external API */
int cscfg_load_config_sets(struct cscfg_config_desc **cfg_descs,
--
2.25.1

2021-08-18 19:43:09

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 10/11] Documentation: coresight: Add documentation for CoreSight config

From: Mike Leach <[email protected]>

Adds documentation for the CoreSight System configuration manager.

Cc: Jonathan Corbet <[email protected]>
Cc: [email protected]
Signed-off-by: Mike Leach <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[Fixed coresight-config.rst documentation link]
Signed-off-by: Mathieu Poirier <[email protected]>
---
.../trace/coresight/coresight-config.rst | 244 ++++++++++++++++++
Documentation/trace/coresight/coresight.rst | 15 ++
2 files changed, 259 insertions(+)
create mode 100644 Documentation/trace/coresight/coresight-config.rst

diff --git a/Documentation/trace/coresight/coresight-config.rst b/Documentation/trace/coresight/coresight-config.rst
new file mode 100644
index 000000000000..a4e3ef295240
--- /dev/null
+++ b/Documentation/trace/coresight/coresight-config.rst
@@ -0,0 +1,244 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+======================================
+CoreSight System Configuration Manager
+======================================
+
+ :Author: Mike Leach <[email protected]>
+ :Date: October 2020
+
+Introduction
+============
+
+The CoreSight System Configuration manager is an API that allows the
+programming of the CoreSight system with pre-defined configurations that
+can then be easily enabled from sysfs or perf.
+
+Many CoreSight components can be programmed in complex ways - especially ETMs.
+In addition, components can interact across the CoreSight system, often via
+the cross trigger components such as CTI and CTM. These system settings can
+be defined and enabled as named configurations.
+
+
+Basic Concepts
+==============
+
+This section introduces the basic concepts of a CoreSight system configuration.
+
+
+Features
+--------
+
+A feature is a named set of programming for a CoreSight device. The programming
+is device dependent, and can be defined in terms of absolute register values,
+resource usage and parameter values.
+
+The feature is defined using a descriptor. This descriptor is used to load onto
+a matching device, either when the feature is loaded into the system, or when the
+CoreSight device is registered with the configuration manager.
+
+The load process involves interpreting the descriptor into a set of register
+accesses in the driver - the resource usage and parameter descriptions
+translated into appropriate register accesses. This interpretation makes it easy
+and efficient for the feature to be programmed onto the device when required.
+
+The feature will not be active on the device until the feature is enabled, and
+the device itself is enabled. When the device is enabled then enabled features
+will be programmed into the device hardware.
+
+A feature is enabled as part of a configuration being enabled on the system.
+
+
+Parameter Value
+~~~~~~~~~~~~~~~
+
+A parameter value is a named value that may be set by the user prior to the
+feature being enabled that can adjust the behaviour of the operation programmed
+by the feature.
+
+For example, this could be a count value in a programmed operation that repeats
+at a given rate. When the feature is enabled then the current value of the
+parameter is used in programming the device.
+
+The feature descriptor defines a default value for a parameter, which is used
+if the user does not supply a new value.
+
+Users can update parameter values using the configfs API for the CoreSight
+system - which is described below.
+
+The current value of the parameter is loaded into the device when the feature
+is enabled on that device.
+
+
+Configurations
+--------------
+
+A configuration defines a set of features that are to be used in a trace
+session where the configuration is selected. For any trace session only one
+configuration may be selected.
+
+The features defined may be on any type of device that is registered
+to support system configuration. A configuration may select features to be
+enabled on a class of devices - i.e. any ETMv4, or specific devices, e.g. a
+specific CTI on the system.
+
+As with the feature, a descriptor is used to define the configuration.
+This will define the features that must be enabled as part of the configuration
+as well as any preset values that can be used to override default parameter
+values.
+
+
+Preset Values
+~~~~~~~~~~~~~
+
+Preset values are easily selectable sets of parameter values for the features
+that the configuration uses. The number of values in a single preset set, equals
+the sum of parameter values in the features used by the configuration.
+
+e.g. a configuration consists of 3 features, one has 2 parameters, one has
+a single parameter, and another has no parameters. A single preset set will
+therefore have 3 values.
+
+Presets are optionally defined by the configuration, up to 15 can be defined.
+If no preset is selected, then the parameter values defined in the feature
+are used as normal.
+
+
+Operation
+~~~~~~~~~
+
+The following steps take place in the operation of a configuration.
+
+1) In this example, the configuration is 'autofdo', which has an
+ associated feature 'strobing' that works on ETMv4 CoreSight Devices.
+
+2) The configuration is enabled. For example 'perf' may select the
+ configuration as part of its command line::
+
+ perf record -e cs_etm/autofdo/ myapp
+
+ which will enable the 'autofdo' configuration.
+
+3) perf starts tracing on the system. As each ETMv4 that perf uses for
+ trace is enabled, the configuration manager will check if the ETMv4
+ has a feature that relates to the currently active configuration.
+ In this case 'strobing' is enabled & programmed into the ETMv4.
+
+4) When the ETMv4 is disabled, any registers marked as needing to be
+ saved will be read back.
+
+5) At the end of the perf session, the configuration will be disabled.
+
+
+Viewing Configurations and Features
+===================================
+
+The set of configurations and features that are currently loaded into the
+system can be viewed using the configfs API.
+
+Mount configfs as normal and the 'cs-syscfg' subsystem will appear::
+
+ $ ls /config
+ cs-syscfg stp-policy
+
+This has two sub-directories::
+
+ $ cd cs-syscfg/
+ $ ls
+ configurations features
+
+The system has the configuration 'autofdo' built in. It may be examined as
+follows::
+
+ $ cd configurations/
+ $ ls
+ autofdo
+ $ cd autofdo/
+ $ ls
+ description preset1 preset3 preset5 preset7 preset9
+ feature_refs preset2 preset4 preset6 preset8
+ $ cat description
+ Setup ETMs with strobing for autofdo
+ $ cat feature_refs
+ strobing
+
+Each preset declared has a preset<n> subdirectory declared. The values for
+the preset can be examined::
+
+ $ cat preset1/values
+ strobing.window = 0x1388 strobing.period = 0x2
+ $ cat preset2/values
+ strobing.window = 0x1388 strobing.period = 0x4
+
+The features referenced by the configuration can be examined in the features
+directory::
+
+ $ cd ../../features/strobing/
+ $ ls
+ description matches nr_params params
+ $ cat description
+ Generate periodic trace capture windows.
+ parameter 'window': a number of CPU cycles (W)
+ parameter 'period': trace enabled for W cycles every period x W cycles
+ $ cat matches
+ SRC_ETMV4
+ $ cat nr_params
+ 2
+
+Move to the params directory to examine and adjust parameters::
+
+ cd params
+ $ ls
+ period window
+ $ cd period
+ $ ls
+ value
+ $ cat value
+ 0x2710
+ # echo 15000 > value
+ # cat value
+ 0x3a98
+
+Parameters adjusted in this way are reflected in all device instances that have
+loaded the feature.
+
+
+Using Configurations in perf
+============================
+
+The configurations loaded into the CoreSight configuration management are
+also declared in the perf 'cs_etm' event infrastructure so that they can
+be selected when running trace under perf::
+
+ $ ls /sys/devices/cs_etm
+ configurations format perf_event_mux_interval_ms sinks type
+ events nr_addr_filters power
+
+Key directories here are 'configurations' - which lists the loaded
+configurations, and 'events' - a generic perf directory which allows
+selection on the perf command line.::
+
+ $ ls configurations/
+ autofdo
+ $ cat configurations/autofdo
+ 0xa7c3dddd
+
+As with the sinks entries, this provides a hash of the configuration name.
+The entry in the 'events' directory uses perfs built in syntax generator
+to substitute the syntax for the name when evaluating the command::
+
+ $ ls events/
+ autofdo
+ $ cat events/autofdo
+ configid=0xa7c3dddd
+
+The 'autofdo' configuration may be selected on the perf command line::
+
+ $ perf record -e cs_etm/autofdo/u --per-thread <application>
+
+A preset to override the current parameter values can also be selected::
+
+ $ perf record -e cs_etm/autofdo,preset=1/u --per-thread <application>
+
+When configurations are selected in this way, then the trace sink used is
+automatically selected.
diff --git a/Documentation/trace/coresight/coresight.rst b/Documentation/trace/coresight/coresight.rst
index 1ec8dc35b1d8..a15571d96cc8 100644
--- a/Documentation/trace/coresight/coresight.rst
+++ b/Documentation/trace/coresight/coresight.rst
@@ -620,6 +620,19 @@ channels on the CTM (Cross Trigger Matrix).
A separate documentation file is provided to explain the use of these devices.
(Documentation/trace/coresight/coresight-ect.rst) [#fourth]_.

+CoreSight System Configuration
+------------------------------
+
+CoreSight components can be complex devices with many programming options.
+Furthermore, components can be programmed to interact with each other across the
+complete system.
+
+A CoreSight System Configuration manager is provided to allow these complex programming
+configurations to be selected and used easily from perf and sysfs.
+
+See the separate document for further information.
+(Documentation/trace/coresight/coresight-config.rst) [#fifth]_.
+

.. [#first] Documentation/ABI/testing/sysfs-bus-coresight-devices-stm

@@ -628,3 +641,5 @@ A separate documentation file is provided to explain the use of these devices.
.. [#third] https://github.com/Linaro/perf-opencsd

.. [#fourth] Documentation/trace/coresight/coresight-ect.rst
+
+.. [#fifth] Documentation/trace/coresight/coresight-config.rst
--
2.25.1

2021-08-18 19:43:53

by Mathieu Poirier

[permalink] [raw]
Subject: [PATCH 11/11] coresight: Replace deprecated CPU-hotplug functions.

From: Sebastian Andrzej Siewior <[email protected]>

The functions get_online_cpus() and put_online_cpus() have been
deprecated during the CPU hotplug rework. They map directly to
cpus_read_lock() and cpus_read_unlock().

Replace deprecated CPU-hotplug functions with the official version.
The behavior remains unchanged.

Cc: Mathieu Poirier <[email protected]>
Cc: Suzuki K Poulose <[email protected]>
Cc: Mike Leach <[email protected]>
Cc: Leo Yan <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Sebastian Andrzej Siewior <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Mathieu Poirier <[email protected]>
---
drivers/hwtracing/coresight/coresight-cpu-debug.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 9731d3a96073..00de46565bc4 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -588,11 +588,11 @@ static int debug_probe(struct amba_device *adev, const struct amba_id *id)

drvdata->base = base;

- get_online_cpus();
+ cpus_read_lock();
per_cpu(debug_drvdata, drvdata->cpu) = drvdata;
ret = smp_call_function_single(drvdata->cpu, debug_init_arch_data,
drvdata, 1);
- put_online_cpus();
+ cpus_read_unlock();

if (ret) {
dev_err(dev, "CPU%d debug arch init failed\n", drvdata->cpu);
--
2.25.1