summaryrefslogtreecommitdiff
path: root/drivers/hwtracing
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/coresight/coresight-catu.c10
-rw-r--r--drivers/hwtracing/coresight/coresight-core.c30
-rw-r--r--drivers/hwtracing/coresight/coresight-ctcu-core.c9
-rw-r--r--drivers/hwtracing/coresight/coresight-cti-core.c5
-rw-r--r--drivers/hwtracing/coresight/coresight-cti.h5
-rw-r--r--drivers/hwtracing/coresight/coresight-dummy.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c8
-rw-r--r--drivers/hwtracing/coresight/coresight-etm-perf.c3
-rw-r--r--drivers/hwtracing/coresight/coresight-etm3x-core.c59
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-core.c140
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.h5
-rw-r--r--drivers/hwtracing/coresight/coresight-priv.h3
-rw-r--r--drivers/hwtracing/coresight/coresight-sysfs.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etf.c10
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-etr.c22
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.h3
-rw-r--r--drivers/hwtracing/coresight/coresight-tpda.c7
-rw-r--r--drivers/hwtracing/coresight/coresight-tpdm.c174
-rw-r--r--drivers/hwtracing/coresight/coresight-tpdm.h12
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-trbe.c4
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.c9
-rw-r--r--drivers/hwtracing/intel_th/core.c22
23 files changed, 377 insertions, 169 deletions
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index a3ccb7034ae1..69b36bae97ab 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -397,7 +397,7 @@ static int catu_wait_for_ready(struct catu_drvdata *drvdata)
}
static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
- void *data)
+ struct coresight_path *path)
{
int rc;
u32 control, mode;
@@ -425,7 +425,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
etrdev = coresight_find_input_type(
csdev->pdata, CORESIGHT_DEV_TYPE_SINK, etr_subtype);
if (etrdev) {
- etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, data);
+ etr_buf = tmc_etr_get_buffer(etrdev, cs_mode, path);
if (IS_ERR(etr_buf))
return PTR_ERR(etr_buf);
}
@@ -455,7 +455,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
}
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
- void *data)
+ struct coresight_path *path)
{
int rc = 0;
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
@@ -463,7 +463,7 @@ static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
if (csdev->refcnt == 0) {
CS_UNLOCK(catu_drvdata->base);
- rc = catu_enable_hw(catu_drvdata, mode, data);
+ rc = catu_enable_hw(catu_drvdata, mode, path);
CS_LOCK(catu_drvdata->base);
}
if (!rc)
@@ -488,7 +488,7 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
return rc;
}
-static int catu_disable(struct coresight_device *csdev, void *__unused)
+static int catu_disable(struct coresight_device *csdev, struct coresight_path *path)
{
int rc = 0;
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
index 3267192f0c1c..c660cf8adb1c 100644
--- a/drivers/hwtracing/coresight/coresight-core.c
+++ b/drivers/hwtracing/coresight/coresight-core.c
@@ -300,9 +300,10 @@ unlock:
EXPORT_SYMBOL_GPL(coresight_add_helper);
static int coresight_enable_sink(struct coresight_device *csdev,
- enum cs_mode mode, void *data)
+ enum cs_mode mode,
+ struct coresight_path *path)
{
- return sink_ops(csdev)->enable(csdev, mode, data);
+ return sink_ops(csdev)->enable(csdev, mode, path);
}
static void coresight_disable_sink(struct coresight_device *csdev)
@@ -355,17 +356,20 @@ static bool coresight_is_helper(struct coresight_device *csdev)
}
static int coresight_enable_helper(struct coresight_device *csdev,
- enum cs_mode mode, void *data)
+ enum cs_mode mode,
+ struct coresight_path *path)
{
- return helper_ops(csdev)->enable(csdev, mode, data);
+ return helper_ops(csdev)->enable(csdev, mode, path);
}
-static void coresight_disable_helper(struct coresight_device *csdev, void *data)
+static void coresight_disable_helper(struct coresight_device *csdev,
+ struct coresight_path *path)
{
- helper_ops(csdev)->disable(csdev, data);
+ helper_ops(csdev)->disable(csdev, path);
}
-static void coresight_disable_helpers(struct coresight_device *csdev, void *data)
+static void coresight_disable_helpers(struct coresight_device *csdev,
+ struct coresight_path *path)
{
int i;
struct coresight_device *helper;
@@ -373,7 +377,7 @@ static void coresight_disable_helpers(struct coresight_device *csdev, void *data
for (i = 0; i < csdev->pdata->nr_outconns; ++i) {
helper = csdev->pdata->out_conns[i]->dest_dev;
if (helper && coresight_is_helper(helper))
- coresight_disable_helper(helper, data);
+ coresight_disable_helper(helper, path);
}
}
@@ -479,7 +483,8 @@ void coresight_disable_path(struct coresight_path *path)
EXPORT_SYMBOL_GPL(coresight_disable_path);
static int coresight_enable_helpers(struct coresight_device *csdev,
- enum cs_mode mode, void *data)
+ enum cs_mode mode,
+ struct coresight_path *path)
{
int i, ret = 0;
struct coresight_device *helper;
@@ -489,7 +494,7 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
if (!helper || !coresight_is_helper(helper))
continue;
- ret = coresight_enable_helper(helper, mode, data);
+ ret = coresight_enable_helper(helper, mode, path);
if (ret)
return ret;
}
@@ -497,8 +502,7 @@ static int coresight_enable_helpers(struct coresight_device *csdev,
return 0;
}
-int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
- void *sink_data)
+int coresight_enable_path(struct coresight_path *path, enum cs_mode mode)
{
int ret = 0;
u32 type;
@@ -528,7 +532,7 @@ int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
switch (type) {
case CORESIGHT_DEV_TYPE_SINK:
- ret = coresight_enable_sink(csdev, mode, sink_data);
+ ret = coresight_enable_sink(csdev, mode, path);
/*
* Sink is the first component turned on. If we
* failed to enable the sink, there are no components
diff --git a/drivers/hwtracing/coresight/coresight-ctcu-core.c b/drivers/hwtracing/coresight/coresight-ctcu-core.c
index c586495e9a08..abed15eb72b4 100644
--- a/drivers/hwtracing/coresight/coresight-ctcu-core.c
+++ b/drivers/hwtracing/coresight/coresight-ctcu-core.c
@@ -156,17 +156,14 @@ static int ctcu_set_etr_traceid(struct coresight_device *csdev, struct coresight
return __ctcu_set_etr_traceid(csdev, traceid, port_num, enable);
}
-static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
+static int ctcu_enable(struct coresight_device *csdev, enum cs_mode mode,
+ struct coresight_path *path)
{
- struct coresight_path *path = (struct coresight_path *)data;
-
return ctcu_set_etr_traceid(csdev, path, true);
}
-static int ctcu_disable(struct coresight_device *csdev, void *data)
+static int ctcu_disable(struct coresight_device *csdev, struct coresight_path *path)
{
- struct coresight_path *path = (struct coresight_path *)data;
-
return ctcu_set_etr_traceid(csdev, path, false);
}
diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 8fb30dd73fd2..bfbc365bb2ef 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -799,14 +799,15 @@ static void cti_pm_release(struct cti_drvdata *drvdata)
}
/** cti ect operations **/
-int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
+int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
+ struct coresight_path *path)
{
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
return cti_enable_hw(drvdata);
}
-int cti_disable(struct coresight_device *csdev, void *data)
+int cti_disable(struct coresight_device *csdev, struct coresight_path *path)
{
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);
diff --git a/drivers/hwtracing/coresight/coresight-cti.h b/drivers/hwtracing/coresight/coresight-cti.h
index 8362a47c939c..4f89091ee93f 100644
--- a/drivers/hwtracing/coresight/coresight-cti.h
+++ b/drivers/hwtracing/coresight/coresight-cti.h
@@ -216,8 +216,9 @@ int cti_add_connection_entry(struct device *dev, struct cti_drvdata *drvdata,
const char *assoc_dev_name);
struct cti_trig_con *cti_allocate_trig_con(struct device *dev, int in_sigs,
int out_sigs);
-int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data);
-int cti_disable(struct coresight_device *csdev, void *data);
+int cti_enable(struct coresight_device *csdev, enum cs_mode mode,
+ struct coresight_path *path);
+int cti_disable(struct coresight_device *csdev, struct coresight_path *path);
void cti_write_all_hw_regs(struct cti_drvdata *drvdata);
void cti_write_intack(struct device *dev, u32 ackval);
void cti_write_single_reg(struct cti_drvdata *drvdata, int offset, u32 value);
diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
index aaa92b5081e3..14322c99e29d 100644
--- a/drivers/hwtracing/coresight/coresight-dummy.c
+++ b/drivers/hwtracing/coresight/coresight-dummy.c
@@ -52,7 +52,7 @@ static int dummy_source_trace_id(struct coresight_device *csdev, __maybe_unused
}
static int dummy_sink_enable(struct coresight_device *csdev, enum cs_mode mode,
- void *data)
+ struct coresight_path *path)
{
dev_dbg(csdev->dev.parent, "Dummy sink enabled\n");
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 35db1b6093d1..6657602d8f2e 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -167,13 +167,13 @@ out:
return ret;
}
-static int etb_enable_perf(struct coresight_device *csdev, void *data)
+static int etb_enable_perf(struct coresight_device *csdev, struct coresight_path *path)
{
int ret = 0;
pid_t pid;
unsigned long flags;
struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- struct perf_output_handle *handle = data;
+ struct perf_output_handle *handle = path->handle;
struct cs_buffers *buf = etm_perf_sink_config(handle);
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -224,7 +224,7 @@ out:
}
static int etb_enable(struct coresight_device *csdev, enum cs_mode mode,
- void *data)
+ struct coresight_path *path)
{
int ret;
@@ -233,7 +233,7 @@ static int etb_enable(struct coresight_device *csdev, enum cs_mode mode,
ret = etb_enable_sysfs(csdev);
break;
case CS_MODE_PERF:
- ret = etb_enable_perf(csdev, data);
+ ret = etb_enable_perf(csdev, path);
break;
default:
ret = -EINVAL;
diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
index f677c08233ba..17afa0f4cdee 100644
--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
+++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
@@ -520,13 +520,14 @@ static void etm_event_start(struct perf_event *event, int flags)
goto out;
path = etm_event_cpu_path(event_data, cpu);
+ path->handle = handle;
/* We need a sink, no need to continue without one */
sink = coresight_get_sink(path);
if (WARN_ON_ONCE(!sink))
goto fail_end_stop;
/* Nothing will happen without a path */
- if (coresight_enable_path(path, CS_MODE_PERF, handle))
+ if (coresight_enable_path(path, CS_MODE_PERF))
goto fail_end_stop;
/* Finally enable the tracer */
diff --git a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
index 45630a1cd32f..a5e809589d3e 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
@@ -439,13 +439,26 @@ struct etm_enable_arg {
int rc;
};
-static void etm_enable_hw_smp_call(void *info)
+static void etm_enable_sysfs_smp_call(void *info)
{
struct etm_enable_arg *arg = info;
+ struct coresight_device *csdev;
if (WARN_ON(!arg))
return;
+
+ csdev = arg->drvdata->csdev;
+ if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
+ /* Someone is already using the tracer */
+ arg->rc = -EBUSY;
+ return;
+ }
+
arg->rc = etm_enable_hw(arg->drvdata);
+
+ /* The tracer didn't start */
+ if (arg->rc)
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
}
static int etm_cpu_id(struct coresight_device *csdev)
@@ -465,16 +478,26 @@ static int etm_enable_perf(struct coresight_device *csdev,
struct coresight_path *path)
{
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
return -EINVAL;
+ if (!coresight_take_mode(csdev, CS_MODE_PERF))
+ return -EBUSY;
+
/* Configure the tracer based on the session's specifics */
etm_parse_event_config(drvdata, event);
drvdata->traceid = path->trace_id;
/* And enable it */
- return etm_enable_hw(drvdata);
+ ret = etm_enable_hw(drvdata);
+
+ /* Failed to start tracer; roll back to DISABLED mode */
+ if (ret)
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
+
+ return ret;
}
static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_path *path)
@@ -494,7 +517,7 @@ static int etm_enable_sysfs(struct coresight_device *csdev, struct coresight_pat
if (cpu_online(drvdata->cpu)) {
arg.drvdata = drvdata;
ret = smp_call_function_single(drvdata->cpu,
- etm_enable_hw_smp_call, &arg, 1);
+ etm_enable_sysfs_smp_call, &arg, 1);
if (!ret)
ret = arg.rc;
if (!ret)
@@ -517,12 +540,6 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
enum cs_mode mode, struct coresight_path *path)
{
int ret;
- struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- if (!coresight_take_mode(csdev, mode)) {
- /* Someone is already using the tracer */
- return -EBUSY;
- }
switch (mode) {
case CS_MODE_SYSFS:
@@ -535,17 +552,12 @@ static int etm_enable(struct coresight_device *csdev, struct perf_event *event,
ret = -EINVAL;
}
- /* The tracer didn't start */
- if (ret)
- coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
-
return ret;
}
-static void etm_disable_hw(void *info)
+static void etm_disable_hw(struct etm_drvdata *drvdata)
{
int i;
- struct etm_drvdata *drvdata = info;
struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
@@ -567,6 +579,15 @@ static void etm_disable_hw(void *info)
"cpu: %d disable smp call done\n", drvdata->cpu);
}
+static void etm_disable_sysfs_smp_call(void *info)
+{
+ struct etm_drvdata *drvdata = info;
+
+ etm_disable_hw(drvdata);
+
+ coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
+}
+
static void etm_disable_perf(struct coresight_device *csdev)
{
struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
@@ -588,6 +609,8 @@ static void etm_disable_perf(struct coresight_device *csdev)
CS_LOCK(drvdata->csa.base);
+ coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
+
/*
* perf will release trace ids when _free_aux()
* is called at the end of the session
@@ -612,7 +635,8 @@ static void etm_disable_sysfs(struct coresight_device *csdev)
* Executing etm_disable_hw on the cpu whose ETM is being disabled
* ensures that register writes occur when cpu is powered.
*/
- smp_call_function_single(drvdata->cpu, etm_disable_hw, drvdata, 1);
+ smp_call_function_single(drvdata->cpu, etm_disable_sysfs_smp_call,
+ drvdata, 1);
spin_unlock(&drvdata->spinlock);
cpus_read_unlock();
@@ -652,9 +676,6 @@ static void etm_disable(struct coresight_device *csdev,
WARN_ON_ONCE(mode);
return;
}
-
- if (mode)
- coresight_set_mode(csdev, CS_MODE_DISABLED);
}
static const struct coresight_ops_source etm_source_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 020f070bf17d..560975b70474 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -446,10 +446,24 @@ static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
etm4x_relaxed_write32(csa, TRCRSR_TA, TRCRSR);
etm4x_allow_trace(drvdata);
+
+ /*
+ * According to software usage PKLXF in Arm ARM (ARM DDI 0487 L.a),
+ * execute a Context synchronization event to guarantee the trace unit
+ * will observe the new values of the System registers.
+ */
+ if (!csa->io_mem)
+ isb();
+
/* Enable the trace unit */
etm4x_relaxed_write32(csa, 1, TRCPRGCTLR);
- /* Synchronize the register updates for sysreg access */
+ /*
+ * As recommended by section 4.3.7 ("Synchronization when using system
+ * instructions to progrom the trace unit") of ARM IHI 0064H.b, the
+ * self-hosted trace analyzer must perform a Context synchronization
+ * event between writing to the TRCPRGCTLR and reading the TRCSTATR.
+ */
if (!csa->io_mem)
isb();
@@ -461,10 +475,16 @@ static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata)
}
/*
- * As recommended by section 4.3.7 ("Synchronization when using the
- * memory-mapped interface") of ARM IHI 0064D
+ * As recommended in section 4.3.7 (Synchronization of register updates)
+ * of ARM IHI 0064H.b, the self-hosted trace analyzer always executes an
+ * ISB instruction after programming the trace unit registers.
+ *
+ * For the memory-mapped interface, the registers are mapped as Device
+ * type (Device-nGnRE). Reading back the value of any register in the
+ * trace unit ensures that all writes have completed. Therefore, polling
+ * on TRCSTATR guarantees that the writing TRCPRGCTLR is complete, and
+ * no explicit dsb() is required at here.
*/
- dsb(sy);
isb();
return 0;
@@ -589,13 +609,26 @@ done:
return rc;
}
-static void etm4_enable_hw_smp_call(void *info)
+static void etm4_enable_sysfs_smp_call(void *info)
{
struct etm4_enable_arg *arg = info;
+ struct coresight_device *csdev;
if (WARN_ON(!arg))
return;
+
+ csdev = arg->drvdata->csdev;
+ if (!coresight_take_mode(csdev, CS_MODE_SYSFS)) {
+ /* Someone is already using the tracer */
+ arg->rc = -EBUSY;
+ return;
+ }
+
arg->rc = etm4_enable_hw(arg->drvdata);
+
+ /* The tracer didn't start */
+ if (arg->rc)
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
}
/*
@@ -808,13 +841,14 @@ static int etm4_enable_perf(struct coresight_device *csdev,
struct perf_event *event,
struct coresight_path *path)
{
- int ret = 0;
struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ int ret;
- if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) {
- ret = -EINVAL;
- goto out;
- }
+ if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
+ return -EINVAL;
+
+ if (!coresight_take_mode(csdev, CS_MODE_PERF))
+ return -EBUSY;
/* Configure the tracer based on the session's specifics */
ret = etm4_parse_event_config(csdev, event);
@@ -830,6 +864,9 @@ static int etm4_enable_perf(struct coresight_device *csdev,
ret = etm4_enable_hw(drvdata);
out:
+ /* Failed to start tracer; roll back to DISABLED mode */
+ if (ret)
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
return ret;
}
@@ -861,7 +898,7 @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa
*/
arg.drvdata = drvdata;
ret = smp_call_function_single(drvdata->cpu,
- etm4_enable_hw_smp_call, &arg, 1);
+ etm4_enable_sysfs_smp_call, &arg, 1);
if (!ret)
ret = arg.rc;
if (!ret)
@@ -882,11 +919,6 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
{
int ret;
- if (!coresight_take_mode(csdev, mode)) {
- /* Someone is already using the tracer */
- return -EBUSY;
- }
-
switch (mode) {
case CS_MODE_SYSFS:
ret = etm4_enable_sysfs(csdev, path);
@@ -898,10 +930,6 @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event,
ret = -EINVAL;
}
- /* The tracer didn't start */
- if (ret)
- coresight_set_mode(csdev, CS_MODE_DISABLED);
-
return ret;
}
@@ -923,11 +951,16 @@ static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
*/
etm4x_prohibit_trace(drvdata);
/*
- * Make sure everything completes before disabling, as recommended
- * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register,
- * SSTATUS") of ARM IHI 0064D
+ * Prevent being speculative at the point of disabling the trace unit,
+ * as recommended by section 7.3.77 ("TRCVICTLR, ViewInst Main Control
+ * Register, SSTATUS") of ARM IHI 0064D
*/
dsb(sy);
+ /*
+ * According to software usage VKHHY in Arm ARM (ARM DDI 0487 L.a),
+ * execute a Context synchronization event to guarantee no new
+ * program-flow trace is generated.
+ */
isb();
/* Trace synchronization barrier, is a nop if not supported */
tsb_csync();
@@ -947,16 +980,22 @@ static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata)
dev_err(etm_dev,
"timeout while waiting for PM stable Trace Status\n");
/*
- * As recommended by section 4.3.7 (Synchronization of register updates)
- * of ARM IHI 0064H.b.
+ * As recommended in section 4.3.7 (Synchronization of register updates)
+ * of ARM IHI 0064H.b, the self-hosted trace analyzer always executes an
+ * ISB instruction after programming the trace unit registers.
+ *
+ * For the memory-mapped interface, the registers are mapped as Device
+ * type (Device-nGnRE). Reading back the value of any register in the
+ * trace unit ensures that all writes have completed. Therefore, polling
+ * on TRCSTATR guarantees that the writing TRCPRGCTLR is complete, and
+ * no explicit dsb() is required at here.
*/
isb();
}
-static void etm4_disable_hw(void *info)
+static void etm4_disable_hw(struct etmv4_drvdata *drvdata)
{
u32 control;
- struct etmv4_drvdata *drvdata = info;
struct etmv4_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
@@ -993,6 +1032,15 @@ static void etm4_disable_hw(void *info)
"cpu: %d disable smp call done\n", drvdata->cpu);
}
+static void etm4_disable_sysfs_smp_call(void *info)
+{
+ struct etmv4_drvdata *drvdata = info;
+
+ etm4_disable_hw(drvdata);
+
+ coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
+}
+
static int etm4_disable_perf(struct coresight_device *csdev,
struct perf_event *event)
{
@@ -1022,6 +1070,8 @@ static int etm4_disable_perf(struct coresight_device *csdev,
/* TRCVICTLR::SSSTATUS, bit[9] */
filters->ssstatus = (control & BIT(9));
+ coresight_set_mode(drvdata->csdev, CS_MODE_DISABLED);
+
/*
* perf will release trace ids when _free_aux() is
* called at the end of the session.
@@ -1047,7 +1097,8 @@ static void etm4_disable_sysfs(struct coresight_device *csdev)
* Executing etm4_disable_hw on the cpu whose ETM is being disabled
* ensures that register writes occur when cpu is powered.
*/
- smp_call_function_single(drvdata->cpu, etm4_disable_hw, drvdata, 1);
+ smp_call_function_single(drvdata->cpu, etm4_disable_sysfs_smp_call,
+ drvdata, 1);
raw_spin_unlock(&drvdata->spinlock);
@@ -1087,9 +1138,6 @@ static void etm4_disable(struct coresight_device *csdev,
etm4_disable_perf(csdev, event);
break;
}
-
- if (mode)
- coresight_set_mode(csdev, CS_MODE_DISABLED);
}
static int etm4_resume_perf(struct coresight_device *csdev)
@@ -1823,9 +1871,11 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
goto out;
}
+ if (!drvdata->paused)
+ etm4_disable_trace_unit(drvdata);
+
state = drvdata->save_state;
- state->trcprgctlr = etm4x_read32(csa, TRCPRGCTLR);
if (drvdata->nr_pe)
state->trcprocselr = etm4x_read32(csa, TRCPROCSELR);
state->trcconfigr = etm4x_read32(csa, TRCCONFIGR);
@@ -1908,7 +1958,7 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
state->trcpdcr = etm4x_read32(csa, TRCPDCR);
/* wait for TRCSTATR.IDLE to go up */
- if (etm4x_wait_status(csa, TRCSTATR_PMSTABLE_BIT, 1)) {
+ if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 1)) {
dev_err(etm_dev,
"timeout while waiting for Idle Trace Status\n");
etm4_os_unlock(drvdata);
@@ -1916,8 +1966,6 @@ static int __etm4_cpu_save(struct etmv4_drvdata *drvdata)
goto out;
}
- drvdata->state_needs_restore = true;
-
/*
* Power can be removed from the trace unit now. We do this to
* potentially save power on systems that respect the TRCPDCR_PU
@@ -1935,14 +1983,14 @@ static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
{
int ret = 0;
- /* Save the TRFCR irrespective of whether the ETM is ON */
- if (drvdata->trfcr)
- drvdata->save_trfcr = read_trfcr();
+ if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED)
+ return 0;
+
/*
* Save and restore the ETM Trace registers only if
* the ETM is active.
*/
- if (coresight_get_mode(drvdata->csdev) && drvdata->save_state)
+ if (coresight_get_mode(drvdata->csdev))
ret = __etm4_cpu_save(drvdata);
return ret;
}
@@ -1959,7 +2007,6 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
etm4_cs_unlock(drvdata, csa);
etm4x_relaxed_write32(csa, state->trcclaimset, TRCCLAIMSET);
- etm4x_relaxed_write32(csa, state->trcprgctlr, TRCPRGCTLR);
if (drvdata->nr_pe)
etm4x_relaxed_write32(csa, state->trcprocselr, TRCPROCSELR);
etm4x_relaxed_write32(csa, state->trcconfigr, TRCCONFIGR);
@@ -2033,8 +2080,6 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
if (!drvdata->skip_power_up)
etm4x_relaxed_write32(csa, state->trcpdcr, TRCPDCR);
- drvdata->state_needs_restore = false;
-
/*
* As recommended by section 4.3.7 ("Synchronization when using the
* memory-mapped interface") of ARM IHI 0064D
@@ -2044,14 +2089,19 @@ static void __etm4_cpu_restore(struct etmv4_drvdata *drvdata)
/* Unlock the OS lock to re-enable trace and external debug access */
etm4_os_unlock(drvdata);
+
+ if (!drvdata->paused)
+ etm4_enable_trace_unit(drvdata);
+
etm4_cs_lock(drvdata, csa);
}
static void etm4_cpu_restore(struct etmv4_drvdata *drvdata)
{
- if (drvdata->trfcr)
- write_trfcr(drvdata->save_trfcr);
- if (drvdata->state_needs_restore)
+ if (pm_save_enable != PARAM_PM_SAVE_SELF_HOSTED)
+ return;
+
+ if (coresight_get_mode(drvdata->csdev))
__etm4_cpu_restore(drvdata);
}
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 13ec9ecef46f..012c52fd1933 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -866,7 +866,6 @@ struct etmv4_config {
* struct etm4_save_state - state to be preserved when ETM is without power
*/
struct etmv4_save_state {
- u32 trcprgctlr;
u32 trcprocselr;
u32 trcconfigr;
u32 trcauxctlr;
@@ -980,9 +979,7 @@ struct etmv4_save_state {
* at runtime, due to the additional setting of TRFCR_CX when
* in EL2. Otherwise, 0.
* @config: structure holding configuration parameters.
- * @save_trfcr: Saved TRFCR_EL1 register during a CPU PM event.
* @save_state: State to be preserved across power loss
- * @state_needs_restore: True when there is context to restore after PM exit
* @skip_power_up: Indicates if an implementation can skip powering up
* the trace unit.
* @paused: Indicates if the trace unit is paused.
@@ -1037,9 +1034,7 @@ struct etmv4_drvdata {
bool lpoverride;
u64 trfcr;
struct etmv4_config config;
- u64 save_trfcr;
struct etmv4_save_state *save_state;
- bool state_needs_restore;
bool skip_power_up;
bool paused;
DECLARE_BITMAP(arch_features, ETM4_IMPDEF_FEATURE_MAX);
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 33e22b1ba043..fd896ac07942 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -135,8 +135,7 @@ static inline void CS_UNLOCK(void __iomem *addr)
}
void coresight_disable_path(struct coresight_path *path);
-int coresight_enable_path(struct coresight_path *path, enum cs_mode mode,
- void *sink_data);
+int coresight_enable_path(struct coresight_path *path, enum cs_mode mode);
struct coresight_device *coresight_get_sink(struct coresight_path *path);
struct coresight_device *coresight_get_sink_by_id(u32 id);
struct coresight_device *
diff --git a/drivers/hwtracing/coresight/coresight-sysfs.c b/drivers/hwtracing/coresight/coresight-sysfs.c
index 5e52324aa9ac..d2a6ed8bcc74 100644
--- a/drivers/hwtracing/coresight/coresight-sysfs.c
+++ b/drivers/hwtracing/coresight/coresight-sysfs.c
@@ -215,7 +215,7 @@ int coresight_enable_sysfs(struct coresight_device *csdev)
if (!IS_VALID_CS_TRACE_ID(path->trace_id))
goto err_path;
- ret = coresight_enable_path(path, CS_MODE_SYSFS, NULL);
+ ret = coresight_enable_path(path, CS_MODE_SYSFS);
if (ret)
goto err_path;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 0f45ab5e5249..8882b1c4cdc0 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -246,13 +246,14 @@ out:
return ret;
}
-static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
+static int tmc_enable_etf_sink_perf(struct coresight_device *csdev,
+ struct coresight_path *path)
{
int ret = 0;
pid_t pid;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- struct perf_output_handle *handle = data;
+ struct perf_output_handle *handle = path->handle;
struct cs_buffers *buf = etm_perf_sink_config(handle);
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -304,7 +305,8 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
}
static int tmc_enable_etf_sink(struct coresight_device *csdev,
- enum cs_mode mode, void *data)
+ enum cs_mode mode,
+ struct coresight_path *path)
{
int ret;
@@ -313,7 +315,7 @@ static int tmc_enable_etf_sink(struct coresight_device *csdev,
ret = tmc_enable_etf_sink_sysfs(csdev);
break;
case CS_MODE_PERF:
- ret = tmc_enable_etf_sink_perf(csdev, data);
+ ret = tmc_enable_etf_sink_perf(csdev, path);
break;
/* We shouldn't be here */
default:
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index b07fcdb3fe1a..e0d83ee01b77 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -1250,6 +1250,13 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
* with the lock released.
*/
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
+
+ /*
+ * If the ETR is already enabled, continue with the existing buffer.
+ */
+ if (coresight_get_mode(csdev) == CS_MODE_SYSFS)
+ goto out;
+
sysfs_buf = READ_ONCE(drvdata->sysfs_buf);
if (!sysfs_buf || (sysfs_buf->size != drvdata->size)) {
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -1325,9 +1332,10 @@ out:
}
struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
- enum cs_mode mode, void *data)
+ enum cs_mode mode,
+ struct coresight_path *path)
{
- struct perf_output_handle *handle = data;
+ struct perf_output_handle *handle = path->handle;
struct etr_perf_buffer *etr_perf;
switch (mode) {
@@ -1725,13 +1733,14 @@ out:
return size;
}
-static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
+static int tmc_enable_etr_sink_perf(struct coresight_device *csdev,
+ struct coresight_path *path)
{
int rc = 0;
pid_t pid;
unsigned long flags;
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
- struct perf_output_handle *handle = data;
+ struct perf_output_handle *handle = path->handle;
struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle);
raw_spin_lock_irqsave(&drvdata->spinlock, flags);
@@ -1779,13 +1788,14 @@ unlock_out:
}
static int tmc_enable_etr_sink(struct coresight_device *csdev,
- enum cs_mode mode, void *data)
+ enum cs_mode mode,
+ struct coresight_path *path)
{
switch (mode) {
case CS_MODE_SYSFS:
return tmc_enable_etr_sink_sysfs(csdev);
case CS_MODE_PERF:
- return tmc_enable_etr_sink_perf(csdev, data);
+ return tmc_enable_etr_sink_perf(csdev, path);
default:
return -EINVAL;
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index cbb4ba439158..95473d131032 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -442,7 +442,8 @@ struct coresight_device *tmc_etr_get_catu_device(struct tmc_drvdata *drvdata);
void tmc_etr_set_catu_ops(const struct etr_buf_operations *catu);
void tmc_etr_remove_catu_ops(void);
struct etr_buf *tmc_etr_get_buffer(struct coresight_device *csdev,
- enum cs_mode mode, void *data);
+ enum cs_mode mode,
+ struct coresight_path *path);
extern const struct attribute_group coresight_etr_group;
#endif
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index 333b3cb23685..3a3825d27f86 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.c
@@ -22,13 +22,6 @@
DEFINE_CORESIGHT_DEVLIST(tpda_devs, "tpda");
-static bool coresight_device_is_tpdm(struct coresight_device *csdev)
-{
- return (coresight_is_device_source(csdev)) &&
- (csdev->subtype.source_subtype ==
- CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
-}
-
static void tpda_clear_element_size(struct coresight_device *csdev)
{
struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 7214e65097ec..06e0a905a67d 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -470,6 +470,9 @@ static void tpdm_enable_cmb(struct tpdm_drvdata *drvdata)
*/
static void __tpdm_enable(struct tpdm_drvdata *drvdata)
{
+ if (coresight_is_static_tpdm(drvdata->csdev))
+ return;
+
CS_UNLOCK(drvdata->base);
tpdm_enable_dsb(drvdata);
@@ -532,6 +535,9 @@ static void tpdm_disable_cmb(struct tpdm_drvdata *drvdata)
/* TPDM disable operations */
static void __tpdm_disable(struct tpdm_drvdata *drvdata)
{
+ if (coresight_is_static_tpdm(drvdata->csdev))
+ return;
+
CS_UNLOCK(drvdata->base);
tpdm_disable_dsb(drvdata);
@@ -595,6 +601,30 @@ static int tpdm_datasets_setup(struct tpdm_drvdata *drvdata)
return 0;
}
+static int static_tpdm_datasets_setup(struct tpdm_drvdata *drvdata, struct device *dev)
+{
+ /* setup datasets for static TPDM */
+ if (fwnode_property_present(dev->fwnode, "qcom,dsb-element-bits") &&
+ (!drvdata->dsb)) {
+ drvdata->dsb = devm_kzalloc(drvdata->dev,
+ sizeof(*drvdata->dsb), GFP_KERNEL);
+
+ if (!drvdata->dsb)
+ return -ENOMEM;
+ }
+
+ if (fwnode_property_present(dev->fwnode, "qcom,cmb-element-bits") &&
+ (!drvdata->cmb)) {
+ drvdata->cmb = devm_kzalloc(drvdata->dev,
+ sizeof(*drvdata->cmb), GFP_KERNEL);
+
+ if (!drvdata->cmb)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static ssize_t reset_dataset_store(struct device *dev,
struct device_attribute *attr,
const char *buf,
@@ -1342,10 +1372,9 @@ static const struct attribute_group *tpdm_attr_grps[] = {
NULL,
};
-static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
+static int tpdm_probe(struct device *dev, struct resource *res)
{
void __iomem *base;
- struct device *dev = &adev->dev;
struct coresight_platform_data *pdata;
struct tpdm_drvdata *drvdata;
struct coresight_desc desc = { 0 };
@@ -1354,32 +1383,37 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
pdata = coresight_get_platform_data(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
- adev->dev.platform_data = pdata;
+ dev->platform_data = pdata;
/* driver data*/
drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
- drvdata->dev = &adev->dev;
+ drvdata->dev = dev;
dev_set_drvdata(dev, drvdata);
- base = devm_ioremap_resource(dev, &adev->res);
- if (IS_ERR(base))
- return PTR_ERR(base);
+ if (res) {
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- drvdata->base = base;
+ drvdata->base = base;
+ ret = tpdm_datasets_setup(drvdata);
+ if (ret)
+ return ret;
- ret = tpdm_datasets_setup(drvdata);
- if (ret)
- return ret;
-
- if (drvdata && tpdm_has_dsb_dataset(drvdata))
- of_property_read_u32(drvdata->dev->of_node,
- "qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
+ if (tpdm_has_dsb_dataset(drvdata))
+ of_property_read_u32(drvdata->dev->of_node,
+ "qcom,dsb-msrs-num", &drvdata->dsb_msr_num);
- if (drvdata && tpdm_has_cmb_dataset(drvdata))
- of_property_read_u32(drvdata->dev->of_node,
- "qcom,cmb-msrs-num", &drvdata->cmb_msr_num);
+ if (tpdm_has_cmb_dataset(drvdata))
+ of_property_read_u32(drvdata->dev->of_node,
+ "qcom,cmb-msrs-num", &drvdata->cmb_msr_num);
+ } else {
+ ret = static_tpdm_datasets_setup(drvdata, dev);
+ if (ret)
+ return ret;
+ }
/* Set up coresight component description */
desc.name = coresight_alloc_device_name(&tpdm_devs, dev);
@@ -1388,34 +1422,51 @@ static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
desc.type = CORESIGHT_DEV_TYPE_SOURCE;
desc.subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM;
desc.ops = &tpdm_cs_ops;
- desc.pdata = adev->dev.platform_data;
- desc.dev = &adev->dev;
+ desc.pdata = dev->platform_data;
+ desc.dev = dev;
desc.access = CSDEV_ACCESS_IOMEM(base);
- desc.groups = tpdm_attr_grps;
+ if (res)
+ desc.groups = tpdm_attr_grps;
drvdata->csdev = coresight_register(&desc);
if (IS_ERR(drvdata->csdev))
return PTR_ERR(drvdata->csdev);
spin_lock_init(&drvdata->spinlock);
- /* Decrease pm refcount when probe is done.*/
- pm_runtime_put(&adev->dev);
-
return 0;
}
-static void tpdm_remove(struct amba_device *adev)
+static int tpdm_remove(struct device *dev)
{
- struct tpdm_drvdata *drvdata = dev_get_drvdata(&adev->dev);
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(dev);
coresight_unregister(drvdata->csdev);
+
+ return 0;
+}
+
+static int dynamic_tpdm_probe(struct amba_device *adev,
+ const struct amba_id *id)
+{
+ int ret;
+
+ ret = tpdm_probe(&adev->dev, &adev->res);
+ if (!ret)
+ pm_runtime_put(&adev->dev);
+
+ return ret;
+}
+
+static void dynamic_tpdm_remove(struct amba_device *adev)
+{
+ tpdm_remove(&adev->dev);
}
/*
* Different TPDM has different periph id.
* The difference is 0-7 bits' value. So ignore 0-7 bits.
*/
-static const struct amba_id tpdm_ids[] = {
+static const struct amba_id dynamic_tpdm_ids[] = {
{
.id = 0x001f0e00,
.mask = 0x00ffff00,
@@ -1423,17 +1474,76 @@ static const struct amba_id tpdm_ids[] = {
{ 0, 0, NULL },
};
-static struct amba_driver tpdm_driver = {
+MODULE_DEVICE_TABLE(amba, dynamic_tpdm_ids);
+
+static struct amba_driver dynamic_tpdm_driver = {
.drv = {
.name = "coresight-tpdm",
.suppress_bind_attrs = true,
},
- .probe = tpdm_probe,
- .id_table = tpdm_ids,
- .remove = tpdm_remove,
+ .probe = dynamic_tpdm_probe,
+ .id_table = dynamic_tpdm_ids,
+ .remove = dynamic_tpdm_remove,
};
-module_amba_driver(tpdm_driver);
+static int tpdm_platform_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int ret;
+
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ ret = tpdm_probe(&pdev->dev, res);
+ pm_runtime_put(&pdev->dev);
+ if (ret)
+ pm_runtime_disable(&pdev->dev);
+
+ return ret;
+}
+
+static void tpdm_platform_remove(struct platform_device *pdev)
+{
+ struct tpdm_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
+
+ if (WARN_ON(!drvdata))
+ return;
+
+ tpdm_remove(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+}
+
+static const struct of_device_id static_tpdm_match[] = {
+ {.compatible = "qcom,coresight-static-tpdm"},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, static_tpdm_match);
+
+static struct platform_driver static_tpdm_driver = {
+ .probe = tpdm_platform_probe,
+ .remove = tpdm_platform_remove,
+ .driver = {
+ .name = "coresight-static-tpdm",
+ .of_match_table = static_tpdm_match,
+ .suppress_bind_attrs = true,
+ },
+};
+
+static int __init tpdm_init(void)
+{
+ return coresight_init_driver("tpdm", &dynamic_tpdm_driver, &static_tpdm_driver,
+ THIS_MODULE);
+}
+
+static void __exit tpdm_exit(void)
+{
+ coresight_remove_driver(&dynamic_tpdm_driver, &static_tpdm_driver);
+}
+
+module_init(tpdm_init);
+module_exit(tpdm_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.h b/drivers/hwtracing/coresight/coresight-tpdm.h
index b11754389734..2867f3ab8186 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.h
+++ b/drivers/hwtracing/coresight/coresight-tpdm.h
@@ -343,4 +343,16 @@ struct tpdm_dataset_attribute {
enum dataset_mem mem;
u32 idx;
};
+
+static inline bool coresight_device_is_tpdm(struct coresight_device *csdev)
+{
+ return (coresight_is_device_source(csdev)) &&
+ (csdev->subtype.source_subtype ==
+ CORESIGHT_DEV_SUBTYPE_SOURCE_TPDM);
+}
+
+static inline bool coresight_is_static_tpdm(struct coresight_device *csdev)
+{
+ return (coresight_device_is_tpdm(csdev) && !csdev->access.base);
+}
#endif /* _CORESIGHT_CORESIGHT_TPDM_H */
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 9463afdbda8a..aaa44bc521c3 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -75,7 +75,7 @@ static void tpiu_enable_hw(struct csdev_access *csa)
}
static int tpiu_enable(struct coresight_device *csdev, enum cs_mode mode,
- void *__unused)
+ struct coresight_path *path)
{
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index 9f64f463339d..474861903f6c 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -1013,11 +1013,11 @@ err:
}
static int arm_trbe_enable(struct coresight_device *csdev, enum cs_mode mode,
- void *data)
+ struct coresight_path *path)
{
struct trbe_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct trbe_cpudata *cpudata = dev_get_drvdata(&csdev->dev);
- struct perf_output_handle *handle = data;
+ struct perf_output_handle *handle = path->handle;
struct trbe_buf *buf = etm_perf_sink_config(handle);
WARN_ON(cpudata->cpu != smp_processor_id());
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index 26cfc939e5bd..8f7922a5e534 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -213,10 +213,11 @@ static void smb_enable_sysfs(struct coresight_device *csdev)
coresight_set_mode(csdev, CS_MODE_SYSFS);
}
-static int smb_enable_perf(struct coresight_device *csdev, void *data)
+static int smb_enable_perf(struct coresight_device *csdev,
+ struct coresight_path *path)
{
struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
- struct perf_output_handle *handle = data;
+ struct perf_output_handle *handle = path->handle;
struct cs_buffers *buf = etm_perf_sink_config(handle);
pid_t pid;
@@ -240,7 +241,7 @@ static int smb_enable_perf(struct coresight_device *csdev, void *data)
}
static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
- void *data)
+ struct coresight_path *path)
{
struct smb_drv_data *drvdata = dev_get_drvdata(csdev->dev.parent);
int ret = 0;
@@ -261,7 +262,7 @@ static int smb_enable(struct coresight_device *csdev, enum cs_mode mode,
smb_enable_sysfs(csdev);
break;
case CS_MODE_PERF:
- ret = smb_enable_perf(csdev, data);
+ ret = smb_enable_perf(csdev, path);
break;
default:
ret = -EINVAL;
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 47d9e6c3bac0..591b7c12aae5 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -166,7 +166,7 @@ static void intel_th_remove(struct device *dev)
pm_runtime_enable(dev);
}
-static struct bus_type intel_th_bus = {
+static const struct bus_type intel_th_bus = {
.name = "intel_th",
.match = intel_th_match,
.probe = intel_th_probe,
@@ -810,13 +810,17 @@ static int intel_th_output_open(struct inode *inode, struct file *file)
int err;
dev = bus_find_device_by_devt(&intel_th_bus, inode->i_rdev);
- if (!dev || !dev->driver)
- return -ENODEV;
+ if (!dev || !dev->driver) {
+ err = -ENODEV;
+ goto out_no_device;
+ }
thdrv = to_intel_th_driver(dev->driver);
fops = fops_get(thdrv->fops);
- if (!fops)
- return -ENODEV;
+ if (!fops) {
+ err = -ENODEV;
+ goto out_put_device;
+ }
replace_fops(file, fops);
@@ -824,10 +828,16 @@ static int intel_th_output_open(struct inode *inode, struct file *file)
if (file->f_op->open) {
err = file->f_op->open(inode, file);
- return err;
+ if (err)
+ goto out_put_device;
}
return 0;
+
+out_put_device:
+ put_device(dev);
+out_no_device:
+ return err;
}
static const struct file_operations intel_th_output_fops = {