diff options
author | Mathieu Poirier <mathieu.poirier@linaro.org> | 2019-04-25 13:52:56 -0600 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-04-25 22:00:16 +0200 |
commit | f973d88b75703719d39c4d5145079199aaf442b2 (patch) | |
tree | 3abbbcce4aa7204d7584b3bcfaca818f910d7a63 /drivers/hwtracing/coresight/coresight.c | |
parent | coresight: Adding return code to sink::disable() operation (diff) | |
download | linux-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.c | 28 |
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, |