aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing/coresight/coresight-tpiu.c
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2019-04-25 13:52:56 -0600
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-04-25 22:00:16 +0200
commitf973d88b75703719d39c4d5145079199aaf442b2 (patch)
tree3abbbcce4aa7204d7584b3bcfaca818f910d7a63 /drivers/hwtracing/coresight/coresight-tpiu.c
parentcoresight: Adding return code to sink::disable() operation (diff)
downloadlinux-dev-f973d88b75703719d39c4d5145079199aaf442b2.tar.xz
linux-dev-f973d88b75703719d39c4d5145079199aaf442b2.zip
coresight: Move reference counting inside sink drivers
When operating in CPU-wide mode with an N:1 source/sink HW topology, multiple CPUs can access a sink concurrently. As such reference counting needs to happen when the device's spinlock is held to avoid racing with other operations (start(), update(), stop()), such as: session A Session B ----- ------- enable_sink atomic_inc(refcount) = 1 ... atomic_dec(refcount) = 0 enable_sink if (refcount == 0) disable_sink atomic_inc() Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Tested-by: Leo Yan <leo.yan@linaro.org> Tested-by: Robert Walker <robert.walker@arm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing/coresight/coresight-tpiu.c')
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index c1b77e3c3187..63d9af31f57f 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -5,6 +5,7 @@
* Description: CoreSight Trace Port Interface Unit driver
*/
+#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
@@ -73,7 +74,7 @@ static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
tpiu_enable_hw(drvdata);
-
+ atomic_inc(csdev->refcnt);
dev_dbg(drvdata->dev, "TPIU enabled\n");
return 0;
}
@@ -98,6 +99,9 @@ static int tpiu_disable(struct coresight_device *csdev)
{
struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+ if (atomic_dec_return(csdev->refcnt))
+ return -EBUSY;
+
tpiu_disable_hw(drvdata);
dev_dbg(drvdata->dev, "TPIU disabled\n");