[PATCH v3 18/31] coresight: cti: Fix race condition by using device mode
Mike Leach
mike.leach at linaro.org
Thu Oct 2 06:31:53 PDT 2025
Hi Leo,
On Mon, 15 Sept 2025 at 11:34, Leo Yan <leo.yan at arm.com> wrote:
>
> 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 at arm.com>
> ---
> 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;
> + }
> + }
> +
Would this be simpler to check along the lines of
if (curr_mode != DISABLED && curr_mode != mode)
rc = -EBUSY; goto err_not_enabled.
then put the set_mode() in the code that is run only once on enable,
removing the need to reset mode in error path?
> /* 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
>
Regards
Mike
--
Mike Leach
Principal Engineer, ARM Ltd.
Manchester Design Centre. UK
More information about the linux-arm-kernel
mailing list