Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1377058 > unrolled thread
| Started by | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| First post | 2016-04-12 20:00 +0200 |
| Last post | 2016-04-12 20:00 +0200 |
| Articles | 16 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH V2 00/15] coresight: tmc: make driver usable by Perf Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
[PATCH V2 02/15] coresight: tmc: waiting for TMCReady bit before programming Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
Re: [PATCH V2 02/15] coresight: tmc: waiting for TMCReady bit before programming Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-14 19:10 +0200
[PATCH V2 15/15] coresight: configuring ETF in FIFO mode when acting as link Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
[PATCH V2 04/15] coresight: tmc: introducing new header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
Re: [PATCH V2 04/15] coresight: tmc: introducing new header file Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-14 19:40 +0200
Re: [PATCH V2 04/15] coresight: tmc: introducing new header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-15 18:10 +0200
Re: [PATCH V2 04/15] coresight: tmc: introducing new header file Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-15 18:10 +0200
Re: [PATCH V2 04/15] coresight: tmc: introducing new header file Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-15 18:20 +0200
Re: [PATCH V2 04/15] coresight: tmc: introducing new header file Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-15 18:20 +0200
[PATCH V2 05/15] coresight: tmc: splitting driver in ETB/ETF and ETR components Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
[PATCH V2 08/15] coresight: tmc: getting the right read_count on tmc_open() Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
[PATCH V2 12/15] coresight: tmc: keep track of memory width Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
Re: [PATCH V2 12/15] coresight: tmc: keep track of memory width Suzuki K Poulose <Suzuki.Poulose@arm.com> - 2016-04-14 13:20 +0200
Re: [PATCH V2 12/15] coresight: tmc: keep track of memory width Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-15 18:20 +0200
[PATCH V2 13/15] coresight: tmc: implementing TMC-ETF AUX space API Mathieu Poirier <mathieu.poirier@linaro.org> - 2016-04-12 20:00 +0200
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 00/15] coresight: tmc: make driver usable by Perf |
| Message-ID | <rnaLv-2Vr-3@gated-at.bofh.it> |
This patchset makes the TMC driver usable from Perf by way of the recently added AUX area functionality. The first 12 patches remodel the driver so that the functionality is compartmented enough to be used as building blocks when interfacing with the Perf subsystem. Patch 13 and 14 implement the AUX area API, taking heavily on the existing ETB10 implementation. Finally patch 15 allows the TMC to be used as a link rather than a sink, something that is required when dealing with an ETF component. Best regards, Mathieu Changes for V2: - Renamed functions tmc_read_prepare/unprepare_etf() to tmc_read_prepare/unprepare_etb(). - Consolidated return points in functions tmc_enable_etf/etr_sink(). - Re-wrote allocation schemed in functions tmc_enable_etf/etr_sink(). - Fixed description typos in patch 7/15. - Fixed problem with linksink devices when disabling a path in patch 15/15. Mathieu Poirier (15): coresight: tmc: modifying naming convention coresight: tmc: waiting for TMCReady bit before programming coresight: tmc: re-implementing tmc_read_prepare/unprepare() functions coresight: tmc: introducing new header file coresight: tmc: splitting driver in ETB/ETF and ETR components coresight: tmc: making prepare/unprepare functions generic coresight: tmc: allocating memory when needed coresight: tmc: getting the right read_count on tmc_open() coresight: tmc: adding mode of operation for link/sinks coresight: tmc: dump system memory content only when needed coresight: tmc: make sysFS and Perf mode mutually exclusive coresight: tmc: keep track of memory width coresight: tmc: implementing TMC-ETF AUX space API coresight: tmc: implementing TMC-ETR AUX space API coresight: configuring ETF in FIFO mode when acting as link drivers/hwtracing/coresight/Makefile | 4 +- drivers/hwtracing/coresight/coresight-tmc-etf.c | 611 ++++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc-etr.c | 467 ++++++++++++++++++ drivers/hwtracing/coresight/coresight-tmc.c | 450 ++--------------- drivers/hwtracing/coresight/coresight-tmc.h | 166 +++++++ drivers/hwtracing/coresight/coresight.c | 32 +- 6 files changed, 1312 insertions(+), 418 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etf.c create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etr.c create mode 100644 drivers/hwtracing/coresight/coresight-tmc.h -- 2.5.0
[toc] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 02/15] coresight: tmc: waiting for TMCReady bit before programming |
| Message-ID | <rnaLx-2Vr-25@gated-at.bofh.it> |
| In reply to | #1377058 |
According to the TRM before programming the TMC in circular
buffer mode (and that for any configuration, ETB, ETR, ETF),
the TMCReady bit in the status register has to be set.
This patch adds a check to make sure the state machine is in
a state where it can be configured, and complains otherwise.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-tmc.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 3f646e29a99b..66fa7736d12f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -180,6 +180,9 @@ static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
CS_UNLOCK(drvdata->base);
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
@@ -201,6 +204,9 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
CS_UNLOCK(drvdata->base);
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
@@ -230,6 +236,9 @@ static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
{
CS_UNLOCK(drvdata->base);
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
drvdata->base + TMC_FFCR);
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-14 19:10 +0200 |
| Subject | Re: [PATCH V2 02/15] coresight: tmc: waiting for TMCReady bit before programming |
| Message-ID | <rnSWe-5pD-17@gated-at.bofh.it> |
| In reply to | #1377059 |
On 12/04/16 18:54, Mathieu Poirier wrote: > According to the TRM before programming the TMC in circular > buffer mode (and that for any configuration, ETB, ETR, ETF), > the TMCReady bit in the status register has to be set. > > This patch adds a check to make sure the state machine is in > a state where it can be configured, and complains otherwise. > > Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> > --- Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 15/15] coresight: configuring ETF in FIFO mode when acting as link |
| Message-ID | <rnaLx-2Vr-27@gated-at.bofh.it> |
| In reply to | #1377058 |
When part of a path but not identified as a sink, the EFT has to
be configured as a link and placed in HW FIFO mode. As such when
enabling a path, call the right configuration function based on
the role the ETF if playing in this trace run.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight.c | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 2ea5961092c1..bba9f3d653c9 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -257,15 +257,27 @@ static void coresight_disable_source(struct coresight_device *csdev)
void coresight_disable_path(struct list_head *path)
{
+ u32 type;
struct coresight_node *nd;
struct coresight_device *csdev, *parent, *child;
list_for_each_entry(nd, path, link) {
csdev = nd->csdev;
+ type = csdev->type;
- switch (csdev->type) {
+ /*
+ * ETF devices are tricky... They can be a link or a sink,
+ * depending on how they are configured. If an ETF has been
+ * "activated" it will be configured as a sink, otherwise
+ * go ahead with the link configuration.
+ */
+ if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+ type = (csdev == coresight_get_sink(path)) ?
+ CORESIGHT_DEV_TYPE_SINK :
+ CORESIGHT_DEV_TYPE_LINK;
+
+ switch (type) {
case CORESIGHT_DEV_TYPE_SINK:
- case CORESIGHT_DEV_TYPE_LINKSINK:
coresight_disable_sink(csdev);
break;
case CORESIGHT_DEV_TYPE_SOURCE:
@@ -286,15 +298,27 @@ int coresight_enable_path(struct list_head *path, u32 mode)
{
int ret = 0;
+ u32 type;
struct coresight_node *nd;
struct coresight_device *csdev, *parent, *child;
list_for_each_entry_reverse(nd, path, link) {
csdev = nd->csdev;
+ type = csdev->type;
+
+ /*
+ * ETF devices are tricky... They can be a link or a sink,
+ * depending on how they are configured. If an ETF has been
+ * "activated" it will be configured as a sink, otherwise
+ * go ahead with the link configuration.
+ */
+ if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+ type = (csdev == coresight_get_sink(path)) ?
+ CORESIGHT_DEV_TYPE_SINK :
+ CORESIGHT_DEV_TYPE_LINK;
- switch (csdev->type) {
+ switch (type) {
case CORESIGHT_DEV_TYPE_SINK:
- case CORESIGHT_DEV_TYPE_LINKSINK:
ret = coresight_enable_sink(csdev, mode);
if (ret)
goto err;
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 04/15] coresight: tmc: introducing new header file |
| Message-ID | <rnaLx-2Vr-29@gated-at.bofh.it> |
| In reply to | #1377058 |
The amount of #define, enumeration and structure definition
is big enough to justify moving them to a new header file.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-tmc.c | 102 +----------------------
drivers/hwtracing/coresight/coresight-tmc.h | 122 ++++++++++++++++++++++++++++
2 files changed, 123 insertions(+), 101 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-tmc.h
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index d211aeec49f8..01a7ce2974f7 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -30,107 +30,7 @@
#include <linux/amba/bus.h>
#include "coresight-priv.h"
-
-#define TMC_RSZ 0x004
-#define TMC_STS 0x00c
-#define TMC_RRD 0x010
-#define TMC_RRP 0x014
-#define TMC_RWP 0x018
-#define TMC_TRG 0x01c
-#define TMC_CTL 0x020
-#define TMC_RWD 0x024
-#define TMC_MODE 0x028
-#define TMC_LBUFLEVEL 0x02c
-#define TMC_CBUFLEVEL 0x030
-#define TMC_BUFWM 0x034
-#define TMC_RRPHI 0x038
-#define TMC_RWPHI 0x03c
-#define TMC_AXICTL 0x110
-#define TMC_DBALO 0x118
-#define TMC_DBAHI 0x11c
-#define TMC_FFSR 0x300
-#define TMC_FFCR 0x304
-#define TMC_PSCR 0x308
-#define TMC_ITMISCOP0 0xee0
-#define TMC_ITTRFLIN 0xee8
-#define TMC_ITATBDATA0 0xeec
-#define TMC_ITATBCTR2 0xef0
-#define TMC_ITATBCTR1 0xef4
-#define TMC_ITATBCTR0 0xef8
-
-/* register description */
-/* TMC_CTL - 0x020 */
-#define TMC_CTL_CAPT_EN BIT(0)
-/* TMC_STS - 0x00C */
-#define TMC_STS_TRIGGERED BIT(1)
-/* TMC_AXICTL - 0x110 */
-#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
-#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
-#define TMC_AXICTL_SCT_GAT_MODE BIT(7)
-#define TMC_AXICTL_WR_BURST_LEN 0xF00
-/* TMC_FFCR - 0x304 */
-#define TMC_FFCR_EN_FMT BIT(0)
-#define TMC_FFCR_EN_TI BIT(1)
-#define TMC_FFCR_FON_FLIN BIT(4)
-#define TMC_FFCR_FON_TRIG_EVT BIT(5)
-#define TMC_FFCR_FLUSHMAN BIT(6)
-#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
-#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
-
-#define TMC_STS_TMCREADY_BIT 2
-#define TMC_FFCR_FLUSHMAN_BIT 6
-
-enum tmc_config_type {
- TMC_CONFIG_TYPE_ETB,
- TMC_CONFIG_TYPE_ETR,
- TMC_CONFIG_TYPE_ETF,
-};
-
-enum tmc_mode {
- TMC_MODE_CIRCULAR_BUFFER,
- TMC_MODE_SOFTWARE_FIFO,
- TMC_MODE_HARDWARE_FIFO,
-};
-
-enum tmc_mem_intf_width {
- TMC_MEM_INTF_WIDTH_32BITS = 0x2,
- TMC_MEM_INTF_WIDTH_64BITS = 0x3,
- TMC_MEM_INTF_WIDTH_128BITS = 0x4,
- TMC_MEM_INTF_WIDTH_256BITS = 0x5,
-};
-
-/**
- * struct tmc_drvdata - specifics associated to an TMC component
- * @base: memory mapped base address for this component.
- * @dev: the device entity associated to this component.
- * @csdev: component vitals needed by the framework.
- * @miscdev: specifics to handle "/dev/xyz.tmc" entry.
- * @spinlock: only one at a time pls.
- * @read_count: manages preparation of buffer for reading.
- * @buf: area of memory where trace data get sent.
- * @paddr: DMA start location in RAM.
- * @vaddr: virtual representation of @paddr.
- * @size: @buf size.
- * @enable: this TMC is being used.
- * @config_type: TMC variant, must be of type @tmc_config_type.
- * @trigger_cntr: amount of words to store after a trigger.
- */
-struct tmc_drvdata {
- void __iomem *base;
- struct device *dev;
- struct coresight_device *csdev;
- struct miscdevice miscdev;
- spinlock_t spinlock;
- int read_count;
- bool reading;
- char *buf;
- dma_addr_t paddr;
- void *vaddr;
- u32 size;
- bool enable;
- enum tmc_config_type config_type;
- u32 trigger_cntr;
-};
+#include "coresight-tmc.h"
static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
new file mode 100644
index 000000000000..2d7d52747b4e
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CORESIGHT_TMC_H
+#define _CORESIGHT_TMC_H
+
+#define TMC_RSZ 0x004
+#define TMC_STS 0x00c
+#define TMC_RRD 0x010
+#define TMC_RRP 0x014
+#define TMC_RWP 0x018
+#define TMC_TRG 0x01c
+#define TMC_CTL 0x020
+#define TMC_RWD 0x024
+#define TMC_MODE 0x028
+#define TMC_LBUFLEVEL 0x02c
+#define TMC_CBUFLEVEL 0x030
+#define TMC_BUFWM 0x034
+#define TMC_RRPHI 0x038
+#define TMC_RWPHI 0x03c
+#define TMC_AXICTL 0x110
+#define TMC_DBALO 0x118
+#define TMC_DBAHI 0x11c
+#define TMC_FFSR 0x300
+#define TMC_FFCR 0x304
+#define TMC_PSCR 0x308
+#define TMC_ITMISCOP0 0xee0
+#define TMC_ITTRFLIN 0xee8
+#define TMC_ITATBDATA0 0xeec
+#define TMC_ITATBCTR2 0xef0
+#define TMC_ITATBCTR1 0xef4
+#define TMC_ITATBCTR0 0xef8
+
+/* register description */
+/* TMC_CTL - 0x020 */
+#define TMC_CTL_CAPT_EN BIT(0)
+/* TMC_STS - 0x00C */
+#define TMC_STS_TRIGGERED BIT(1)
+/* TMC_AXICTL - 0x110 */
+#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
+#define TMC_AXICTL_PROT_CTL_B1 BIT(1)
+#define TMC_AXICTL_SCT_GAT_MODE BIT(7)
+#define TMC_AXICTL_WR_BURST_LEN 0xF00
+/* TMC_FFCR - 0x304 */
+#define TMC_FFCR_EN_FMT BIT(0)
+#define TMC_FFCR_EN_TI BIT(1)
+#define TMC_FFCR_FON_FLIN BIT(4)
+#define TMC_FFCR_FON_TRIG_EVT BIT(5)
+#define TMC_FFCR_FLUSHMAN BIT(6)
+#define TMC_FFCR_TRIGON_TRIGIN BIT(8)
+#define TMC_FFCR_STOP_ON_FLUSH BIT(12)
+
+#define TMC_STS_TMCREADY_BIT 2
+#define TMC_FFCR_FLUSHMAN_BIT 6
+
+enum tmc_config_type {
+ TMC_CONFIG_TYPE_ETB,
+ TMC_CONFIG_TYPE_ETR,
+ TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+ TMC_MODE_CIRCULAR_BUFFER,
+ TMC_MODE_SOFTWARE_FIFO,
+ TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+ TMC_MEM_INTF_WIDTH_32BITS = 0x2,
+ TMC_MEM_INTF_WIDTH_64BITS = 0x3,
+ TMC_MEM_INTF_WIDTH_128BITS = 0x4,
+ TMC_MEM_INTF_WIDTH_256BITS = 0x5,
+};
+
+/**
+ * struct tmc_drvdata - specifics associated to an TMC component
+ * @base: memory mapped base address for this component.
+ * @dev: the device entity associated to this component.
+ * @csdev: component vitals needed by the framework.
+ * @miscdev: specifics to handle "/dev/xyz.tmc" entry.
+ * @spinlock: only one at a time pls.
+ * @read_count: manages preparation of buffer for reading.
+ * @buf: area of memory where trace data get sent.
+ * @paddr: DMA start location in RAM.
+ * @vaddr: virtual representation of @paddr.
+ * @size: @buf size.
+ * @enable: this TMC is being used.
+ * @config_type: TMC variant, must be of type @tmc_config_type.
+ * @trigger_cntr: amount of words to store after a trigger.
+ */
+struct tmc_drvdata {
+ void __iomem *base;
+ struct device *dev;
+ struct coresight_device *csdev;
+ struct miscdevice miscdev;
+ spinlock_t spinlock;
+ int read_count;
+ bool reading;
+ char *buf;
+ dma_addr_t paddr;
+ void __iomem *vaddr;
+ u32 size;
+ bool enable;
+ enum tmc_config_type config_type;
+ u32 trigger_cntr;
+};
+
+#endif
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-14 19:40 +0200 |
| Subject | Re: [PATCH V2 04/15] coresight: tmc: introducing new header file |
| Message-ID | <rnTpg-5FL-25@gated-at.bofh.it> |
| In reply to | #1377061 |
On 12/04/16 18:54, Mathieu Poirier wrote: > The amount of #define, enumeration and structure definition > is big enough to justify moving them to a new header file. > > +/* TMC_STS - 0x00C */ > +#define TMC_STS_TRIGGERED BIT(1) ... > +#define TMC_AXICTL_WR_BURST_LEN 0xF00 Nit: The value above signifies, 16 data transfers per burst. So ideally it would be good to rename it to reflect that. say, TMC_AXICTL_WR_BURST_16 > +/* TMC_FFCR - 0x304 */ > +#define TMC_FFCR_EN_FMT BIT(0) > +#define TMC_FFCR_EN_TI BIT(1) > +#define TMC_FFCR_FON_FLIN BIT(4) > +#define TMC_FFCR_FON_TRIG_EVT BIT(5) > +#define TMC_FFCR_FLUSHMAN BIT(6) > +#define TMC_FFCR_TRIGON_TRIGIN BIT(8) > +#define TMC_FFCR_STOP_ON_FLUSH BIT(12) > + > +#define TMC_STS_TMCREADY_BIT 2 > +#define TMC_FFCR_FLUSHMAN_BIT 6 nit: It would be nice to group the STS_ and FFCR_ bits together. Also I see that the defintion for TMC_STS_FULL is added in a completely unrelated patch (TMC-ETF AUX SPACE patch ?). It would be good to add it either here or in a different patch. Otherwise looks good. Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Thanks Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-15 18:10 +0200 |
| Subject | Re: [PATCH V2 04/15] coresight: tmc: introducing new header file |
| Message-ID | <roetI-5Ly-33@gated-at.bofh.it> |
| In reply to | #1379151 |
On 14 April 2016 at 11:33, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote: > On 12/04/16 18:54, Mathieu Poirier wrote: >> >> The amount of #define, enumeration and structure definition >> is big enough to justify moving them to a new header file. >> > > >> +/* TMC_STS - 0x00C */ >> +#define TMC_STS_TRIGGERED BIT(1) > > > ... > >> +#define TMC_AXICTL_WR_BURST_LEN 0xF00 > > > Nit: The value above signifies, 16 data transfers per burst. > So ideally it would be good to rename it to reflect that. say, > > TMC_AXICTL_WR_BURST_16 Will do. But I'll have to do this in a separate patch then the grouping of STS_ and FFCR_ defines you're referring to below since it will also require changes to the .c files. > > > >> +/* TMC_FFCR - 0x304 */ >> +#define TMC_FFCR_EN_FMT BIT(0) >> +#define TMC_FFCR_EN_TI BIT(1) >> +#define TMC_FFCR_FON_FLIN BIT(4) >> +#define TMC_FFCR_FON_TRIG_EVT BIT(5) >> +#define TMC_FFCR_FLUSHMAN BIT(6) >> +#define TMC_FFCR_TRIGON_TRIGIN BIT(8) >> +#define TMC_FFCR_STOP_ON_FLUSH BIT(12) >> + >> +#define TMC_STS_TMCREADY_BIT 2 > > >> +#define TMC_FFCR_FLUSHMAN_BIT 6 > > > nit: It would be nice to group the STS_ and FFCR_ bits together. > Also I see that the defintion for > TMC_STS_FULL is added in a completely unrelated patch (TMC-ETF AUX SPACE > patch ?). It would be good to add it either here or in a different patch. TMC_STS_FULL is not added here because at this point it is not used by the code - it is only added later when it is useful. Please get back to me if I missed your point. > > Otherwise looks good. > > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> > > Thanks > Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-15 18:10 +0200 |
| Subject | Re: [PATCH V2 04/15] coresight: tmc: introducing new header file |
| Message-ID | <roetI-5Ly-35@gated-at.bofh.it> |
| In reply to | #1379961 |
On 15/04/16 17:03, Mathieu Poirier wrote: > On 14 April 2016 at 11:33, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote: >> On 12/04/16 18:54, Mathieu Poirier wrote: >>> >>> The amount of #define, enumeration and structure definition >>> is big enough to justify moving them to a new header file. >>> >> >> >>> +/* TMC_STS - 0x00C */ >>> +#define TMC_STS_TRIGGERED BIT(1) >> >> >> ... >> >>> +#define TMC_AXICTL_WR_BURST_LEN 0xF00 >> >> >> Nit: The value above signifies, 16 data transfers per burst. >> So ideally it would be good to rename it to reflect that. say, >> >> TMC_AXICTL_WR_BURST_16 > > Will do. But I'll have to do this in a separate patch then the > grouping of STS_ and FFCR_ defines you're referring to below since it > will also require changes to the .c files. Yes, I don't expect this change to be part of the patch. Separate patch is fine. > >> >> >> >>> +/* TMC_FFCR - 0x304 */ >>> +#define TMC_FFCR_EN_FMT BIT(0) >>> +#define TMC_FFCR_EN_TI BIT(1) >>> +#define TMC_FFCR_FON_FLIN BIT(4) >>> +#define TMC_FFCR_FON_TRIG_EVT BIT(5) >>> +#define TMC_FFCR_FLUSHMAN BIT(6) >>> +#define TMC_FFCR_TRIGON_TRIGIN BIT(8) >>> +#define TMC_FFCR_STOP_ON_FLUSH BIT(12) >>> + >>> +#define TMC_STS_TMCREADY_BIT 2 >> >> >>> +#define TMC_FFCR_FLUSHMAN_BIT 6 >> >> >> nit: It would be nice to group the STS_ and FFCR_ bits together. >> Also I see that the defintion for >> TMC_STS_FULL is added in a completely unrelated patch (TMC-ETF AUX SPACE >> patch ?). It would be good to add it either here or in a different patch. > > TMC_STS_FULL is not added here because at this point it is not used by > the code - it is only added later when it is useful. I agree. But the patch which introduces the definition doesn't deal with TMC_STS_ at all either. Thats why I said, either here or in a different patch than what is there. May be you could club the change above and the STS_FULL into a new single patch. Its not mandatory though. Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-15 18:20 +0200 |
| Subject | Re: [PATCH V2 04/15] coresight: tmc: introducing new header file |
| Message-ID | <roeDn-5Pa-13@gated-at.bofh.it> |
| In reply to | #1379964 |
On 15 April 2016 at 10:08, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote: > On 15/04/16 17:03, Mathieu Poirier wrote: >> >> On 14 April 2016 at 11:33, Suzuki K Poulose <Suzuki.Poulose@arm.com> >> wrote: >>> >>> On 12/04/16 18:54, Mathieu Poirier wrote: >>>> >>>> >>>> The amount of #define, enumeration and structure definition >>>> is big enough to justify moving them to a new header file. >>>> >>> >>> >>>> +/* TMC_STS - 0x00C */ >>>> +#define TMC_STS_TRIGGERED BIT(1) >>> >>> >>> >>> ... >>> >>>> +#define TMC_AXICTL_WR_BURST_LEN 0xF00 >>> >>> >>> >>> Nit: The value above signifies, 16 data transfers per burst. >>> So ideally it would be good to rename it to reflect that. say, >>> >>> TMC_AXICTL_WR_BURST_16 >> >> >> Will do. But I'll have to do this in a separate patch then the >> grouping of STS_ and FFCR_ defines you're referring to below since it >> will also require changes to the .c files. > > > Yes, I don't expect this change to be part of the patch. Separate patch > is fine. > >> >>> >>> >>> >>>> +/* TMC_FFCR - 0x304 */ >>>> +#define TMC_FFCR_EN_FMT BIT(0) >>>> +#define TMC_FFCR_EN_TI BIT(1) >>>> +#define TMC_FFCR_FON_FLIN BIT(4) >>>> +#define TMC_FFCR_FON_TRIG_EVT BIT(5) >>>> +#define TMC_FFCR_FLUSHMAN BIT(6) >>>> +#define TMC_FFCR_TRIGON_TRIGIN BIT(8) >>>> +#define TMC_FFCR_STOP_ON_FLUSH BIT(12) >>>> + >>>> +#define TMC_STS_TMCREADY_BIT 2 >>> >>> >>> >>>> +#define TMC_FFCR_FLUSHMAN_BIT 6 >>> >>> >>> >>> nit: It would be nice to group the STS_ and FFCR_ bits together. >>> Also I see that the defintion for >>> TMC_STS_FULL is added in a completely unrelated patch (TMC-ETF AUX SPACE >>> patch ?). It would be good to add it either here or in a different patch. >> >> >> TMC_STS_FULL is not added here because at this point it is not used by >> the code - it is only added later when it is useful. > > > I agree. But the patch which introduces the definition doesn't deal with > TMC_STS_ at all either. Patch 13/15 is using the TMC_STS_FULL define on line 147. Am I missing your point? >Thats why I said, either here or in a different > patch > than what is there. May be you could club the change above and the STS_FULL > into a new single patch. Its not mandatory though. > > Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-15 18:20 +0200 |
| Subject | Re: [PATCH V2 04/15] coresight: tmc: introducing new header file |
| Message-ID | <roeDo-5Pa-41@gated-at.bofh.it> |
| In reply to | #1379973 |
On 15/04/16 17:15, Mathieu Poirier wrote: > On 15 April 2016 at 10:08, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote: >> On 15/04/16 17:03, Mathieu Poirier wrote: >> I agree. But the patch which introduces the definition doesn't deal with >> TMC_STS_ at all either. > > Patch 13/15 is using the TMC_STS_FULL define on line 147. Am I > missing your point? Ah, sorry, didn't see that TMC_STS_FULL was used there. Ignore my comments.
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 05/15] coresight: tmc: splitting driver in ETB/ETF and ETR components |
| Message-ID | <rnaLx-2Vr-33@gated-at.bofh.it> |
| In reply to | #1377058 |
The TMC block can operate in 3 modes (ETB, ETF and ETR) and accessed
via two interfaces (sysFS and Perf). That makes 6 mode to cover, which
is way too much coupling for a single file.
This patch splits the original TMC driver in 2 halves, one for ETB/ETF
and another one for ETR mode. A common core is kept for functionality
common to all 3 modes.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/Makefile | 4 +-
drivers/hwtracing/coresight/coresight-tmc-etf.c | 204 ++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc-etr.c | 128 ++++++++++++
drivers/hwtracing/coresight/coresight-tmc.c | 264 +-----------------------
drivers/hwtracing/coresight/coresight-tmc.h | 18 ++
5 files changed, 357 insertions(+), 261 deletions(-)
create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etf.c
create mode 100644 drivers/hwtracing/coresight/coresight-tmc-etr.c
diff --git a/drivers/hwtracing/coresight/Makefile b/drivers/hwtracing/coresight/Makefile
index 1d0e32c7dbe4..0cf842ea3fe2 100644
--- a/drivers/hwtracing/coresight/Makefile
+++ b/drivers/hwtracing/coresight/Makefile
@@ -3,7 +3,9 @@
#
obj-$(CONFIG_CORESIGHT) += coresight.o coresight-etm-perf.o
obj-$(CONFIG_OF) += of_coresight.o
-obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o
+obj-$(CONFIG_CORESIGHT_LINK_AND_SINK_TMC) += coresight-tmc.o \
+ coresight-tmc-etf.o \
+ coresight-tmc-etr.o
obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o
obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o
obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
new file mode 100644
index 000000000000..467d19221f7b
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/coresight.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
+{
+ /* Zero out the memory to help with debug */
+ memset(drvdata->buf, 0, drvdata->size);
+
+ CS_UNLOCK(drvdata->base);
+
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
+ writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+ TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+ TMC_FFCR_TRIGON_TRIGIN,
+ drvdata->base + TMC_FFCR);
+
+ writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+ tmc_enable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
+{
+ enum tmc_mem_intf_width memwidth;
+ u8 memwords;
+ char *bufp;
+ u32 read_data;
+ int i;
+
+ memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
+ if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+ memwords = 1;
+ else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+ memwords = 2;
+ else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+ memwords = 4;
+ else
+ memwords = 8;
+
+ bufp = drvdata->buf;
+ while (1) {
+ for (i = 0; i < memwords; i++) {
+ read_data = readl_relaxed(drvdata->base + TMC_RRD);
+ if (read_data == 0xFFFFFFFF)
+ return;
+ memcpy(bufp, &read_data, 4);
+ bufp += 4;
+ }
+ }
+}
+
+void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+ tmc_etb_dump_hw(drvdata);
+ tmc_disable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
+ writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
+ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
+ drvdata->base + TMC_FFCR);
+ writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
+ tmc_enable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+ tmc_disable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etf_sink(struct coresight_device *csdev, u32 mode)
+{
+ unsigned long flags;
+ 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;
+ }
+
+ tmc_etb_enable_hw(drvdata);
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETB/ETF enabled\n");
+ return 0;
+}
+
+static void tmc_disable_etf_sink(struct coresight_device *csdev)
+{
+ unsigned long flags;
+ 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;
+ }
+
+ tmc_etb_disable_hw(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETB/ETF disabled\n");
+}
+
+static int tmc_enable_etf_link(struct coresight_device *csdev,
+ int inport, int outport)
+{
+ unsigned long flags;
+ 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;
+ }
+
+ tmc_etf_enable_hw(drvdata);
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETF enabled\n");
+ return 0;
+}
+
+static void tmc_disable_etf_link(struct coresight_device *csdev,
+ int inport, int outport)
+{
+ unsigned long flags;
+ 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;
+ }
+
+ tmc_etf_disable_hw(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etf_sink_ops = {
+ .enable = tmc_enable_etf_sink,
+ .disable = tmc_disable_etf_sink,
+};
+
+static const struct coresight_ops_link tmc_etf_link_ops = {
+ .enable = tmc_enable_etf_link,
+ .disable = tmc_disable_etf_link,
+};
+
+const struct coresight_ops tmc_etb_cs_ops = {
+ .sink_ops = &tmc_etf_sink_ops,
+};
+
+const struct coresight_ops tmc_etf_cs_ops = {
+ .sink_ops = &tmc_etf_sink_ops,
+ .link_ops = &tmc_etf_link_ops,
+};
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
new file mode 100644
index 000000000000..910d6f3b7d26
--- /dev/null
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/coresight.h>
+#include "coresight-priv.h"
+#include "coresight-tmc.h"
+
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
+{
+ u32 axictl;
+
+ /* Zero out the memory to help with debug */
+ memset(drvdata->vaddr, 0, drvdata->size);
+
+ CS_UNLOCK(drvdata->base);
+
+ /* Wait for TMCSReady bit to be set */
+ tmc_wait_for_tmcready(drvdata);
+
+ writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
+ writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
+
+ axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
+ axictl |= TMC_AXICTL_WR_BURST_LEN;
+ writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+ axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
+ writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+ axictl = (axictl &
+ ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
+ TMC_AXICTL_PROT_CTL_B1;
+ writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
+
+ writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
+ writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
+ writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
+ TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
+ TMC_FFCR_TRIGON_TRIGIN,
+ drvdata->base + TMC_FFCR);
+ writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
+ tmc_enable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
+{
+ u32 rwp, val;
+
+ rwp = readl_relaxed(drvdata->base + TMC_RWP);
+ val = readl_relaxed(drvdata->base + TMC_STS);
+
+ /* How much memory do we still have */
+ if (val & BIT(0))
+ drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
+ else
+ drvdata->buf = drvdata->vaddr;
+}
+
+void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
+{
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+ tmc_etr_dump_hw(drvdata);
+ tmc_disable_hw(drvdata);
+
+ CS_LOCK(drvdata->base);
+}
+
+static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
+{
+ unsigned long flags;
+ 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;
+ }
+
+ tmc_etr_enable_hw(drvdata);
+ drvdata->enable = true;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETR enabled\n");
+ return 0;
+}
+
+static void tmc_disable_etr_sink(struct coresight_device *csdev)
+{
+ unsigned long flags;
+ 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;
+ }
+
+ tmc_etr_disable_hw(drvdata);
+ drvdata->enable = false;
+ spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+ dev_info(drvdata->dev, "TMC-ETR disabled\n");
+}
+
+static const struct coresight_ops_sink tmc_etr_sink_ops = {
+ .enable = tmc_enable_etr_sink,
+ .disable = tmc_disable_etr_sink,
+};
+
+const struct coresight_ops tmc_etr_cs_ops = {
+ .sink_ops = &tmc_etr_sink_ops,
+};
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 01a7ce2974f7..67b3cd299782 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -32,7 +32,7 @@
#include "coresight-priv.h"
#include "coresight-tmc.h"
-static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
/* Ensure formatter, unformatter and hardware fifo are empty */
if (coresight_timeout(drvdata->base,
@@ -43,7 +43,7 @@ static void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
}
}
-static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
{
u32 ffcr;
@@ -63,272 +63,16 @@ static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
tmc_wait_for_tmcready(drvdata);
}
-static void tmc_enable_hw(struct tmc_drvdata *drvdata)
+void tmc_enable_hw(struct tmc_drvdata *drvdata)
{
writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
}
-static void tmc_disable_hw(struct tmc_drvdata *drvdata)
+void tmc_disable_hw(struct tmc_drvdata *drvdata)
{
writel_relaxed(0x0, drvdata->base + TMC_CTL);
}
-static void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
-{
- /* Zero out the memory to help with debug */
- memset(drvdata->buf, 0, drvdata->size);
-
- CS_UNLOCK(drvdata->base);
-
- /* Wait for TMCSReady bit to be set */
- tmc_wait_for_tmcready(drvdata);
-
- writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
- writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
- TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
- TMC_FFCR_TRIGON_TRIGIN,
- drvdata->base + TMC_FFCR);
-
- writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
- tmc_enable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
-{
- u32 axictl;
-
- /* Zero out the memory to help with debug */
- memset(drvdata->vaddr, 0, drvdata->size);
-
- CS_UNLOCK(drvdata->base);
-
- /* Wait for TMCSReady bit to be set */
- tmc_wait_for_tmcready(drvdata);
-
- writel_relaxed(drvdata->size / 4, drvdata->base + TMC_RSZ);
- writel_relaxed(TMC_MODE_CIRCULAR_BUFFER, drvdata->base + TMC_MODE);
-
- axictl = readl_relaxed(drvdata->base + TMC_AXICTL);
- axictl |= TMC_AXICTL_WR_BURST_LEN;
- writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
- axictl &= ~TMC_AXICTL_SCT_GAT_MODE;
- writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
- axictl = (axictl &
- ~(TMC_AXICTL_PROT_CTL_B0 | TMC_AXICTL_PROT_CTL_B1)) |
- TMC_AXICTL_PROT_CTL_B1;
- writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
-
- writel_relaxed(drvdata->paddr, drvdata->base + TMC_DBALO);
- writel_relaxed(0x0, drvdata->base + TMC_DBAHI);
- writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI |
- TMC_FFCR_FON_FLIN | TMC_FFCR_FON_TRIG_EVT |
- TMC_FFCR_TRIGON_TRIGIN,
- drvdata->base + TMC_FFCR);
- writel_relaxed(drvdata->trigger_cntr, drvdata->base + TMC_TRG);
- tmc_enable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- /* Wait for TMCSReady bit to be set */
- tmc_wait_for_tmcready(drvdata);
-
- writel_relaxed(TMC_MODE_HARDWARE_FIFO, drvdata->base + TMC_MODE);
- writel_relaxed(TMC_FFCR_EN_FMT | TMC_FFCR_EN_TI,
- drvdata->base + TMC_FFCR);
- writel_relaxed(0x0, drvdata->base + TMC_BUFWM);
- tmc_enable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
- return -EBUSY;
- }
-
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
- tmc_etb_enable_hw(drvdata);
- } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- tmc_etr_enable_hw(drvdata);
- } else {
- if (mode == TMC_MODE_CIRCULAR_BUFFER)
- tmc_etb_enable_hw(drvdata);
- else
- tmc_etf_enable_hw(drvdata);
- }
- drvdata->enable = true;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- dev_info(drvdata->dev, "TMC enabled\n");
- return 0;
-}
-
-static int tmc_enable_sink(struct coresight_device *csdev, u32 mode)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static int tmc_enable_link(struct coresight_device *csdev, int inport,
- int outport)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
-{
- enum tmc_mem_intf_width memwidth;
- u8 memwords;
- char *bufp;
- u32 read_data;
- int i;
-
- memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
- if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
- memwords = 1;
- else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
- memwords = 2;
- else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
- memwords = 4;
- else
- memwords = 8;
-
- bufp = drvdata->buf;
- while (1) {
- for (i = 0; i < memwords; i++) {
- read_data = readl_relaxed(drvdata->base + TMC_RRD);
- if (read_data == 0xFFFFFFFF)
- return;
- memcpy(bufp, &read_data, 4);
- bufp += 4;
- }
- }
-}
-
-static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- tmc_flush_and_stop(drvdata);
- tmc_etb_dump_hw(drvdata);
- tmc_disable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
-{
- u32 rwp, val;
-
- rwp = readl_relaxed(drvdata->base + TMC_RWP);
- val = readl_relaxed(drvdata->base + TMC_STS);
-
- /* How much memory do we still have */
- if (val & BIT(0))
- drvdata->buf = drvdata->vaddr + rwp - drvdata->paddr;
- else
- drvdata->buf = drvdata->vaddr;
-}
-
-static void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- tmc_flush_and_stop(drvdata);
- tmc_etr_dump_hw(drvdata);
- tmc_disable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
-{
- CS_UNLOCK(drvdata->base);
-
- tmc_flush_and_stop(drvdata);
- tmc_disable_hw(drvdata);
-
- CS_LOCK(drvdata->base);
-}
-
-static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading)
- goto out;
-
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
- tmc_etb_disable_hw(drvdata);
- } else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- tmc_etr_disable_hw(drvdata);
- } else {
- if (mode == TMC_MODE_CIRCULAR_BUFFER)
- tmc_etb_disable_hw(drvdata);
- else
- tmc_etf_disable_hw(drvdata);
- }
-out:
- drvdata->enable = false;
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- dev_info(drvdata->dev, "TMC disabled\n");
-}
-
-static void tmc_disable_sink(struct coresight_device *csdev)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
-}
-
-static void tmc_disable_link(struct coresight_device *csdev, int inport,
- int outport)
-{
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
-}
-
-static const struct coresight_ops_sink tmc_sink_ops = {
- .enable = tmc_enable_sink,
- .disable = tmc_disable_sink,
-};
-
-static const struct coresight_ops_link tmc_link_ops = {
- .enable = tmc_enable_link,
- .disable = tmc_disable_link,
-};
-
-static const struct coresight_ops tmc_etb_cs_ops = {
- .sink_ops = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etr_cs_ops = {
- .sink_ops = &tmc_sink_ops,
-};
-
-static const struct coresight_ops tmc_etf_cs_ops = {
- .sink_ops = &tmc_sink_ops,
- .link_ops = &tmc_link_ops,
-};
-
static int tmc_read_prepare(struct tmc_drvdata *drvdata)
{
int ret = 0;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 2d7d52747b4e..b99d4dfc1d0b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -18,6 +18,8 @@
#ifndef _CORESIGHT_TMC_H
#define _CORESIGHT_TMC_H
+#include <linux/miscdevice.h>
+
#define TMC_RSZ 0x004
#define TMC_STS 0x00c
#define TMC_RRD 0x010
@@ -119,4 +121,20 @@ struct tmc_drvdata {
u32 trigger_cntr;
};
+/* Generic functions */
+void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata);
+void tmc_flush_and_stop(struct tmc_drvdata *drvdata);
+void tmc_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_disable_hw(struct tmc_drvdata *drvdata);
+
+/* ETB/ETF functions */
+void tmc_etb_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_etb_disable_hw(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etb_cs_ops;
+extern const struct coresight_ops tmc_etf_cs_ops;
+
+/* ETR functions */
+void tmc_etr_enable_hw(struct tmc_drvdata *drvdata);
+void tmc_etr_disable_hw(struct tmc_drvdata *drvdata);
+extern const struct coresight_ops tmc_etr_cs_ops;
#endif
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 08/15] coresight: tmc: getting the right read_count on tmc_open() |
| Message-ID | <rnaLy-2Vr-37@gated-at.bofh.it> |
| In reply to | #1377058 |
In function tmc_open(), if tmc_read_prepare() fails variable drvdata->read_count is not decremented, causing unwanted access to drvdata->buf and very likely, a crash dump. By moving the incrementation to a place where we know things are stable this kind of situation is avoided. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> --- drivers/hwtracing/coresight/coresight-tmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index ae336641518f..4d7b64f69389 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -121,13 +121,14 @@ static int tmc_open(struct inode *inode, struct file *file) struct tmc_drvdata, miscdev); int ret = 0; - if (drvdata->read_count++) + if (drvdata->read_count) goto out; ret = tmc_read_prepare(drvdata); if (ret) return ret; out: + drvdata->read_count++; nonseekable_open(inode, file); dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__); -- 2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 12/15] coresight: tmc: keep track of memory width |
| Message-ID | <rnaLy-2Vr-45@gated-at.bofh.it> |
| In reply to | #1377058 |
Accessing the HW configuration register each time the memory
width is needed simply doesn't make sense. It is much more
efficient to read the value once and keep a reference for
later use.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-tmc-etf.c | 8 +++-----
drivers/hwtracing/coresight/coresight-tmc.c | 1 +
drivers/hwtracing/coresight/coresight-tmc.h | 2 ++
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 50d32e8ef4ea..a440784e3b27 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -41,18 +41,16 @@ void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
{
- enum tmc_mem_intf_width memwidth;
u8 memwords;
char *bufp;
u32 read_data;
int i;
- memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
- if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+ if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_32BITS)
memwords = 1;
- else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+ else if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_64BITS)
memwords = 2;
- else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+ else if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_128BITS)
memwords = 4;
else
memwords = 8;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 4d7b64f69389..bc013d5f71c3 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -306,6 +306,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
devid = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
drvdata->config_type = BMVAL(devid, 6, 7);
+ drvdata->memwidth = BMVAL(devid, 8, 10);
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
if (np)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 821bdf150ac9..062dd7dcea96 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -102,6 +102,7 @@ enum tmc_mem_intf_width {
* @size: @buf size.
* @mode: how this TMC is being used.
* @config_type: TMC variant, must be of type @tmc_config_type.
+ * @memwidth: width of the memory interface databus, powers of two.
* @trigger_cntr: amount of words to store after a trigger.
*/
struct tmc_drvdata {
@@ -118,6 +119,7 @@ struct tmc_drvdata {
u32 size;
local_t mode;
enum tmc_config_type config_type;
+ enum tmc_mem_intf_width memwidth;
u32 trigger_cntr;
};
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Suzuki K Poulose <Suzuki.Poulose@arm.com> |
|---|---|
| Date | 2016-04-14 13:20 +0200 |
| Subject | Re: [PATCH V2 12/15] coresight: tmc: keep track of memory width |
| Message-ID | <rnNtw-MQ-21@gated-at.bofh.it> |
| In reply to | #1377065 |
On 12/04/16 18:54, Mathieu Poirier wrote:
> Accessing the HW configuration register each time the memory
> width is needed simply doesn't make sense. It is much more
> efficient to read the value once and keep a reference for
> later use.
>
> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> ---
> drivers/hwtracing/coresight/coresight-tmc-etf.c | 8 +++-----
> drivers/hwtracing/coresight/coresight-tmc.c | 1 +
> drivers/hwtracing/coresight/coresight-tmc.h | 2 ++
> 3 files changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> index 50d32e8ef4ea..a440784e3b27 100644
> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
> @@ -41,18 +41,16 @@ void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
>
> static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
> {
> - enum tmc_mem_intf_width memwidth;
> u8 memwords;
> char *bufp;
> u32 read_data;
> int i;
>
> - memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID), 8, 10);
> - if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
> + if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_32BITS)
> memwords = 1;
> - else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
> + else if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_64BITS)
> memwords = 2;
> - else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
> + else if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_128BITS)
> memwords = 4;
> struct tmc_drvdata {
> @@ -118,6 +119,7 @@ struct tmc_drvdata {
> u32 size;
> local_t mode;
> enum tmc_config_type config_type;
> + enum tmc_mem_intf_width memwidth;
Could we not store the converted memwords here, instead of the enum value here
and convert it every time we access it ?
Cheers
Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-15 18:20 +0200 |
| Subject | Re: [PATCH V2 12/15] coresight: tmc: keep track of memory width |
| Message-ID | <roeDo-5Pa-35@gated-at.bofh.it> |
| In reply to | #1378699 |
On 14 April 2016 at 05:19, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 12/04/16 18:54, Mathieu Poirier wrote:
>>
>> Accessing the HW configuration register each time the memory
>> width is needed simply doesn't make sense. It is much more
>> efficient to read the value once and keep a reference for
>> later use.
>>
>> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> ---
>> drivers/hwtracing/coresight/coresight-tmc-etf.c | 8 +++-----
>> drivers/hwtracing/coresight/coresight-tmc.c | 1 +
>> drivers/hwtracing/coresight/coresight-tmc.h | 2 ++
>> 3 files changed, 6 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> b/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> index 50d32e8ef4ea..a440784e3b27 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
>> @@ -41,18 +41,16 @@ void tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
>>
>> static void tmc_etb_dump_hw(struct tmc_drvdata *drvdata)
>> {
>> - enum tmc_mem_intf_width memwidth;
>> u8 memwords;
>> char *bufp;
>> u32 read_data;
>> int i;
>>
>> - memwidth = BMVAL(readl_relaxed(drvdata->base + CORESIGHT_DEVID),
>> 8, 10);
>> - if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
>> + if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_32BITS)
>> memwords = 1;
>> - else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
>> + else if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_64BITS)
>> memwords = 2;
>> - else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
>> + else if (drvdata->memwidth == TMC_MEM_INTF_WIDTH_128BITS)
>> memwords = 4;
>
>
>
>> struct tmc_drvdata {
>> @@ -118,6 +119,7 @@ struct tmc_drvdata {
>> u32 size;
>> local_t mode;
>> enum tmc_config_type config_type;
>> + enum tmc_mem_intf_width memwidth;
>
>
> Could we not store the converted memwords here, instead of the enum value
> here
> and convert it every time we access it ?
Sure, I can fix that.
Thanks for the review,
Mathieu
>
> Cheers
> Suzuki
[toc] | [prev] | [next] | [standalone]
| From | Mathieu Poirier <mathieu.poirier@linaro.org> |
|---|---|
| Date | 2016-04-12 20:00 +0200 |
| Subject | [PATCH V2 13/15] coresight: tmc: implementing TMC-ETF AUX space API |
| Message-ID | <rnaLy-2Vr-47@gated-at.bofh.it> |
| In reply to | #1377058 |
This patch implement the AUX area interfaces required to
use the TMC (configured as an ETF) from the Perf sub-system.
The heuristic is heavily borrowed from the ETB10 implementation.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
---
drivers/hwtracing/coresight/coresight-tmc-etf.c | 198 ++++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc.h | 21 +++
2 files changed, 219 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index a440784e3b27..fff175d4020d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -15,7 +15,9 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/circ_buf.h>
#include <linux/coresight.h>
+#include <linux/perf_event.h>
#include <linux/slab.h>
#include "coresight-priv.h"
#include "coresight-tmc.h"
@@ -295,9 +297,205 @@ static void tmc_disable_etf_link(struct coresight_device *csdev,
dev_info(drvdata->dev, "TMC disabled\n");
}
+static void *tmc_alloc_etf_buffer(struct coresight_device *csdev, int cpu,
+ void **pages, int nr_pages, bool overwrite)
+{
+ int node;
+ struct cs_tmc_buffers *buf;
+
+ if (cpu == -1)
+ cpu = smp_processor_id();
+ node = cpu_to_node(cpu);
+
+ /* Allocate memory structure for interaction with Perf */
+ buf = kzalloc_node(sizeof(struct cs_tmc_buffers), GFP_KERNEL, node);
+ if (!buf)
+ return NULL;
+
+ buf->snapshot = overwrite;
+ buf->nr_pages = nr_pages;
+ buf->data_pages = pages;
+
+ return buf;
+}
+
+static void tmc_free_etf_buffer(void *config)
+{
+ struct cs_tmc_buffers *buf = config;
+
+ kfree(buf);
+}
+
+static int tmc_set_etf_buffer(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *sink_config)
+{
+ int ret = 0;
+ unsigned long head;
+ struct cs_tmc_buffers *buf = sink_config;
+
+ /* wrap head around to the amount of space we have */
+ head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
+
+ /* find the page to write to */
+ buf->cur = head / PAGE_SIZE;
+
+ /* and offset within that page */
+ buf->offset = head % PAGE_SIZE;
+
+ local_set(&buf->data_size, 0);
+
+ return ret;
+}
+
+static unsigned long tmc_reset_etf_buffer(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *sink_config, bool *lost)
+{
+ unsigned long size = 0;
+ struct cs_tmc_buffers *buf = sink_config;
+
+ if (buf) {
+ /*
+ * In snapshot mode ->data_size holds the new address of the
+ * ring buffer's head. The size itself is the whole address
+ * range since we want the latest information.
+ */
+ if (buf->snapshot)
+ handle->head = local_xchg(&buf->data_size,
+ buf->nr_pages << PAGE_SHIFT);
+ /*
+ * Tell the tracer PMU how much we got in this run and if
+ * something went wrong along the way. Nobody else can use
+ * this cs_tmc_buffers instance until we are done. As such
+ * resetting parameters here and squaring off with the ring
+ * buffer API in the tracer PMU is fine.
+ */
+ *lost = !!local_xchg(&buf->lost, 0);
+ size = local_xchg(&buf->data_size, 0);
+ }
+
+ return size;
+}
+
+static void tmc_update_etf_buffer(struct coresight_device *csdev,
+ struct perf_output_handle *handle,
+ void *sink_config)
+{
+ int i, cur;
+ u32 *buf_ptr;
+ u32 read_ptr, write_ptr;
+ u32 status, to_read;
+ unsigned long offset;
+ struct cs_tmc_buffers *buf = sink_config;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+ if (!buf)
+ return;
+
+ /* This shouldn't happen */
+ if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
+ return;
+
+ CS_UNLOCK(drvdata->base);
+
+ tmc_flush_and_stop(drvdata);
+
+ read_ptr = readl_relaxed(drvdata->base + TMC_RRP);
+ write_ptr = readl_relaxed(drvdata->base + TMC_RWP);
+
+ /*
+ * Get a hold of the status register and see if a wrap around
+ * has occurred. If so adjust things accordingly.
+ */
+ status = readl_relaxed(drvdata->base + TMC_STS);
+ if (status & TMC_STS_FULL) {
+ local_inc(&buf->lost);
+ to_read = drvdata->size;
+ } else {
+ to_read = CIRC_CNT(write_ptr, read_ptr, drvdata->size);
+ }
+
+ /*
+ * The TMC RAM buffer may be bigger than the space available in the
+ * perf ring buffer (handle->size). If so advance the RRP so that we
+ * get the latest trace data.
+ */
+ if (to_read > handle->size) {
+ u32 mask = 0;
+
+ /*
+ * The value written to RRP must be byte-address aligned to
+ * the width of the trace memory databus _and_ to a frame
+ * boundary (16 byte), whichever is the biggest. For example,
+ * for 32-bit, 64-bit and 128-bit wide trace memory, the four
+ * LSBs must be 0s. For 256-bit wide trace memory, the five
+ * LSBs must be 0s.
+ */
+ switch (drvdata->memwidth) {
+ case TMC_MEM_INTF_WIDTH_32BITS:
+ case TMC_MEM_INTF_WIDTH_64BITS:
+ case TMC_MEM_INTF_WIDTH_128BITS:
+ mask = GENMASK(31, 5);
+ break;
+ case TMC_MEM_INTF_WIDTH_256BITS:
+ mask = GENMASK(31, 6);
+ break;
+ }
+
+ /*
+ * Make sure the new size is aligned in accordance with the
+ * requirement explained above.
+ */
+ to_read -= handle->size & mask;
+ /* Move the RAM read pointer up */
+ read_ptr = (write_ptr + drvdata->size) - to_read;
+ /* Make sure we are still within our limits */
+ read_ptr &= ~(drvdata->size - 1);
+ /* Tell the HW */
+ writel_relaxed(read_ptr, drvdata->base + TMC_RRP);
+ local_inc(&buf->lost);
+ }
+
+ cur = buf->cur;
+ offset = buf->offset;
+
+ /* for every byte to read */
+ for (i = 0; i < to_read; i += 4) {
+ buf_ptr = buf->data_pages[cur] + offset;
+ *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD);
+
+ offset += 4;
+ if (offset >= PAGE_SIZE) {
+ offset = 0;
+ cur++;
+ /* wrap around at the end of the buffer */
+ cur &= buf->nr_pages - 1;
+ }
+ }
+
+ /*
+ * In snapshot mode all we have to do is communicate to
+ * perf_aux_output_end() the address of the current head. In full
+ * trace mode the same function expects a size to move rb->aux_head
+ * forward.
+ */
+ if (buf->snapshot)
+ local_set(&buf->data_size, (cur * PAGE_SIZE) + offset);
+ else
+ local_add(to_read, &buf->data_size);
+
+ CS_LOCK(drvdata->base);
+}
+
static const struct coresight_ops_sink tmc_etf_sink_ops = {
.enable = tmc_enable_etf_sink,
.disable = tmc_disable_etf_sink,
+ .alloc_buffer = tmc_alloc_etf_buffer,
+ .free_buffer = tmc_free_etf_buffer,
+ .set_buffer = tmc_set_etf_buffer,
+ .reset_buffer = tmc_reset_etf_buffer,
+ .update_buffer = tmc_update_etf_buffer,
};
static const struct coresight_ops_link tmc_etf_link_ops = {
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 062dd7dcea96..62d568195e8e 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -51,6 +51,7 @@
/* TMC_CTL - 0x020 */
#define TMC_CTL_CAPT_EN BIT(0)
/* TMC_STS - 0x00C */
+#define TMC_STS_FULL BIT(0)
#define TMC_STS_TRIGGERED BIT(1)
/* TMC_AXICTL - 0x110 */
#define TMC_AXICTL_PROT_CTL_B0 BIT(0)
@@ -89,6 +90,26 @@ enum tmc_mem_intf_width {
};
/**
+ * struct cs_buffer - keep track of a recording session' specifics
+ * @cur: index of the current buffer
+ * @nr_pages: max number of pages granted to us
+ * @offset: offset within the current buffer
+ * @data_size: how much we collected in this run
+ * @lost: other than zero if we had a HW buffer wrap around
+ * @snapshot: is this run in snapshot mode
+ * @data_pages: a handle the ring buffer
+ */
+struct cs_tmc_buffers {
+ unsigned int cur;
+ unsigned int nr_pages;
+ unsigned long offset;
+ local_t data_size;
+ local_t lost;
+ bool snapshot;
+ void **data_pages;
+};
+
+/**
* struct tmc_drvdata - specifics associated to an TMC component
* @base: memory mapped base address for this component.
* @dev: the device entity associated to this component.
--
2.5.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web