From: Mathieu Poirier <mathieu.poirier@linaro.org>
To: linux-arm-kernel@lists.infradead.org
Cc: suzuki.poulose@arm.com, alexander.shishkin@linux.intel.com,
coresight@lists.linaro.org, peterz@infradead.org,
mike.leach@arm.com, leo.yan@linaro.org
Subject: [PATCH v2 05/16] coresight: Move reference counting inside sink drivers
Date: Mon, 25 Mar 2019 15:56:21 -0600 [thread overview]
Message-ID: <20190325215632.17013-6-mathieu.poirier@linaro.org> (raw)
In-Reply-To: <20190325215632.17013-1-mathieu.poirier@linaro.org>
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>
---
drivers/hwtracing/coresight/coresight-etb10.c | 21 ++++++++++----
.../hwtracing/coresight/coresight-tmc-etf.c | 21 +++++++++++---
.../hwtracing/coresight/coresight-tmc-etr.c | 19 +++++++++++--
drivers/hwtracing/coresight/coresight-tpiu.c | 6 +++-
drivers/hwtracing/coresight/coresight.c | 28 +++++++++----------
5 files changed, 66 insertions(+), 29 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 71c2a3cdb866..5af50a852e87 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -5,6 +5,7 @@
* Description: CoreSight Embedded Trace Buffer driver
*/
+#include <linux/atomic.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -159,14 +160,15 @@ static int etb_enable_sysfs(struct coresight_device *csdev)
goto out;
}
- /* Nothing to do, the tracer is already enabled. */
- if (drvdata->mode == CS_MODE_SYSFS)
- goto out;
+ if (drvdata->mode == CS_MODE_DISABLED) {
+ ret = etb_enable_hw(drvdata);
+ if (ret)
+ goto out;
- ret = etb_enable_hw(drvdata);
- if (!ret)
drvdata->mode = CS_MODE_SYSFS;
+ }
+ atomic_inc(csdev->refcnt);
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return ret;
@@ -196,8 +198,10 @@ static int etb_enable_perf(struct coresight_device *csdev, void *data)
goto out;
ret = etb_enable_hw(drvdata);
- if (!ret)
+ if (!ret) {
drvdata->mode = CS_MODE_PERF;
+ atomic_inc(csdev->refcnt);
+ }
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -332,6 +336,11 @@ static int etb_disable(struct coresight_device *csdev)
spin_lock_irqsave(&drvdata->spinlock, flags);
+ if (atomic_dec_return(csdev->refcnt)) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
/* Disable the ETB only if it needs to */
if (drvdata->mode != CS_MODE_DISABLED) {
etb_disable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index d4213e7c2c45..d50a608a60f1 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -4,6 +4,7 @@
* Author: Mathieu Poirier <mathieu.poirier@linaro.org>
*/
+#include <linux/atomic.h>
#include <linux/circ_buf.h>
#include <linux/coresight.h>
#include <linux/perf_event.h>
@@ -180,8 +181,10 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
* sink is already enabled no memory is needed and the HW need not be
* touched.
*/
- if (drvdata->mode == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS) {
+ atomic_inc(csdev->refcnt);
goto out;
+ }
/*
* If drvdata::buf isn't NULL, memory was allocated for a previous
@@ -200,11 +203,13 @@ static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
}
ret = tmc_etb_enable_hw(drvdata);
- if (!ret)
+ if (!ret) {
drvdata->mode = CS_MODE_SYSFS;
- else
+ atomic_inc(csdev->refcnt);
+ } else {
/* Free up the buffer if we failed to enable */
used = false;
+ }
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -239,8 +244,10 @@ static int tmc_enable_etf_sink_perf(struct coresight_device *csdev, void *data)
if (ret)
break;
ret = tmc_etb_enable_hw(drvdata);
- if (!ret)
+ if (!ret) {
drvdata->mode = CS_MODE_PERF;
+ atomic_inc(csdev->refcnt);
+ }
} while (0);
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -279,11 +286,17 @@ static int tmc_disable_etf_sink(struct coresight_device *csdev)
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock_irqsave(&drvdata->spinlock, flags);
+
if (drvdata->reading) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return -EBUSY;
}
+ if (atomic_dec_return(csdev->refcnt)) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
/* Disable the TMC only if it needs to */
if (drvdata->mode != CS_MODE_DISABLED) {
tmc_etb_disable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 33501777038a..f90bca971367 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -4,6 +4,7 @@
* Author: Mathieu Poirier <mathieu.poirier@linaro.org>
*/
+#include <linux/atomic.h>
#include <linux/coresight.h>
#include <linux/dma-mapping.h>
#include <linux/iommu.h>
@@ -1124,8 +1125,10 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
* sink is already enabled no memory is needed and the HW need not be
* touched, even if the buffer size has changed.
*/
- if (drvdata->mode == CS_MODE_SYSFS)
+ if (drvdata->mode == CS_MODE_SYSFS) {
+ atomic_inc(csdev->refcnt);
goto out;
+ }
/*
* If we don't have a buffer or it doesn't match the requested size,
@@ -1138,8 +1141,10 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
}
ret = tmc_etr_enable_hw(drvdata, drvdata->sysfs_buf);
- if (!ret)
+ if (!ret) {
drvdata->mode = CS_MODE_SYSFS;
+ atomic_inc(csdev->refcnt);
+ }
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -1370,8 +1375,10 @@ static int tmc_enable_etr_sink_perf(struct coresight_device *csdev, void *data)
etr_perf->head = PERF_IDX2OFF(handle->head, etr_perf);
drvdata->perf_data = etr_perf;
rc = tmc_etr_enable_hw(drvdata, etr_perf->etr_buf);
- if (!rc)
+ if (!rc) {
drvdata->mode = CS_MODE_PERF;
+ atomic_inc(csdev->refcnt);
+ }
unlock_out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
@@ -1398,11 +1405,17 @@ static int tmc_disable_etr_sink(struct coresight_device *csdev)
struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
spin_lock_irqsave(&drvdata->spinlock, flags);
+
if (drvdata->reading) {
spin_unlock_irqrestore(&drvdata->spinlock, flags);
return -EBUSY;
}
+ if (atomic_dec_return(csdev->refcnt)) {
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ return -EBUSY;
+ }
+
/* Disable the TMC only if it needs to */
if (drvdata->mode != CS_MODE_DISABLED) {
tmc_etr_disable_hw(drvdata);
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 0d13da1b9df1..7acbeffcc137 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");
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 13eda4693f81..19ba121d7451 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,
--
2.17.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-03-25 21:57 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-25 21:56 [PATCH v2 00/16] coresight: Add support for CPU-wide trace scenarios Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 01/16] coresight: pmu: Adding ITRACE property to cs_etm PMU Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 02/16] coresight: etm4x: Add kernel configuration for CONTEXTID Mathieu Poirier
2019-03-26 11:59 ` Suzuki K Poulose
2019-03-25 21:56 ` [PATCH v2 03/16] coresight: etm4x: Configure tracers to emit timestamps Mathieu Poirier
2019-03-26 11:53 ` Suzuki K Poulose
2019-03-25 21:56 ` [PATCH v2 04/16] coresight: Adding return code to sink::disable() operation Mathieu Poirier
2019-03-26 14:55 ` Suzuki K Poulose
2019-03-25 21:56 ` Mathieu Poirier [this message]
2019-03-26 15:04 ` [PATCH v2 05/16] coresight: Move reference counting inside sink drivers Suzuki K Poulose
2019-03-25 21:56 ` [PATCH v2 06/16] coresight: Properly address errors in sink::disable() functions Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 07/16] coresight: Properly address concurrency in sink::update() functions Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 08/16] coresight: perf: Clean up function etm_setup_aux() Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 09/16] coresight: perf: Refactor function free_event_data() Mathieu Poirier
2019-03-26 15:07 ` Suzuki K Poulose
2019-03-25 21:56 ` [PATCH v2 10/16] coresight: Communicate perf event to sink buffer allocation function Mathieu Poirier
2019-03-26 15:12 ` Suzuki K Poulose
2019-03-25 21:56 ` [PATCH v2 11/16] coresight: tmc-etr: Refactor function tmc_etr_setup_perf_buf() Mathieu Poirier
2019-03-26 15:29 ` Suzuki K Poulose
2019-03-26 16:29 ` Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 12/16] coresight: tmc-etr: Introduce the notion of process ID to ETR devices Mathieu Poirier
2019-03-26 16:46 ` Suzuki K Poulose
2019-03-26 18:06 ` Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 13/16] coresight: tmc-etr: Allow events to use the same ETR buffer Mathieu Poirier
2019-03-26 16:18 ` Suzuki K Poulose
2019-03-26 17:55 ` Mathieu Poirier
2019-03-27 11:32 ` Suzuki K Poulose
2019-03-27 17:01 ` Mathieu Poirier
2019-04-01 13:01 ` Suzuki K Poulose
2019-04-03 2:13 ` Mathieu Poirier
2019-03-30 15:43 ` Leo Yan
2019-04-01 7:29 ` Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 14/16] coresight: tmc-etr: Add support for CPU-wide trace scenarios Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 15/16] coresight: tmc-etf: " Mathieu Poirier
2019-03-25 21:56 ` [PATCH v2 16/16] coresight: etb10: " Mathieu Poirier
2019-03-27 7:52 ` [PATCH v2 00/16] coresight: " Leo Yan
2019-03-27 14:40 ` Mathieu Poirier
2019-03-27 14:44 ` Leo Yan
2019-04-11 18:52 ` Robert Walker
2019-04-16 19:37 ` Mathieu Poirier
2019-04-24 16:22 ` Robert Walker
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20190325215632.17013-6-mathieu.poirier@linaro.org \
--to=mathieu.poirier@linaro.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=coresight@lists.linaro.org \
--cc=leo.yan@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=mike.leach@arm.com \
--cc=peterz@infradead.org \
--cc=suzuki.poulose@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).