Skip to content

Commit a03a0a0

Browse files
yabincSuzuki K Poulose
authored andcommitted
coresight: catu: Introduce refcount and spinlock for enabling/disabling
When tracing ETM data on multiple CPUs concurrently via the perf interface, the CATU device is shared across different CPU paths. This can lead to race conditions when multiple CPUs attempt to enable or disable the CATU device simultaneously. To address these race conditions, this patch introduces the following changes: 1. The enable and disable operations for the CATU device are not reentrant. Therefore, a spinlock is added to ensure that only one CPU can enable or disable a given CATU device at any point in time. 2. A reference counter is used to manage the enable/disable state of the CATU device. The device is enabled when the first CPU requires it and is only disabled when the last CPU finishes using it. This ensures the device remains active as long as at least one CPU needs it. Fixes: fcacb5c ("coresight: Introduce support for Coresight Address Translation Unit") Signed-off-by: Yabin Cui <yabinc@google.com> Reviewed-by: James Clark <james.clark@linaro.org> Reviewed-by: Leo Yan <leo.yan@arm.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Link: https://lore.kernel.org/r/20250429231301.1952246-2-yabinc@google.com
1 parent 13e3a88 commit a03a0a0

2 files changed

Lines changed: 18 additions & 8 deletions

File tree

drivers/hwtracing/coresight/coresight-catu.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -458,12 +458,17 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, enum cs_mode cs_mode,
458458
static int catu_enable(struct coresight_device *csdev, enum cs_mode mode,
459459
void *data)
460460
{
461-
int rc;
461+
int rc = 0;
462462
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
463463

464-
CS_UNLOCK(catu_drvdata->base);
465-
rc = catu_enable_hw(catu_drvdata, mode, data);
466-
CS_LOCK(catu_drvdata->base);
464+
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
465+
if (csdev->refcnt == 0) {
466+
CS_UNLOCK(catu_drvdata->base);
467+
rc = catu_enable_hw(catu_drvdata, mode, data);
468+
CS_LOCK(catu_drvdata->base);
469+
}
470+
if (!rc)
471+
csdev->refcnt++;
467472
return rc;
468473
}
469474

@@ -486,12 +491,15 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
486491

487492
static int catu_disable(struct coresight_device *csdev, void *__unused)
488493
{
489-
int rc;
494+
int rc = 0;
490495
struct catu_drvdata *catu_drvdata = csdev_to_catu_drvdata(csdev);
491496

492-
CS_UNLOCK(catu_drvdata->base);
493-
rc = catu_disable_hw(catu_drvdata);
494-
CS_LOCK(catu_drvdata->base);
497+
guard(raw_spinlock_irqsave)(&catu_drvdata->spinlock);
498+
if (--csdev->refcnt == 0) {
499+
CS_UNLOCK(catu_drvdata->base);
500+
rc = catu_disable_hw(catu_drvdata);
501+
CS_LOCK(catu_drvdata->base);
502+
}
495503
return rc;
496504
}
497505

@@ -550,6 +558,7 @@ static int __catu_probe(struct device *dev, struct resource *res)
550558
dev->platform_data = pdata;
551559

552560
drvdata->base = base;
561+
raw_spin_lock_init(&drvdata->spinlock);
553562
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
554563
catu_desc.pdata = pdata;
555564
catu_desc.dev = dev;

drivers/hwtracing/coresight/coresight-catu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ struct catu_drvdata {
6565
void __iomem *base;
6666
struct coresight_device *csdev;
6767
int irq;
68+
raw_spinlock_t spinlock;
6869
};
6970

7071
#define CATU_REG32(name, offset) \

0 commit comments

Comments
 (0)