[PATCH v2 18/28] coresight: cti: Fix race condition by using device mode

From: Leo Yan
Date: Tue Jul 01 2025 - 10:58:15 EST


A CTI device can be enabled as a helper in a CoreSight path or directly
via the SysFS knob. Currently, the driver lacks protection when multiple
flows contend for access to the same CTI device.

Use the device mode to mark the CTI as in use, and reset it to the
DISABLED state when the device is no longer needed. Any conflict will
cause the attempt to acquire the mode to fail, ensuring the device can
only be enabled exclusively.

Fixes: 1b5b1646e63d ("coresight: Fix CTI module refcount leak by making it a helper device")
Signed-off-by: Leo Yan <leo.yan@xxxxxxx>
---
drivers/hwtracing/coresight/coresight-cti-core.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-cti-core.c b/drivers/hwtracing/coresight/coresight-cti-core.c
index 2c8bf5dbe8b8206c92ae5ea64a26c947ef5b9582..ba4635dfc2e30b4e9ae4972f91bdc6647975b719 100644
--- a/drivers/hwtracing/coresight/coresight-cti-core.c
+++ b/drivers/hwtracing/coresight/coresight-cti-core.c
@@ -87,20 +87,31 @@ void cti_write_all_hw_regs(struct cti_drvdata *drvdata)
}

/* write regs to hardware and enable */
-static int cti_enable_hw(struct cti_drvdata *drvdata)
+static int cti_enable_hw(struct cti_drvdata *drvdata, enum cs_mode mode)
{
struct cti_config *config = &drvdata->config;
+ struct coresight_device *csdev = drvdata->csdev;
unsigned long flags;
int rc = 0;

raw_spin_lock_irqsave(&drvdata->spinlock, flags);

+ if (!drvdata->config.enable_req_count) {
+ coresight_set_mode(csdev, mode);
+ } else {
+ /* The device has been configured with an incompatible mode */
+ if (coresight_get_mode(csdev) != mode) {
+ rc = -EBUSY;
+ goto cti_err_not_enabled;
+ }
+ }
+
/* no need to do anything if enabled or unpowered*/
if (config->hw_enabled || !config->hw_powered)
goto cti_state_unchanged;

/* claim the device */
- rc = coresight_claim_device(drvdata->csdev);
+ rc = coresight_claim_device(csdev);
if (rc)
goto cti_err_not_enabled;

@@ -116,6 +127,8 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)

/* cannot enable due to error */
cti_err_not_enabled:
+ if (!drvdata->config.enable_req_count)
+ coresight_set_mode(csdev, CS_MODE_DISABLED);
raw_spin_unlock_irqrestore(&drvdata->spinlock, flags);
return rc;
}
@@ -165,6 +178,8 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
if (--drvdata->config.enable_req_count > 0)
goto cti_not_disabled;

+ coresight_set_mode(csdev, CS_MODE_DISABLED);
+
/* no need to do anything if disabled or cpu unpowered */
if (!config->hw_enabled || !config->hw_powered)
goto cti_not_disabled;
@@ -803,7 +818,7 @@ int cti_enable(struct coresight_device *csdev, enum cs_mode mode, void *data)
{
struct cti_drvdata *drvdata = csdev_to_cti_drvdata(csdev);

- return cti_enable_hw(drvdata);
+ return cti_enable_hw(drvdata, mode);
}

int cti_disable(struct coresight_device *csdev, void *data)

--
2.34.1