Change since V7:
1. Update the conflict when apply to coresight next.
2. Update the Date and version in ABI file.
V7 link: https://patchwork.kernel.org/project/linux-arm-kernel/patch/20250226121926.…
Change since V6:
1. Update the date and verison in ABI file.
Change since V5:
1. Update the kernel version of ABI files.
2. Add link of different patch versions.
V5 link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20241210122253.319…
Change since V4:
1. Add label in DT and add label sysfs node for each coresight device.
V4 link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20240703122340.268…
Change since V3:
1. Change device-name to arm,cs-dev-name.
2. Add arm,cs-dev-name to only CTI and sources' dt-binding.
V3 link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20240131082628.628…
Change since V2:
1. Fix the error in coresight core.
drivers/hwtracing/coresight/coresight-core.c:1775:7: error: assigning to 'char *' from 'const char *' discards qualifiers
2. Fix the warning when run dtbinding check.
Documentation/devicetree/bindings/arm/arm,coresight-cpu-debug.yaml: device-name: missing type definition
V2 link: https://patchwork.kernel.org/project/linux-arm-msm/cover/20240115164252.265…
Change since V1:
1. Change coresight-name to device name.
2. Add the device-name in coresight dt bindings.
V1 link: https://patchwork.kernel.org/project/linux-arm-kernel/patch/20230208110716.…
Mao Jinlong (2):
dt-bindings: arm: Add label in the coresight components
coresight: Add label sysfs node support
.../testing/sysfs-bus-coresight-devices-cti | 6 ++++
.../sysfs-bus-coresight-devices-funnel | 6 ++++
.../testing/sysfs-bus-coresight-devices-tpdm | 6 ++++
.../bindings/arm/arm,coresight-cti.yaml | 6 ++++
.../arm/arm,coresight-dummy-sink.yaml | 6 ++++
.../arm/arm,coresight-dummy-source.yaml | 6 ++++
.../arm/arm,coresight-dynamic-funnel.yaml | 6 ++++
.../arm/arm,coresight-dynamic-replicator.yaml | 6 ++++
.../arm/arm,coresight-static-funnel.yaml | 6 ++++
.../arm/arm,coresight-static-replicator.yaml | 6 ++++
.../bindings/arm/arm,coresight-tmc.yaml | 6 ++++
.../bindings/arm/qcom,coresight-tpda.yaml | 6 ++++
.../bindings/arm/qcom,coresight-tpdm.yaml | 6 ++++
drivers/hwtracing/coresight/coresight-sysfs.c | 32 +++++++++++++++++++
14 files changed, 110 insertions(+)
--
2.17.1
This patchset builds upon Yicong's previous patches [1].
Introducing fix two race issues found by using TMC-ETR and CATU, Two
cleanups found when debugging the issues.
[1] https://lore.kernel.org/linux-arm-kernel/20241202092419.11777-1-yangyicong@…
---
Changes in v2:
- Updated the commit of patch2.
- Rebase to v6.16-rc1
Junhao He (1):
coresight: tmc: refactor the tmc-etr mode setting to avoid race
conditions
Yicong Yang (2):
coresight: tmc: Add missing doc of tmc_drvdata::reading
coresight: tmc: Decouple the perf buffer allocation from sysfs mode
.../hwtracing/coresight/coresight-tmc-etr.c | 102 +++++++++---------
drivers/hwtracing/coresight/coresight-tmc.h | 1 +
2 files changed, 53 insertions(+), 50 deletions(-)
--
2.33.0
On Wed, Jul 02, 2025 at 12:05:10PM +0100, Yeoreum Yun wrote:
[...]
> > @@ -445,13 +445,37 @@ 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();
> > +
>
> But, when write to SYS_TRFCR_EL1 in etm4x_allow_trace(), it already does
> isb(). Is it redundant?
Good point. It is not sufficient. As a system register writing in
kvm_tracing_set_el1_configuration(), this is why adds a ISB here.
Thanks,
Leo
Hi Levi,
On Wed, Jul 02, 2025 at 12:10:17PM +0100, Yeoreum Yun wrote:
[...]
> > @@ -579,6 +572,13 @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata)
> >
> > if (!drvdata->paused)
> > rc = etm4_enable_trace_unit(drvdata);
> > +
> > + /*
> > + * As recommended by 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.
> > + */
> > + isb();
>
> But according to 4.3.7 ("Synchronization when using memory-mapped
> interface"), doesn't it need to dsb like:
>
> if (csa->iomem)
> dsb(sy);
> isb();
>
> Or am I missing something?
Section 4.3.7 suggests using a DSB barrier to ensure that writes have
completed in MMIO mode. It also mentions an alternative:
"If the memory is marked as Device-nGnRE or stronger, read back the
value of any register in the trace unit. This relies on the peripheral
coherence order defined in the Arm architecture."
In the etm4_{enable|disable}_trace_unit() functions, each time the
TRCPRGCTLR register is written, the driver polls bits in TRCSTATR.
This acts as synchronization using read-after-write (RAW), which is
exactly the approach suggested above.
This is why we don't need DSB() anymore.
Thanks,
Leo
Hi Levi,
On Wed, Jul 02, 2025 at 10:49:01AM +0100, Yeoreum Yun wrote:
> Hi Leo,
>
> > {
> > - return local_cmpxchg(&csdev->mode, CS_MODE_DISABLED, new_mode) ==
> > - CS_MODE_DISABLED;
> > + int curr = CS_MODE_DISABLED;
> > +
> > + return atomic_try_cmpxchg_acquire(&csdev->mode, &curr, new_mode);
> > }
>
> Just question. why is acquire symentic enough in here?
My understanding is that acquire semantics ensure ordering between
cmpxchg_acquire() and all memory accesses that follow it. However, it
does not guarantee that memory accesses appearing before the acquire
are ordered as well.
This is exactly what we want in the driver. We must ensure to first grab
an active device mode, then it is safe to proceed later operations (e.g.
set configurations in driver data and access registers).
> before this change, local_cmpxchg seems to use full_fenced.
Not really. Arm64 has atomic instruction for cmpxchg, it does not use
full_fenced. It should run into the path of arch_cmpxchg().
Thanks,
Leo
This series addresses CPU power management issues in the CoreSight
drivers. For easier review, the patches are organized into two
categories:
o Patches 01 ~ 10 focus on CPU power management within the ETM drivers.
These patches fix SMP-safe access to the mode, correct context
synchronization, and refactor the CPU suspend/resume flows.
o Patches 11 ~ 28 extend CPU power management to cover activated paths,
including helpers, links, and sinks. These changes move CPU PM and
hotplug notifiers from the ETMv4 driver into the CoreSight core layer.
Summary of Changes:
- Patches 01 ~ 03: Fix device mode access in the SMP mode.
- Patch 04 : A minor fix for polling bit.
- Patches 05 ~ 07: Improve the context synchronization based on the ETM
specification (IHI0064H.b) and Arm ARM (ARM DDI 0487
L.a).
- Patches 08 ~ 10: Refactor the context save/restore flow in the ETMv4
driver, in the end, the CPU PM callbacks reuse the
normal enabling and disabling flows.
- Patches 11 ~ 17: Move CPU PM code from ETMv4 driver to the core layer.
- Patches 18 ~ 25: Enhance device mode handling in the CTI driver,
distinguishes debug mode from trace modes (Perf or
SysFS mode). Extend support activated paths during
CPU idle. Support save and restore context for
per-CPU sink (TRBE).
- Patches 26 ~ 28: Move CPU hotplug notifier from the ETMv4 driver to
the core layer. The full path is now managed in CPU
hotplug.
Verification:
This series has been verified on the following platforms:
- Hikey960, Juno-r0 and Juno-r2:
Note that the firmware on Hikey960 and Juno-r0 is unstable. While no
CoreSight failures were observed, but the CPU hotplug or CPU idle
itself may fail intermittently.
Juno-r2 is much stable and can pass 24+ hours stress test.
- FVP RevC: Verified TRBE changes.
Stress test script:
#!/usr/bin/bash
echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink
while true; do
echo 0 > /sys/devices/system/cpu/cpu2/online;
echo 1 > /sys/devices/system/cpu/cpu2/online;
done &
while true; do
echo 1 > /sys/bus/coresight/devices/etm2/enable_source;
echo 0 > /sys/bus/coresight/devices/etm2/enable_source;
done &
---
Changes in v2:
- Refactored ETMv4 suspend and resume for reusing the normal enabling
and disabling flows (James).
- Used a per-CPU structure to maintain path pointers (James).
- Supported helpers in CPU PM flows (James).
- Fixed the SMP-safe access to device mode.
- Fixed the context synchronization in ETMv4x driver.
- Link to v1: https://lore.kernel.org/linux-arm-kernel/20250516160742.1200904-1-leo.yan@a…
Signed-off-by: Leo Yan <leo.yan(a)arm.com>
---
Leo Yan (27):
coresight: Change device mode to atomic type
coresight: etm4x: Always set tracer's device mode on target CPU
coresight: etm3x: Always set tracer's device mode on target CPU
coresight: etm4x: Correct polling IDLE bit
coresight: etm4x: Ensure context synchronization is not ignored
coresight: etm4x: Add context synchronization before enabling trace
coresight: etm4x: Properly control filter in CPU idle with FEAT_TRF
coresight: etm4x: Remove the state_needs_restore flag
coresight: etm4x: Add flag to control single-shot restart
coresight: etm4x: Reuse normal enable and disable logic in CPU idle
coresight: Populate CPU ID into the coresight_device structure
coresight: sysfs: Validate CPU online status for per-CPU sources
coresight: Set per CPU source pointer
coresight: Register CPU PM notifier in core layer
coresight: etm4x: Hook CPU PM callbacks
coresight: Add callback to determine if context save/restore is needed
coresight: etm4x: Remove redundant condition checks in save and restore
coresight: cti: Fix race condition by using device mode
coresight: cti: Introduce CS_MODE_DEBUG mode
coresight: cti: Properly handle modes in CPU PM notifiers
coresight: Add per-CPU path pointer
coresight: Add 'in_idle' argument to path enable/disable functions
coresight: Control path during CPU idle
coresight: Add PM callbacks for percpu sink
coresight: Take hotplug lock in enable_source_store() for Sysfs mode
coresight: Move CPU hotplug callbacks to core layer
coresight: Manage activated path during CPU hotplug
Yabin Cui (1):
coresight: trbe: Save and restore state across CPU low power state
drivers/hwtracing/coresight/coresight-catu.c | 1 +
drivers/hwtracing/coresight/coresight-core.c | 337 ++++++++++++--
drivers/hwtracing/coresight/coresight-ctcu-core.c | 1 +
drivers/hwtracing/coresight/coresight-cti-core.c | 40 +-
drivers/hwtracing/coresight/coresight-cti-sysfs.c | 2 +-
drivers/hwtracing/coresight/coresight-dummy.c | 1 +
drivers/hwtracing/coresight/coresight-etb10.c | 1 +
drivers/hwtracing/coresight/coresight-etm3x-core.c | 61 ++-
drivers/hwtracing/coresight/coresight-etm4x-core.c | 488 ++++++---------------
drivers/hwtracing/coresight/coresight-etm4x.h | 62 ---
drivers/hwtracing/coresight/coresight-funnel.c | 1 +
drivers/hwtracing/coresight/coresight-replicator.c | 1 +
drivers/hwtracing/coresight/coresight-stm.c | 1 +
drivers/hwtracing/coresight/coresight-sysfs.c | 10 +
drivers/hwtracing/coresight/coresight-tmc-core.c | 1 +
drivers/hwtracing/coresight/coresight-tpda.c | 1 +
drivers/hwtracing/coresight/coresight-tpdm.c | 1 +
drivers/hwtracing/coresight/coresight-tpiu.c | 1 +
drivers/hwtracing/coresight/coresight-trbe.c | 85 ++++
drivers/hwtracing/coresight/ultrasoc-smb.c | 1 +
include/linux/coresight.h | 55 ++-
21 files changed, 665 insertions(+), 487 deletions(-)
---
base-commit: 66701750d5565c574af42bef0b789ce0203e3071
change-id: 20250611-arm_cs_pm_fix_v3-f4ae29bb7d81
Best regards,
--
Leo Yan <leo.yan(a)arm.com>
On 2025/6/20 19:53, Jonathan Cameron wrote:
> On Fri, 20 Jun 2025 15:54:10 +0800
> Junhao He <hejunhao3(a)huawei.com> wrote:
>
>> From: Yicong Yang <yangyicong(a)hisilicon.com>
>>
>> tmc_drvdata::reading is used to indicate whether a reading process
>> is performed through /dev/xyz.tmc. Document it.
>>
>> Reviewed-by: James Clark <james.clark(a)linaro.org>
>> Signed-off-by: Yicong Yang <yangyicong(a)hisilicon.com>
>> Signed-off-by: Junhao He <hejunhao3(a)huawei.com>
>> ---
>> drivers/hwtracing/coresight/coresight-tmc.h | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
>> index 6541a27a018e..3ca0d40c580d 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc.h
>> +++ b/drivers/hwtracing/coresight/coresight-tmc.h
>> @@ -220,6 +220,7 @@ struct tmc_resrv_buf {
>> * @pid: Process ID of the process that owns the session that is using
>> * this component. For example this would be the pid of the Perf
>> * process.
>> + * @reading: buffer's in the reading through "/dev/xyz.tmc" entry
> Hi,
>
> Perhaps reword:
>
> "buffer is being read through "/dev/xyz.tmc" entry" or
> "buffer read in progress through "/dev/xyz.tmc" entry"
>
> I've not checked what this actually means - just looking at what you have here.
Will update this. Thanks
Best regards,
Junhao.
>> * @stop_on_flush: Stop on flush trigger user configuration.
>> * @buf: Snapshot of the trace data for ETF/ETB.
>> * @etr_buf: details of buffer used in TMC-ETR
> .
>
On 2025/6/20 20:45, Jonathan Cameron wrote:
> On Fri, 20 Jun 2025 15:54:11 +0800
> Junhao He <hejunhao3(a)huawei.com> wrote:
>
>> When trying to run perf and sysfs mode simultaneously, the WARN_ON()
>> in tmc_etr_enable_hw() is triggered sometimes:
>>
>> WARNING: CPU: 42 PID: 3911571 at drivers/hwtracing/coresight/coresight-tmc-etr.c:1060 tmc_etr_enable_hw+0xc0/0xd8 [coresight_tmc]
>> [..snip..]
>> Call trace:
>> tmc_etr_enable_hw+0xc0/0xd8 [coresight_tmc] (P)
>> tmc_enable_etr_sink+0x11c/0x250 [coresight_tmc] (L)
>> tmc_enable_etr_sink+0x11c/0x250 [coresight_tmc]
>> coresight_enable_path+0x1c8/0x218 [coresight]
>> coresight_enable_sysfs+0xa4/0x228 [coresight]
>> enable_source_store+0x58/0xa8 [coresight]
>> dev_attr_store+0x20/0x40
>> sysfs_kf_write+0x4c/0x68
>> kernfs_fop_write_iter+0x120/0x1b8
>> vfs_write+0x2c8/0x388
>> ksys_write+0x74/0x108
>> __arm64_sys_write+0x24/0x38
>> el0_svc_common.constprop.0+0x64/0x148
>> do_el0_svc+0x24/0x38
>> el0_svc+0x3c/0x130
>> el0t_64_sync_handler+0xc8/0xd0
>> el0t_64_sync+0x1ac/0x1b0
>> ---[ end trace 0000000000000000 ]---
>>
>> Since the sysfs buffer allocation and the hardware enablement is not
>> in the same critical region, it's possible to race with the perf
>>
>> mode:
>> [sysfs mode] [perf mode]
>> tmc_etr_get_sysfs_buffer()
>> spin_lock(&drvdata->spinlock)
>> [sysfs buffer allocation]
>> spin_unlock(&drvdata->spinlock)
>> spin_lock(&drvdata->spinlock)
>> tmc_etr_enable_hw()
>> drvdata->etr_buf = etr_perf->etr_buf
>> spin_unlock(&drvdata->spinlock)
>> spin_lock(&drvdata->spinlock)
>> tmc_etr_enable_hw()
>> WARN_ON(drvdata->etr_buf) // WARN sicne etr_buf initialized at
>> the perf side
>> spin_unlock(&drvdata->spinlock)
>>
>> A race condition is introduced here, perf always prioritizes execution, and
>> warnings can lead to concerns about potential hidden bugs, such as getting
>> out of sync.
>>
>> To fix this, configure the tmc-etr mode before invoking enable_etr_perf()
>> or enable_etr_sysfs(), explicitly check if the tmc-etr sink is already
>> enabled in a different mode, and simplily the setup and checks for "mode".
>> To prevent race conditions between mode transitions.
>>
>> Fixes: 296b01fd106e ("coresight: Refactor out buffer allocation function for ETR")
>> Reported-by: Yicong Yang <yangyicong(a)hisilicon.com>
>> Closes: https://lore.kernel.org/linux-arm-kernel/20241202092419.11777-2-yangyicong@…
>> Signed-off-by: Junhao He <hejunhao3(a)huawei.com>
>> ---
>> .../hwtracing/coresight/coresight-tmc-etr.c | 73 +++++++++++--------
>> 1 file changed, 43 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index b07fcdb3fe1a..252a57a8e94e 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -1263,11 +1263,6 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
>> raw_spin_lock_irqsave(&drvdata->spinlock, flags);
>> }
>>
>> - if (drvdata->reading || coresight_get_mode(csdev) == CS_MODE_PERF) {
>> - ret = -EBUSY;
>> - goto out;
>> - }
>> -
>> /*
>> * If we don't have a buffer or it doesn't match the requested size,
>> * use the buffer allocated above. Otherwise reuse the existing buffer.
>> @@ -1278,7 +1273,6 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
>> drvdata->sysfs_buf = new_buf;
>> }
>>
>> -out:
>> raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
>>
>> /* Free memory outside the spinlock if need be */
>> @@ -1289,7 +1283,7 @@ static struct etr_buf *tmc_etr_get_sysfs_buffer(struct coresight_device *csdev)
>>
>> static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
>> {
>> - int ret = 0;
>> + int ret;
>> unsigned long flags;
>> struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> struct etr_buf *sysfs_buf = tmc_etr_get_sysfs_buffer(csdev);
>> @@ -1299,23 +1293,10 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
>>
>> raw_spin_lock_irqsave(&drvdata->spinlock, flags);
>>
>> - /*
>> - * In sysFS mode we can have multiple writers per sink. Since this
>> - * sink is already enabled no memory is needed and the HW need not be
>> - * touched, even if the buffer size has changed.
>> - */
>> - if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
>> - csdev->refcnt++;
>> - goto out;
>> - }
>> -
>> ret = tmc_etr_enable_hw(drvdata, sysfs_buf);
>> - if (!ret) {
>> - coresight_set_mode(csdev, CS_MODE_SYSFS);
>> + if (!ret)
>> csdev->refcnt++;
>> - }
>>
>> -out:
>> raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
>>
>> if (!ret)
>> @@ -1735,11 +1716,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
>> struct etr_perf_buffer *etr_perf = etm_perf_sink_config(handle);
>>
>> raw_spin_lock_irqsave(&drvdata->spinlock, flags);
>> - /* Don't use this sink if it is already claimed by sysFS */
>> - if (coresight_get_mode(csdev) == CS_MODE_SYSFS) {
>> - rc = -EBUSY;
>> - goto unlock_out;
>> - }
>>
>> if (WARN_ON(!etr_perf || !etr_perf->etr_buf)) {
>> rc = -EINVAL;
>> @@ -1768,7 +1744,6 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
>> if (!rc) {
>> /* Associate with monitored process. */
>> drvdata->pid = pid;
>> - coresight_set_mode(csdev, CS_MODE_PERF);
>> drvdata->perf_buf = etr_perf->etr_buf;
>> csdev->refcnt++;
>> }
>> @@ -1781,14 +1756,52 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
>> static int tmc_enable_etr_sink(struct coresight_device *csdev,
>> enum cs_mode mode, void *data)
>> {
>> + struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> + enum cs_mode old_mode;
>> + int rc = -EINVAL;
>> +
>> + scoped_guard(spinlock_irqsave, &drvdata->spinlock) {
>> + old_mode = coresight_get_mode(csdev);
>> + if (old_mode != CS_MODE_DISABLED && old_mode != mode)
>> + return -EBUSY;
>> +
>> + if (drvdata->reading)
>> + return -EBUSY;
>> +
>> + /* In sysFS mode we can have multiple writers per sink. */
>> + if (old_mode == CS_MODE_SYSFS) {
> This seems odd. You are incrementing the reference count when potentially changing
> away from CS_MODE_SYSFS?
> Is this meant to only occur if old_mode == mode && old_mode == CS_MODE_SYSFS?
Yes, old_mode == CS_MODE_SYSFS means tmc_etr is occupied by sysfs, and
old_mode == mode, so can add reference counting directly.
When tmc_etr is idle its mode is CS_MODE_DISABLED.
> In the code prior to this patch this bit only ran in tmc_enable_etr_sink_sysfs()
> which was only called based on the mode being configured (mode here I think) being
> sysfs. That no longer looks to be the case.
before the patch, first check (mode == CS_MODE_SYSFS), then check
(coresight_get_mode(csdev) == CS_MODE_SYSFS),
and finally csdev->refcnt++. This is the same as the current functionality.
> Maybe I'm missing something as the flows around this are complex.
>
>
>> + csdev->refcnt++;
>> + return 0;
>> + }
>> +
>> + /*
>> + * minor note: In sysFS mode, the task1 get locked first, it setup
>> + * etr mode to SYSFS. Then task2 get locked,it will directly return
>> + * success even when the tmc-etr is not enabled at this moment.
>> + * Ultimately, task1 will still successfully enable tmc-etr.
>> + * This is a transient state and does not cause an anomaly.
>> + */
>> + coresight_set_mode(csdev, mode);
>> + }
>> +
>> switch (mode) {
>> case CS_MODE_SYSFS:
>> - return tmc_enable_etr_sink_sysfs(csdev);
>> + rc = tmc_enable_etr_sink_sysfs(csdev);
>> + break;
>> case CS_MODE_PERF:
>> - return tmc_enable_etr_sink_perf(csdev, data);
>> + rc = tmc_enable_etr_sink_perf(csdev, data);
>> + break;
>> default:
>> - return -EINVAL;
>> + rc = -EINVAL;
>> }
>> +
>> + if (rc && old_mode != mode) {
>> + scoped_guard(spinlock_irqsave, &drvdata->spinlock) {
> Might be a local style matching thing but if not the scope is tight anyway
> so could use the unscoped version.
>
> guard(spinlock_irqsave)(&drvdata->spinlock);
> coresight_set_mode(csdev, old_mode);
Sure, Will fix in next version.
>> + coresight_set_mode(csdev, old_mode);
>> + }
>> + }
>> +
>> + return rc;
>> }
>>
>> static int tmc_disable_etr_sink(struct coresight_device *csdev)
> .
>