aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing/coresight/coresight.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.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.c')
-rw-r--r--drivers/hwtracing/coresight/coresight.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 66c25b0a785e..4b130281236a 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -225,14 +225,13 @@ static int coresight_enable_sink(struct coresight_device *csdev,
* We need to make sure the "new" session is compatible with the
* existing "mode" of operation.
*/
- if (sink_ops(csdev)->enable) {
- ret = sink_ops(csdev)->enable(csdev, mode, data);
- if (ret)
- return ret;
- csdev->enable = true;
- }
+ if (!sink_ops(csdev)->enable)
+ return -EINVAL;
- atomic_inc(csdev->refcnt);
+ ret = sink_ops(csdev)->enable(csdev, mode, data);
+ if (ret)
+ return ret;
+ csdev->enable = true;
return 0;
}
@@ -241,14 +240,13 @@ static void coresight_disable_sink(struct coresight_device *csdev)
{
int ret;
- if (atomic_dec_return(csdev->refcnt) == 0) {
- if (sink_ops(csdev)->disable) {
- ret = sink_ops(csdev)->disable(csdev);
- if (ret)
- return;
- csdev->enable = false;
- }
- }
+ if (!sink_ops(csdev)->disable)
+ return;
+
+ ret = sink_ops(csdev)->disable(csdev);
+ if (ret)
+ return;
+ csdev->enable = false;
}
static int coresight_enable_link(struct coresight_device *csdev,