2019-04-19 00:11:26

by Eric Anholt

[permalink] [raw]
Subject: [PATCH 1/4] drm/v3d: Fix debugfs reads of MMU regs.

They're in the hub, not the individual cores.

Signed-off-by: Eric Anholt <[email protected]>
---
drivers/gpu/drm/v3d/v3d_debugfs.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c
index a2dc4262955e..356a8acfa72d 100644
--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
@@ -26,6 +26,10 @@ static const struct v3d_reg_def v3d_hub_reg_defs[] = {
REGDEF(V3D_HUB_IDENT3),
REGDEF(V3D_HUB_INT_STS),
REGDEF(V3D_HUB_INT_MSK_STS),
+
+ REGDEF(V3D_MMU_CTL),
+ REGDEF(V3D_MMU_VIO_ADDR),
+ REGDEF(V3D_MMU_VIO_ID),
};

static const struct v3d_reg_def v3d_gca_reg_defs[] = {
@@ -50,9 +54,6 @@ static const struct v3d_reg_def v3d_core_reg_defs[] = {
REGDEF(V3D_PTB_BPCA),
REGDEF(V3D_PTB_BPCS),

- REGDEF(V3D_MMU_CTL),
- REGDEF(V3D_MMU_VIO_ADDR),
-
REGDEF(V3D_GMP_STATUS),
REGDEF(V3D_GMP_CFG),
REGDEF(V3D_GMP_VIO_ADDR),
--
2.20.1


2019-04-19 00:11:32

by Eric Anholt

[permalink] [raw]
Subject: [PATCH 4/4] drm/v3d: Fix and extend MMU error handling.

We were setting the wrong flags to enable PTI errors, so we were
seeing reads to invalid PTEs show up as write errors. Also, we
weren't turning on the interrupts. The AXI IDs we were dumping
included the outstanding write number and so they looked basically
random. And the VIO_ADDR decoding was based on the MMU VA_WIDTH for
the first platform I worked on and was wrong on others. In short,
this was a thorough mess from early HW enabling.

Tested on V3D 4.1 and 4.2 with intentional L2T, CLE, PTB, and TLB
faults.

Signed-off-by: Eric Anholt <[email protected]>
---
drivers/gpu/drm/v3d/v3d_drv.c | 1 +
drivers/gpu/drm/v3d/v3d_drv.h | 2 ++
drivers/gpu/drm/v3d/v3d_irq.c | 31 +++++++++++++++++++++++++++----
drivers/gpu/drm/v3d/v3d_mmu.c | 7 +++++--
drivers/gpu/drm/v3d/v3d_regs.h | 3 ++-
5 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 7ab36192e6bc..9ce2e4ef6c2a 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -494,6 +494,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
dev->coherent_dma_mask =
DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
+ v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);

ident1 = V3D_READ(V3D_HUB_IDENT1);
v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index 6d31a6a5a08e..64682923018d 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -63,6 +63,8 @@ struct v3d_dev {
*/
void *mmu_scratch;
dma_addr_t mmu_scratch_paddr;
+ /* virtual address bits from V3D to the MMU. */
+ int va_width;

/* Number of V3D cores. */
u32 cores;
diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
index fac3c542860b..268d8a889ac5 100644
--- a/drivers/gpu/drm/v3d/v3d_irq.c
+++ b/drivers/gpu/drm/v3d/v3d_irq.c
@@ -162,10 +162,33 @@ v3d_hub_irq(int irq, void *arg)
V3D_HUB_INT_MMU_PTI |
V3D_HUB_INT_MMU_CAP)) {
u32 axi_id = V3D_READ(V3D_MMU_VIO_ID);
- u64 vio_addr = (u64)V3D_READ(V3D_MMU_VIO_ADDR) << 8;
-
- dev_err(v3d->dev, "MMU error from client %d at 0x%08llx%s%s%s\n",
- axi_id, (long long)vio_addr,
+ u64 vio_addr = ((u64)V3D_READ(V3D_MMU_VIO_ADDR) <<
+ (v3d->va_width - 32));
+ static const char *const v3d41_axi_ids[] = {
+ "L2T",
+ "PTB",
+ "PSE",
+ "TLB",
+ "CLE",
+ "TFU",
+ "MMU",
+ "GMP",
+ };
+ const char *client = "?";
+
+ V3D_WRITE(V3D_MMU_CTL,
+ V3D_READ(V3D_MMU_CTL) & (V3D_MMU_CTL_CAP_EXCEEDED |
+ V3D_MMU_CTL_PT_INVALID |
+ V3D_MMU_CTL_WRITE_VIOLATION));
+
+ if (v3d->ver >= 41) {
+ axi_id = axi_id >> 5;
+ if (axi_id < ARRAY_SIZE(v3d41_axi_ids))
+ client = v3d41_axi_ids[axi_id];
+ }
+
+ dev_err(v3d->dev, "MMU error from client %s (%d) at 0x%llx%s%s%s\n",
+ client, axi_id, (long long)vio_addr,
((intsts & V3D_HUB_INT_MMU_WRV) ?
", write violation" : ""),
((intsts & V3D_HUB_INT_MMU_PTI) ?
diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c
index 7a21f1787ab1..395e81d97163 100644
--- a/drivers/gpu/drm/v3d/v3d_mmu.c
+++ b/drivers/gpu/drm/v3d/v3d_mmu.c
@@ -69,10 +69,13 @@ int v3d_mmu_set_page_table(struct v3d_dev *v3d)
V3D_WRITE(V3D_MMU_PT_PA_BASE, v3d->pt_paddr >> V3D_MMU_PAGE_SHIFT);
V3D_WRITE(V3D_MMU_CTL,
V3D_MMU_CTL_ENABLE |
- V3D_MMU_CTL_PT_INVALID |
+ V3D_MMU_CTL_PT_INVALID_ENABLE |
V3D_MMU_CTL_PT_INVALID_ABORT |
+ V3D_MMU_CTL_PT_INVALID_INT |
V3D_MMU_CTL_WRITE_VIOLATION_ABORT |
- V3D_MMU_CTL_CAP_EXCEEDED_ABORT);
+ V3D_MMU_CTL_WRITE_VIOLATION_INT |
+ V3D_MMU_CTL_CAP_EXCEEDED_ABORT |
+ V3D_MMU_CTL_CAP_EXCEEDED_INT);
V3D_WRITE(V3D_MMU_ILLEGAL_ADDR,
(v3d->mmu_scratch_paddr >> V3D_MMU_PAGE_SHIFT) |
V3D_MMU_ILLEGAL_ADDR_ENABLE);
diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
index eda1e289976f..9bcb57781d31 100644
--- a/drivers/gpu/drm/v3d/v3d_regs.h
+++ b/drivers/gpu/drm/v3d/v3d_regs.h
@@ -152,7 +152,8 @@
# define V3D_MMU_CTL_PT_INVALID_ABORT BIT(19)
# define V3D_MMU_CTL_PT_INVALID_INT BIT(18)
# define V3D_MMU_CTL_PT_INVALID_EXCEPTION BIT(17)
-# define V3D_MMU_CTL_WRITE_VIOLATION BIT(16)
+# define V3D_MMU_CTL_PT_INVALID_ENABLE BIT(16)
+# define V3D_MMU_CTL_WRITE_VIOLATION BIT(12)
# define V3D_MMU_CTL_WRITE_VIOLATION_ABORT BIT(11)
# define V3D_MMU_CTL_WRITE_VIOLATION_INT BIT(10)
# define V3D_MMU_CTL_WRITE_VIOLATION_EXCEPTION BIT(9)
--
2.20.1

2019-04-19 00:12:44

by Eric Anholt

[permalink] [raw]
Subject: [PATCH 2/4] drm/v3d: Set the correct DMA mask according to the MMU's limits.

On 7278, we've got 40 bits to work with.

Signed-off-by: Eric Anholt <[email protected]>
---
drivers/gpu/drm/v3d/v3d_debugfs.c | 1 +
drivers/gpu/drm/v3d/v3d_drv.c | 6 +++++-
drivers/gpu/drm/v3d/v3d_regs.h | 8 ++++++++
3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c
index 356a8acfa72d..ab652a034959 100644
--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
@@ -30,6 +30,7 @@ static const struct v3d_reg_def v3d_hub_reg_defs[] = {
REGDEF(V3D_MMU_CTL),
REGDEF(V3D_MMU_VIO_ADDR),
REGDEF(V3D_MMU_VIO_ID),
+ REGDEF(V3D_MMU_DEBUG_INFO),
};

static const struct v3d_reg_def v3d_gca_reg_defs[] = {
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index f8d1d2569c1f..7ab36192e6bc 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -472,9 +472,9 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
struct drm_device *drm;
struct v3d_dev *v3d;
int ret;
+ u32 mmu_debug;
u32 ident1;

- dev->coherent_dma_mask = DMA_BIT_MASK(36);

v3d = kzalloc(sizeof(*v3d), GFP_KERNEL);
if (!v3d)
@@ -491,6 +491,10 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
if (ret)
goto dev_free;

+ mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
+ dev->coherent_dma_mask =
+ DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
+
ident1 = V3D_READ(V3D_HUB_IDENT1);
v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +
V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV));
diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
index 9a8ff0ce648e..54c8c4320da0 100644
--- a/drivers/gpu/drm/v3d/v3d_regs.h
+++ b/drivers/gpu/drm/v3d/v3d_regs.h
@@ -191,6 +191,14 @@
/* Address that faulted */
#define V3D_MMU_VIO_ADDR 0x01234

+#define V3D_MMU_DEBUG_INFO 0x01238
+# define V3D_MMU_PA_WIDTH_MASK V3D_MASK(11, 8)
+# define V3D_MMU_PA_WIDTH_SHIFT 8
+# define V3D_MMU_VA_WIDTH_MASK V3D_MASK(7, 4)
+# define V3D_MMU_VA_WIDTH_SHIFT 4
+# define V3D_MMU_VERSION_MASK V3D_MASK(3, 0)
+# define V3D_MMU_VERSION_SHIFT 0
+
/* Per-V3D-core registers */

#define V3D_CTL_IDENT0 0x00000
--
2.20.1

2019-04-19 00:13:56

by Eric Anholt

[permalink] [raw]
Subject: [PATCH 3/4] drm/v3d: Dump V3D error debug registers in debugfs, and one at reset.

Looking at a hang recently, I noticed these registers that might tell
me if something obvious was wrong. They didn't help in this case, but
keep it around for the future.

Signed-off-by: Eric Anholt <[email protected]>
---
drivers/gpu/drm/v3d/v3d_debugfs.c | 5 ++++
drivers/gpu/drm/v3d/v3d_gem.c | 4 +++-
drivers/gpu/drm/v3d/v3d_regs.h | 38 +++++++++++++++++++++++++++++++
3 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c
index ab652a034959..78a78938e81f 100644
--- a/drivers/gpu/drm/v3d/v3d_debugfs.c
+++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
@@ -58,6 +58,11 @@ static const struct v3d_reg_def v3d_core_reg_defs[] = {
REGDEF(V3D_GMP_STATUS),
REGDEF(V3D_GMP_CFG),
REGDEF(V3D_GMP_VIO_ADDR),
+
+ REGDEF(V3D_ERR_FDBGO),
+ REGDEF(V3D_ERR_FDBGB),
+ REGDEF(V3D_ERR_FDBGS),
+ REGDEF(V3D_ERR_STAT),
};

static const struct v3d_reg_def v3d_csd_reg_defs[] = {
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index f736e021467a..27e0f87075d9 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -109,7 +109,9 @@ v3d_reset(struct v3d_dev *v3d)
{
struct drm_device *dev = &v3d->drm;

- DRM_ERROR("Resetting GPU.\n");
+ DRM_DEV_ERROR(dev->dev, "Resetting GPU for hang.\n");
+ DRM_DEV_ERROR(dev->dev, "V3D_ERR_STAT: 0x%08x\n",
+ V3D_CORE_READ(0, V3D_ERR_STAT));
trace_v3d_reset_begin(dev);

/* XXX: only needed for safe powerdown, not reset. */
diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
index 54c8c4320da0..eda1e289976f 100644
--- a/drivers/gpu/drm/v3d/v3d_regs.h
+++ b/drivers/gpu/drm/v3d/v3d_regs.h
@@ -455,4 +455,42 @@
# define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0)
# define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT 0

+#define V3D_ERR_FDBGO 0x00f04
+#define V3D_ERR_FDBGB 0x00f08
+#define V3D_ERR_FDBGR 0x00f0c
+
+#define V3D_ERR_FDBGS 0x00f10
+# define V3D_ERR_FDBGS_INTERPZ_IP_STALL BIT(17)
+# define V3D_ERR_FDBGS_DEPTHO_FIFO_IP_STALL BIT(16)
+# define V3D_ERR_FDBGS_XYNRM_IP_STALL BIT(14)
+# define V3D_ERR_FDBGS_EZREQ_FIFO_OP_VALID BIT(13)
+# define V3D_ERR_FDBGS_QXYF_FIFO_OP_VALID BIT(12)
+# define V3D_ERR_FDBGS_QXYF_FIFO_OP_LAST BIT(11)
+# define V3D_ERR_FDBGS_EZTEST_ANYQVALID BIT(7)
+# define V3D_ERR_FDBGS_EZTEST_PASS BIT(6)
+# define V3D_ERR_FDBGS_EZTEST_QREADY BIT(5)
+# define V3D_ERR_FDBGS_EZTEST_VLF_OKNOVALID BIT(4)
+# define V3D_ERR_FDBGS_EZTEST_QSTALL BIT(3)
+# define V3D_ERR_FDBGS_EZTEST_IP_VLFSTALL BIT(2)
+# define V3D_ERR_FDBGS_EZTEST_IP_PRSTALL BIT(1)
+# define V3D_ERR_FDBGS_EZTEST_IP_QSTALL BIT(0)
+
+#define V3D_ERR_STAT 0x00f20
+# define V3D_ERR_L2CARE BIT(15)
+# define V3D_ERR_VCMBE BIT(14)
+# define V3D_ERR_VCMRE BIT(13)
+# define V3D_ERR_VCDI BIT(12)
+# define V3D_ERR_VCDE BIT(11)
+# define V3D_ERR_VDWE BIT(10)
+# define V3D_ERR_VPMEAS BIT(9)
+# define V3D_ERR_VPMEFNA BIT(8)
+# define V3D_ERR_VPMEWNA BIT(7)
+# define V3D_ERR_VPMERNA BIT(6)
+# define V3D_ERR_VPMERR BIT(5)
+# define V3D_ERR_VPMEWR BIT(4)
+# define V3D_ERR_VPAERRGL BIT(3)
+# define V3D_ERR_VPAEBRGL BIT(2)
+# define V3D_ERR_VPAERGS BIT(1)
+# define V3D_ERR_VPAEABB BIT(0)
+
#endif /* V3D_REGS_H */
--
2.20.1

2019-04-19 19:01:58

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 1/4] drm/v3d: Fix debugfs reads of MMU regs.

Hi,

On Thu, 2019-04-18 at 17:10 -0700, Eric Anholt wrote:
> They're in the hub, not the individual cores.

Although I don't have docs to check, looks sane:

Reviewed-by: Paul Kocialkowski <[email protected]>

Cheers,

Paul

> Signed-off-by: Eric Anholt <[email protected]>
> ---
> drivers/gpu/drm/v3d/v3d_debugfs.c | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c
> index a2dc4262955e..356a8acfa72d 100644
> --- a/drivers/gpu/drm/v3d/v3d_debugfs.c
> +++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
> @@ -26,6 +26,10 @@ static const struct v3d_reg_def v3d_hub_reg_defs[] = {
> REGDEF(V3D_HUB_IDENT3),
> REGDEF(V3D_HUB_INT_STS),
> REGDEF(V3D_HUB_INT_MSK_STS),
> +
> + REGDEF(V3D_MMU_CTL),
> + REGDEF(V3D_MMU_VIO_ADDR),
> + REGDEF(V3D_MMU_VIO_ID),
> };
>
> static const struct v3d_reg_def v3d_gca_reg_defs[] = {
> @@ -50,9 +54,6 @@ static const struct v3d_reg_def v3d_core_reg_defs[] = {
> REGDEF(V3D_PTB_BPCA),
> REGDEF(V3D_PTB_BPCS),
>
> - REGDEF(V3D_MMU_CTL),
> - REGDEF(V3D_MMU_VIO_ADDR),
> -
> REGDEF(V3D_GMP_STATUS),
> REGDEF(V3D_GMP_CFG),
> REGDEF(V3D_GMP_VIO_ADDR),
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


2019-04-19 19:10:07

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 4/4] drm/v3d: Fix and extend MMU error handling.

Hi,

On Thu, 2019-04-18 at 17:10 -0700, Eric Anholt wrote:
> We were setting the wrong flags to enable PTI errors, so we were
> seeing reads to invalid PTEs show up as write errors. Also, we
> weren't turning on the interrupts. The AXI IDs we were dumping
> included the outstanding write number and so they looked basically
> random. And the VIO_ADDR decoding was based on the MMU VA_WIDTH for
> the first platform I worked on and was wrong on others. In short,
> this was a thorough mess from early HW enabling.
>
> Tested on V3D 4.1 and 4.2 with intentional L2T, CLE, PTB, and TLB
> faults.

Didn't check the docs but looks sane too!

Reviewed-by: Paul Kocialkowski <[email protected]>

Cheers,

Paul

> Signed-off-by: Eric Anholt <[email protected]>
> ---
> drivers/gpu/drm/v3d/v3d_drv.c | 1 +
> drivers/gpu/drm/v3d/v3d_drv.h | 2 ++
> drivers/gpu/drm/v3d/v3d_irq.c | 31 +++++++++++++++++++++++++++----
> drivers/gpu/drm/v3d/v3d_mmu.c | 7 +++++--
> drivers/gpu/drm/v3d/v3d_regs.h | 3 ++-
> 5 files changed, 37 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
> index 7ab36192e6bc..9ce2e4ef6c2a 100644
> --- a/drivers/gpu/drm/v3d/v3d_drv.c
> +++ b/drivers/gpu/drm/v3d/v3d_drv.c
> @@ -494,6 +494,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
> mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
> dev->coherent_dma_mask =
> DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
> + v3d->va_width = 30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_VA_WIDTH);
>
> ident1 = V3D_READ(V3D_HUB_IDENT1);
> v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +
> diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
> index 6d31a6a5a08e..64682923018d 100644
> --- a/drivers/gpu/drm/v3d/v3d_drv.h
> +++ b/drivers/gpu/drm/v3d/v3d_drv.h
> @@ -63,6 +63,8 @@ struct v3d_dev {
> */
> void *mmu_scratch;
> dma_addr_t mmu_scratch_paddr;
> + /* virtual address bits from V3D to the MMU. */
> + int va_width;
>
> /* Number of V3D cores. */
> u32 cores;
> diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
> index fac3c542860b..268d8a889ac5 100644
> --- a/drivers/gpu/drm/v3d/v3d_irq.c
> +++ b/drivers/gpu/drm/v3d/v3d_irq.c
> @@ -162,10 +162,33 @@ v3d_hub_irq(int irq, void *arg)
> V3D_HUB_INT_MMU_PTI |
> V3D_HUB_INT_MMU_CAP)) {
> u32 axi_id = V3D_READ(V3D_MMU_VIO_ID);
> - u64 vio_addr = (u64)V3D_READ(V3D_MMU_VIO_ADDR) << 8;
> -
> - dev_err(v3d->dev, "MMU error from client %d at 0x%08llx%s%s%s\n",
> - axi_id, (long long)vio_addr,
> + u64 vio_addr = ((u64)V3D_READ(V3D_MMU_VIO_ADDR) <<
> + (v3d->va_width - 32));
> + static const char *const v3d41_axi_ids[] = {
> + "L2T",
> + "PTB",
> + "PSE",
> + "TLB",
> + "CLE",
> + "TFU",
> + "MMU",
> + "GMP",
> + };
> + const char *client = "?";
> +
> + V3D_WRITE(V3D_MMU_CTL,
> + V3D_READ(V3D_MMU_CTL) & (V3D_MMU_CTL_CAP_EXCEEDED |
> + V3D_MMU_CTL_PT_INVALID |
> + V3D_MMU_CTL_WRITE_VIOLATION));
> +
> + if (v3d->ver >= 41) {
> + axi_id = axi_id >> 5;
> + if (axi_id < ARRAY_SIZE(v3d41_axi_ids))
> + client = v3d41_axi_ids[axi_id];
> + }
> +
> + dev_err(v3d->dev, "MMU error from client %s (%d) at 0x%llx%s%s%s\n",
> + client, axi_id, (long long)vio_addr,
> ((intsts & V3D_HUB_INT_MMU_WRV) ?
> ", write violation" : ""),
> ((intsts & V3D_HUB_INT_MMU_PTI) ?
> diff --git a/drivers/gpu/drm/v3d/v3d_mmu.c b/drivers/gpu/drm/v3d/v3d_mmu.c
> index 7a21f1787ab1..395e81d97163 100644
> --- a/drivers/gpu/drm/v3d/v3d_mmu.c
> +++ b/drivers/gpu/drm/v3d/v3d_mmu.c
> @@ -69,10 +69,13 @@ int v3d_mmu_set_page_table(struct v3d_dev *v3d)
> V3D_WRITE(V3D_MMU_PT_PA_BASE, v3d->pt_paddr >> V3D_MMU_PAGE_SHIFT);
> V3D_WRITE(V3D_MMU_CTL,
> V3D_MMU_CTL_ENABLE |
> - V3D_MMU_CTL_PT_INVALID |
> + V3D_MMU_CTL_PT_INVALID_ENABLE |
> V3D_MMU_CTL_PT_INVALID_ABORT |
> + V3D_MMU_CTL_PT_INVALID_INT |
> V3D_MMU_CTL_WRITE_VIOLATION_ABORT |
> - V3D_MMU_CTL_CAP_EXCEEDED_ABORT);
> + V3D_MMU_CTL_WRITE_VIOLATION_INT |
> + V3D_MMU_CTL_CAP_EXCEEDED_ABORT |
> + V3D_MMU_CTL_CAP_EXCEEDED_INT);
> V3D_WRITE(V3D_MMU_ILLEGAL_ADDR,
> (v3d->mmu_scratch_paddr >> V3D_MMU_PAGE_SHIFT) |
> V3D_MMU_ILLEGAL_ADDR_ENABLE);
> diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
> index eda1e289976f..9bcb57781d31 100644
> --- a/drivers/gpu/drm/v3d/v3d_regs.h
> +++ b/drivers/gpu/drm/v3d/v3d_regs.h
> @@ -152,7 +152,8 @@
> # define V3D_MMU_CTL_PT_INVALID_ABORT BIT(19)
> # define V3D_MMU_CTL_PT_INVALID_INT BIT(18)
> # define V3D_MMU_CTL_PT_INVALID_EXCEPTION BIT(17)
> -# define V3D_MMU_CTL_WRITE_VIOLATION BIT(16)
> +# define V3D_MMU_CTL_PT_INVALID_ENABLE BIT(16)
> +# define V3D_MMU_CTL_WRITE_VIOLATION BIT(12)
> # define V3D_MMU_CTL_WRITE_VIOLATION_ABORT BIT(11)
> # define V3D_MMU_CTL_WRITE_VIOLATION_INT BIT(10)
> # define V3D_MMU_CTL_WRITE_VIOLATION_EXCEPTION BIT(9)
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


2019-04-19 19:12:01

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 2/4] drm/v3d: Set the correct DMA mask according to the MMU's limits.

Hi,

On Thu, 2019-04-18 at 17:10 -0700, Eric Anholt wrote:
> On 7278, we've got 40 bits to work with.

Although I don't have docs to check, looks sane:

Reviewed-by: Paul Kocialkowski <[email protected]>

Cheers,

Paul

> Signed-off-by: Eric Anholt <[email protected]>
> ---
> drivers/gpu/drm/v3d/v3d_debugfs.c | 1 +
> drivers/gpu/drm/v3d/v3d_drv.c | 6 +++++-
> drivers/gpu/drm/v3d/v3d_regs.h | 8 ++++++++
> 3 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c
> index 356a8acfa72d..ab652a034959 100644
> --- a/drivers/gpu/drm/v3d/v3d_debugfs.c
> +++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
> @@ -30,6 +30,7 @@ static const struct v3d_reg_def v3d_hub_reg_defs[] = {
> REGDEF(V3D_MMU_CTL),
> REGDEF(V3D_MMU_VIO_ADDR),
> REGDEF(V3D_MMU_VIO_ID),
> + REGDEF(V3D_MMU_DEBUG_INFO),
> };
>
> static const struct v3d_reg_def v3d_gca_reg_defs[] = {
> diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
> index f8d1d2569c1f..7ab36192e6bc 100644
> --- a/drivers/gpu/drm/v3d/v3d_drv.c
> +++ b/drivers/gpu/drm/v3d/v3d_drv.c
> @@ -472,9 +472,9 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
> struct drm_device *drm;
> struct v3d_dev *v3d;
> int ret;
> + u32 mmu_debug;
> u32 ident1;
>
> - dev->coherent_dma_mask = DMA_BIT_MASK(36);
>
> v3d = kzalloc(sizeof(*v3d), GFP_KERNEL);
> if (!v3d)
> @@ -491,6 +491,10 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
> if (ret)
> goto dev_free;
>
> + mmu_debug = V3D_READ(V3D_MMU_DEBUG_INFO);
> + dev->coherent_dma_mask =
> + DMA_BIT_MASK(30 + V3D_GET_FIELD(mmu_debug, V3D_MMU_PA_WIDTH));
> +
> ident1 = V3D_READ(V3D_HUB_IDENT1);
> v3d->ver = (V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_TVER) * 10 +
> V3D_GET_FIELD(ident1, V3D_HUB_IDENT1_REV));
> diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
> index 9a8ff0ce648e..54c8c4320da0 100644
> --- a/drivers/gpu/drm/v3d/v3d_regs.h
> +++ b/drivers/gpu/drm/v3d/v3d_regs.h
> @@ -191,6 +191,14 @@
> /* Address that faulted */
> #define V3D_MMU_VIO_ADDR 0x01234
>
> +#define V3D_MMU_DEBUG_INFO 0x01238
> +# define V3D_MMU_PA_WIDTH_MASK V3D_MASK(11, 8)
> +# define V3D_MMU_PA_WIDTH_SHIFT 8
> +# define V3D_MMU_VA_WIDTH_MASK V3D_MASK(7, 4)
> +# define V3D_MMU_VA_WIDTH_SHIFT 4
> +# define V3D_MMU_VERSION_MASK V3D_MASK(3, 0)
> +# define V3D_MMU_VERSION_SHIFT 0
> +
> /* Per-V3D-core registers */
>
> #define V3D_CTL_IDENT0 0x00000
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com


2019-04-19 20:05:48

by Paul Kocialkowski

[permalink] [raw]
Subject: Re: [PATCH 3/4] drm/v3d: Dump V3D error debug registers in debugfs, and one at reset.

Hi,

On Thu, 2019-04-18 at 17:10 -0700, Eric Anholt wrote:
> Looking at a hang recently, I noticed these registers that might tell
> me if something obvious was wrong. They didn't help in this case, but
> keep it around for the future.

Although I don't have docs to check, looks sane:

Reviewed-by: Paul Kocialkowski <[email protected]>

Cheers,

Paul

> Signed-off-by: Eric Anholt <[email protected]>
> ---
> drivers/gpu/drm/v3d/v3d_debugfs.c | 5 ++++
> drivers/gpu/drm/v3d/v3d_gem.c | 4 +++-
> drivers/gpu/drm/v3d/v3d_regs.h | 38 +++++++++++++++++++++++++++++++
> 3 files changed, 46 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c
> index ab652a034959..78a78938e81f 100644
> --- a/drivers/gpu/drm/v3d/v3d_debugfs.c
> +++ b/drivers/gpu/drm/v3d/v3d_debugfs.c
> @@ -58,6 +58,11 @@ static const struct v3d_reg_def v3d_core_reg_defs[] = {
> REGDEF(V3D_GMP_STATUS),
> REGDEF(V3D_GMP_CFG),
> REGDEF(V3D_GMP_VIO_ADDR),
> +
> + REGDEF(V3D_ERR_FDBGO),
> + REGDEF(V3D_ERR_FDBGB),
> + REGDEF(V3D_ERR_FDBGS),
> + REGDEF(V3D_ERR_STAT),
> };
>
> static const struct v3d_reg_def v3d_csd_reg_defs[] = {
> diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
> index f736e021467a..27e0f87075d9 100644
> --- a/drivers/gpu/drm/v3d/v3d_gem.c
> +++ b/drivers/gpu/drm/v3d/v3d_gem.c
> @@ -109,7 +109,9 @@ v3d_reset(struct v3d_dev *v3d)
> {
> struct drm_device *dev = &v3d->drm;
>
> - DRM_ERROR("Resetting GPU.\n");
> + DRM_DEV_ERROR(dev->dev, "Resetting GPU for hang.\n");
> + DRM_DEV_ERROR(dev->dev, "V3D_ERR_STAT: 0x%08x\n",
> + V3D_CORE_READ(0, V3D_ERR_STAT));
> trace_v3d_reset_begin(dev);
>
> /* XXX: only needed for safe powerdown, not reset. */
> diff --git a/drivers/gpu/drm/v3d/v3d_regs.h b/drivers/gpu/drm/v3d/v3d_regs.h
> index 54c8c4320da0..eda1e289976f 100644
> --- a/drivers/gpu/drm/v3d/v3d_regs.h
> +++ b/drivers/gpu/drm/v3d/v3d_regs.h
> @@ -455,4 +455,42 @@
> # define V3D_CSD_CURRENT_ID0_WG_Y_MASK V3D_MASK(15, 0)
> # define V3D_CSD_CURRENT_ID0_WG_Y_SHIFT 0
>
> +#define V3D_ERR_FDBGO 0x00f04
> +#define V3D_ERR_FDBGB 0x00f08
> +#define V3D_ERR_FDBGR 0x00f0c
> +
> +#define V3D_ERR_FDBGS 0x00f10
> +# define V3D_ERR_FDBGS_INTERPZ_IP_STALL BIT(17)
> +# define V3D_ERR_FDBGS_DEPTHO_FIFO_IP_STALL BIT(16)
> +# define V3D_ERR_FDBGS_XYNRM_IP_STALL BIT(14)
> +# define V3D_ERR_FDBGS_EZREQ_FIFO_OP_VALID BIT(13)
> +# define V3D_ERR_FDBGS_QXYF_FIFO_OP_VALID BIT(12)
> +# define V3D_ERR_FDBGS_QXYF_FIFO_OP_LAST BIT(11)
> +# define V3D_ERR_FDBGS_EZTEST_ANYQVALID BIT(7)
> +# define V3D_ERR_FDBGS_EZTEST_PASS BIT(6)
> +# define V3D_ERR_FDBGS_EZTEST_QREADY BIT(5)
> +# define V3D_ERR_FDBGS_EZTEST_VLF_OKNOVALID BIT(4)
> +# define V3D_ERR_FDBGS_EZTEST_QSTALL BIT(3)
> +# define V3D_ERR_FDBGS_EZTEST_IP_VLFSTALL BIT(2)
> +# define V3D_ERR_FDBGS_EZTEST_IP_PRSTALL BIT(1)
> +# define V3D_ERR_FDBGS_EZTEST_IP_QSTALL BIT(0)
> +
> +#define V3D_ERR_STAT 0x00f20
> +# define V3D_ERR_L2CARE BIT(15)
> +# define V3D_ERR_VCMBE BIT(14)
> +# define V3D_ERR_VCMRE BIT(13)
> +# define V3D_ERR_VCDI BIT(12)
> +# define V3D_ERR_VCDE BIT(11)
> +# define V3D_ERR_VDWE BIT(10)
> +# define V3D_ERR_VPMEAS BIT(9)
> +# define V3D_ERR_VPMEFNA BIT(8)
> +# define V3D_ERR_VPMEWNA BIT(7)
> +# define V3D_ERR_VPMERNA BIT(6)
> +# define V3D_ERR_VPMERR BIT(5)
> +# define V3D_ERR_VPMEWR BIT(4)
> +# define V3D_ERR_VPAERRGL BIT(3)
> +# define V3D_ERR_VPAEBRGL BIT(2)
> +# define V3D_ERR_VPAERGS BIT(1)
> +# define V3D_ERR_VPAEABB BIT(0)
> +
> #endif /* V3D_REGS_H */
--
Paul Kocialkowski, Bootlin
Embedded Linux and kernel engineering
https://bootlin.com