patch "coresight: Serialize enabling/disabling a link device." added to char-misc-next
This is a note to let you know that I've just added the patch titled
coresight: Serialize enabling/disabling a link device.
to my char-misc git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
in the char-misc-next branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will also be merged in the next major kernel release during the merge window.
If you have any questions about this process, please let me know.
From edda32dabedb01f98b9d7b9a4492c13357834bbe Mon Sep 17 00:00:00 2001
From: Yabin Cui <[email protected]>
Date: Mon, 4 Nov 2019 11:12:50 -0700
Subject: coresight: Serialize enabling/disabling a link device.
When tracing etm data of multiple threads on multiple cpus through perf interface, some link devices are shared between paths of different cpus. It creates race conditions when different cpus wants to enable/disable the same link device at the same time.
Example 1:
Two cpus want to enable different ports of a coresight funnel, thus calling the funnel enable operation at the same time. But the funnel enable operation isn't reentrantable.
Example 2:
For an enabled coresight dynamic replicator with refcnt=1, one cpu wants to disable it, while another cpu wants to enable it. Ideally we still have an enabled replicator with refcnt=1 at the end. But in reality the result is uncertain.
Since coresight devices claim themselves when enabled for self-hosted usage, the race conditions above usually make the link devices not usable after many cycles.
To fix the race conditions, this patch uses spinlocks to serialize enabling/disabling link devices.
--- .../hwtracing/coresight/coresight-funnel.c | 36 +++++++++++---- .../coresight/coresight-replicator.c | 35 ++++++++++++--- .../hwtracing/coresight/coresight-tmc-etf.c | 26 ++++++++--- drivers/hwtracing/coresight/coresight.c | 45 ++++++------------- 4 files changed, 90 insertions(+), 52 deletions(-)
drivers/hwtracing/coresight/coresight-funnel.c +28 -8
@@ -38,12 +38,14 @@ DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel");* @atclk: optional clock for the core parts of the funnel. * @csdev: component vitals needed by the framework. * @priority: port selection order. +* @spinlock: serialize enable/disable operations. */ struct funnel_drvdata {void __iomem *base;struct clk *atclk;struct coresight_device *csdev;unsigned long priority; +spinlock_t spinlock; };static int dynamic_funnel_enable_hw (struct funnel_drvdata *drvdata,int port)
@@ -76,11 +78,21 @@ static int funnel_enable(struct coresight_device *csdev, int inport, {int rc =0 ;struct funnel_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); - -if (drvdata->base) - rc =dynamic_funnel_enable_hw (drvdata, inport); - +unsigned long flags; +bool first_enable = false; + +spin_lock_irqsave (&drvdata->spinlock, flags); +if (atomic_read (&csdev->refcnt[inport]) ==0 ) { +if (drvdata->base) + rc =dynamic_funnel_enable_hw (drvdata, inport); +if (!rc) + first_enable = true; + }if (!rc) +atomic_inc (&csdev->refcnt[inport]); +spin_unlock_irqrestore (&drvdata->spinlock, flags); + +if (first_enable)dev_dbg (&csdev->dev,"FUNNEL inport %d enabled\n" , inport);return rc; }
@@ -107,11 +119,19 @@ static void funnel_disable(struct coresight_device *csdev, int inport, int outport) {struct funnel_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); +unsigned long flags; +bool last_disable = false; + +spin_lock_irqsave (&drvdata->spinlock, flags); +if (atomic_dec_return (&csdev->refcnt[inport]) ==0 ) { +if (drvdata->base) +dynamic_funnel_disable_hw (drvdata, inport); + last_disable = true; + } +spin_unlock_irqrestore (&drvdata->spinlock, flags); -if (drvdata->base) -dynamic_funnel_disable_hw (drvdata, inport); - -dev_dbg (&csdev->dev,"FUNNEL inport %d disabled\n" , inport); +if (last_disable) +dev_dbg (&csdev->dev,"FUNNEL inport %d disabled\n" , inport); }static const struct coresight_ops_link funnel_link_ops = {
drivers/hwtracing/coresight/coresight-replicator.c +29 -6
@@ -31,11 +31,13 @@ DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator");* whether this one is programmable or not. * @atclk: optional clock for the core parts of the replicator. * @csdev: component vitals needed by the framework +* @spinlock: serialize enable/disable operations. */ struct replicator_drvdata {void __iomem *base;struct clk *atclk;struct coresight_device *csdev; +spinlock_t spinlock; };static void dynamic_replicator_reset (struct replicator_drvdata *drvdata)
@@ -97,10 +99,22 @@ static int replicator_enable(struct coresight_device *csdev, int inport, {int rc =0 ;struct replicator_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); - -if (drvdata->base) - rc =dynamic_replicator_enable (drvdata, inport, outport); +unsigned long flags; +bool first_enable = false; + +spin_lock_irqsave (&drvdata->spinlock, flags); +if (atomic_read (&csdev->refcnt[outport]) ==0 ) { +if (drvdata->base) + rc =dynamic_replicator_enable (drvdata, inport, + outport); +if (!rc) + first_enable = true; + }if (!rc) +atomic_inc (&csdev->refcnt[outport]); +spin_unlock_irqrestore (&drvdata->spinlock, flags); + +if (first_enable)dev_dbg (&csdev->dev,"REPLICATOR enabled\n" );return rc; }
@@ -137,10 +151,19 @@ static void replicator_disable(struct coresight_device *csdev, int inport, int outport) {struct replicator_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); +unsigned long flags; +bool last_disable = false; + +spin_lock_irqsave (&drvdata->spinlock, flags); +if (atomic_dec_return (&csdev->refcnt[outport]) ==0 ) { +if (drvdata->base) +dynamic_replicator_disable (drvdata, inport, outport); + last_disable = true; + } +spin_unlock_irqrestore (&drvdata->spinlock, flags); -if (drvdata->base) -dynamic_replicator_disable (drvdata, inport, outport); -dev_dbg (&csdev->dev,"REPLICATOR disabled\n" ); +if (last_disable) +dev_dbg (&csdev->dev,"REPLICATOR disabled\n" ); }static const struct coresight_ops_link replicator_link_ops = {
drivers/hwtracing/coresight/coresight-tmc-etf.c +19 -7
@@ -334,9 +334,10 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)static int tmc_enable_etf_link (struct coresight_device *csdev,int inport,int outport) { -int ret; +int ret =0 ;unsigned long flags;struct tmc_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); +bool first_enable = false;spin_lock_irqsave (&drvdata->spinlock, flags);if (drvdata->reading) {
@@ -344,12 +345,18 @@ static int tmc_enable_etf_link(struct coresight_device *csdev,return -EBUSY ; } - ret =tmc_etf_enable_hw (drvdata); +if (atomic_read (&csdev->refcnt[0 ]) ==0 ) { + ret =tmc_etf_enable_hw (drvdata); +if (!ret) { + drvdata->mode =CS_MODE_SYSFS ; + first_enable = true; + } + }if (!ret) - drvdata->mode =CS_MODE_SYSFS ; +atomic_inc (&csdev->refcnt[0 ]);spin_unlock_irqrestore (&drvdata->spinlock, flags); -if (!ret) +if (first_enable)dev_dbg (&csdev->dev,"TMC-ETF enabled\n" );return ret; }
@@ -359,6 +366,7 @@ static void tmc_disable_etf_link(struct coresight_device *csdev, {unsigned long flags;struct tmc_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); +bool last_disable = false;spin_lock_irqsave (&drvdata->spinlock, flags);if (drvdata->reading) {
@@ -366,11 +374,15 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,return ; } -tmc_etf_disable_hw (drvdata); - drvdata->mode =CS_MODE_DISABLED ; +if (atomic_dec_return (&csdev->refcnt[0 ]) ==0 ) { +tmc_etf_disable_hw (drvdata); + drvdata->mode =CS_MODE_DISABLED ; + last_disable = true; + }spin_unlock_irqrestore (&drvdata->spinlock, flags); -dev_dbg (&csdev->dev,"TMC-ETF disabled\n" ); +if (last_disable) +dev_dbg (&csdev->dev,"TMC-ETF disabled\n" ); } static void *tmc_alloc_etf_buffer(struct coresight_device *csdev,
drivers/hwtracing/coresight/coresight.c +14 -31
79 lines not on this page · raw message
Signature · 1 line
2.23.0