diff options
author | Deepak Nibade <dnibade@nvidia.com> | 2015-09-24 05:26:44 -0400 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2015-10-16 11:23:49 -0400 |
commit | 68099f8298d25e94579f7d45c61b959f2c7ac184 (patch) | |
tree | 9f5b75f3d8c28f3110bb3177c7ad69156bf96386 /drivers/gpu/nvgpu | |
parent | 5b7b59714a6f6ea34295e4827eca68f496f5df18 (diff) |
gpu: nvgpu: fix pbdma intr handling
To handle any of the pbdma interrupt, we currently write zero
to pbdma_method0 and then clear the interrupt
But this is insufficient since we cannot use same intr clear
method for all the interrupts
Hence, add intr specific routines to handle those interrupts
NV_PPBDMA_INTR_0_PBENTRY:
- fix the pb_header to have a null opcode
- fix the pbdma_method to have a valid nop
NV_PPBDMA_INTR_0_METHOD:
- fix the pbdma_method to have a valid nop
NV_PPBDMA_INTR_0_DEVICE:
- fix the pb_header to have a null opcode
- go through all pbdma_method0/1/2/3
-- if they contain host s/w methods, replace those
methods with a valid NOP
Bug 200134238
Change-Id: I10c284a6cdc1441f9d437cea65aae00d3c33a8c8
Signed-off-by: Deepak Nibade <dnibade@nvidia.com>
Reviewed-on: http://git-master/r/814561
Reviewed-by: Automatic_Commit_Validation_User
GVS: Gerrit_Virtual_Submit
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 81 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h | 38 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h | 42 |
3 files changed, 156 insertions, 5 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index 4f3363f2..ad7162fc 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -1561,6 +1561,54 @@ static u32 fifo_error_isr(struct gk20a *g, u32 fifo_intr) | |||
1561 | return handled; | 1561 | return handled; |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | static inline void gk20a_fifo_reset_pbdma_header(struct gk20a *g, int pbdma_id) | ||
1565 | { | ||
1566 | gk20a_writel(g, pbdma_pb_header_r(pbdma_id), | ||
1567 | pbdma_pb_header_first_true_f() | | ||
1568 | pbdma_pb_header_type_non_inc_f()); | ||
1569 | } | ||
1570 | |||
1571 | static inline void gk20a_fifo_reset_pbdma_method(struct gk20a *g, int pbdma_id, | ||
1572 | int pbdma_method_index) | ||
1573 | { | ||
1574 | u32 pbdma_method_stride; | ||
1575 | u32 pbdma_method_reg; | ||
1576 | |||
1577 | pbdma_method_stride = pbdma_method1_r(pbdma_id) - | ||
1578 | pbdma_method0_r(pbdma_id); | ||
1579 | |||
1580 | pbdma_method_reg = pbdma_method0_r(pbdma_id) + | ||
1581 | (pbdma_method_index * pbdma_method_stride); | ||
1582 | |||
1583 | gk20a_writel(g, pbdma_method_reg, | ||
1584 | pbdma_method0_valid_true_f() | | ||
1585 | pbdma_method0_first_true_f() | | ||
1586 | pbdma_method0_addr_f( | ||
1587 | pbdma_udma_nop_r() >> 2)); | ||
1588 | } | ||
1589 | |||
1590 | static bool gk20a_fifo_is_sw_method_subch(struct gk20a *g, int pbdma_id, | ||
1591 | int pbdma_method_index) | ||
1592 | { | ||
1593 | u32 pbdma_method_stride; | ||
1594 | u32 pbdma_method_reg, pbdma_method_subch; | ||
1595 | |||
1596 | pbdma_method_stride = pbdma_method1_r(pbdma_id) - | ||
1597 | pbdma_method0_r(pbdma_id); | ||
1598 | |||
1599 | pbdma_method_reg = pbdma_method0_r(pbdma_id) + | ||
1600 | (pbdma_method_index * pbdma_method_stride); | ||
1601 | |||
1602 | pbdma_method_subch = pbdma_method0_subch_v( | ||
1603 | gk20a_readl(g, pbdma_method_reg)); | ||
1604 | |||
1605 | if (pbdma_method_subch == 5 || pbdma_method_subch == 6 || | ||
1606 | pbdma_method_subch == 7) | ||
1607 | return true; | ||
1608 | |||
1609 | return false; | ||
1610 | } | ||
1611 | |||
1564 | static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | 1612 | static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, |
1565 | struct gk20a *g, | 1613 | struct gk20a *g, |
1566 | struct fifo_gk20a *f, | 1614 | struct fifo_gk20a *f, |
@@ -1570,6 +1618,7 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | |||
1570 | u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id)); | 1618 | u32 pbdma_intr_1 = gk20a_readl(g, pbdma_intr_1_r(pbdma_id)); |
1571 | u32 handled = 0; | 1619 | u32 handled = 0; |
1572 | bool reset = false; | 1620 | bool reset = false; |
1621 | int i; | ||
1573 | 1622 | ||
1574 | gk20a_dbg_fn(""); | 1623 | gk20a_dbg_fn(""); |
1575 | 1624 | ||
@@ -1580,11 +1629,15 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | |||
1580 | f->intr.pbdma.channel_fatal_0 | | 1629 | f->intr.pbdma.channel_fatal_0 | |
1581 | f->intr.pbdma.restartable_0) & pbdma_intr_0) { | 1630 | f->intr.pbdma.restartable_0) & pbdma_intr_0) { |
1582 | gk20a_err(dev_from_gk20a(g), | 1631 | gk20a_err(dev_from_gk20a(g), |
1583 | "pbdma_intr_0(%d):0x%08x PBH: %08x SHADOW: %08x M0: %08x", | 1632 | "pbdma_intr_0(%d):0x%08x PBH: %08x SHADOW: %08x M0: %08x %08x %08x %08x", |
1584 | pbdma_id, pbdma_intr_0, | 1633 | pbdma_id, pbdma_intr_0, |
1585 | gk20a_readl(g, pbdma_pb_header_r(pbdma_id)), | 1634 | gk20a_readl(g, pbdma_pb_header_r(pbdma_id)), |
1586 | gk20a_readl(g, pbdma_hdr_shadow_r(pbdma_id)), | 1635 | gk20a_readl(g, pbdma_hdr_shadow_r(pbdma_id)), |
1587 | gk20a_readl(g, pbdma_method0_r(pbdma_id))); | 1636 | gk20a_readl(g, pbdma_method0_r(pbdma_id)), |
1637 | gk20a_readl(g, pbdma_method1_r(pbdma_id)), | ||
1638 | gk20a_readl(g, pbdma_method2_r(pbdma_id)), | ||
1639 | gk20a_readl(g, pbdma_method3_r(pbdma_id)) | ||
1640 | ); | ||
1588 | reset = true; | 1641 | reset = true; |
1589 | handled |= ((f->intr.pbdma.device_fatal_0 | | 1642 | handled |= ((f->intr.pbdma.device_fatal_0 | |
1590 | f->intr.pbdma.channel_fatal_0 | | 1643 | f->intr.pbdma.channel_fatal_0 | |
@@ -1592,7 +1645,29 @@ static u32 gk20a_fifo_handle_pbdma_intr(struct device *dev, | |||
1592 | pbdma_intr_0); | 1645 | pbdma_intr_0); |
1593 | } | 1646 | } |
1594 | 1647 | ||
1595 | gk20a_writel(g, pbdma_method0_r(pbdma_id), 0); | 1648 | if (pbdma_intr_0 & pbdma_intr_0_pbentry_pending_f()) { |
1649 | gk20a_fifo_reset_pbdma_header(g, pbdma_id); | ||
1650 | gk20a_fifo_reset_pbdma_method(g, pbdma_id, 0); | ||
1651 | reset = true; | ||
1652 | } | ||
1653 | |||
1654 | if (pbdma_intr_0 & pbdma_intr_0_method_pending_f()) { | ||
1655 | gk20a_fifo_reset_pbdma_method(g, pbdma_id, 0); | ||
1656 | reset = true; | ||
1657 | } | ||
1658 | |||
1659 | if (pbdma_intr_0 & pbdma_intr_0_device_pending_f()) { | ||
1660 | gk20a_fifo_reset_pbdma_header(g, pbdma_id); | ||
1661 | |||
1662 | for (i = 0; i < 4; i++) { | ||
1663 | if (gk20a_fifo_is_sw_method_subch(g, | ||
1664 | pbdma_id, i)) | ||
1665 | gk20a_fifo_reset_pbdma_method(g, | ||
1666 | pbdma_id, i); | ||
1667 | } | ||
1668 | reset = true; | ||
1669 | } | ||
1670 | |||
1596 | gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0); | 1671 | gk20a_writel(g, pbdma_intr_0_r(pbdma_id), pbdma_intr_0); |
1597 | } | 1672 | } |
1598 | 1673 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h b/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h index e124e17f..e83dbb5c 100644 --- a/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/hw_pbdma_gk20a.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012-2014, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2012-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
@@ -190,6 +190,10 @@ static inline u32 pbdma_pb_header_type_inc_f(void) | |||
190 | { | 190 | { |
191 | return 0x20000000; | 191 | return 0x20000000; |
192 | } | 192 | } |
193 | static inline u32 pbdma_pb_header_type_non_inc_f(void) | ||
194 | { | ||
195 | return 0x60000000; | ||
196 | } | ||
193 | static inline u32 pbdma_hdr_shadow_r(u32 i) | 197 | static inline u32 pbdma_hdr_shadow_r(u32 i) |
194 | { | 198 | { |
195 | return 0x00040118 + i*8192; | 199 | return 0x00040118 + i*8192; |
@@ -214,6 +218,38 @@ static inline u32 pbdma_method0_r(u32 i) | |||
214 | { | 218 | { |
215 | return 0x000400c0 + i*8192; | 219 | return 0x000400c0 + i*8192; |
216 | } | 220 | } |
221 | static inline u32 pbdma_method0_addr_f(u32 v) | ||
222 | { | ||
223 | return (v & 0xfff) << 2; | ||
224 | } | ||
225 | static inline u32 pbdma_method0_addr_v(u32 r) | ||
226 | { | ||
227 | return (r >> 2) & 0xfff; | ||
228 | } | ||
229 | static inline u32 pbdma_method0_subch_v(u32 r) | ||
230 | { | ||
231 | return (r >> 16) & 0x7; | ||
232 | } | ||
233 | static inline u32 pbdma_method0_first_true_f(void) | ||
234 | { | ||
235 | return 0x400000; | ||
236 | } | ||
237 | static inline u32 pbdma_method0_valid_true_f(void) | ||
238 | { | ||
239 | return 0x80000000; | ||
240 | } | ||
241 | static inline u32 pbdma_method1_r(u32 i) | ||
242 | { | ||
243 | return 0x000400c8 + i*8192; | ||
244 | } | ||
245 | static inline u32 pbdma_method2_r(u32 i) | ||
246 | { | ||
247 | return 0x000400d0 + i*8192; | ||
248 | } | ||
249 | static inline u32 pbdma_method3_r(u32 i) | ||
250 | { | ||
251 | return 0x000400d8 + i*8192; | ||
252 | } | ||
217 | static inline u32 pbdma_data0_r(u32 i) | 253 | static inline u32 pbdma_data0_r(u32 i) |
218 | { | 254 | { |
219 | return 0x000400c4 + i*8192; | 255 | return 0x000400c4 + i*8192; |
diff --git a/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h b/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h index 7b25d4af..c03a377a 100644 --- a/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h +++ b/drivers/gpu/nvgpu/gm20b/hw_pbdma_gm20b.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
@@ -174,6 +174,10 @@ static inline u32 pbdma_pb_header_type_inc_f(void) | |||
174 | { | 174 | { |
175 | return 0x20000000; | 175 | return 0x20000000; |
176 | } | 176 | } |
177 | static inline u32 pbdma_pb_header_type_non_inc_f(void) | ||
178 | { | ||
179 | return 0x60000000; | ||
180 | } | ||
177 | static inline u32 pbdma_hdr_shadow_r(u32 i) | 181 | static inline u32 pbdma_hdr_shadow_r(u32 i) |
178 | { | 182 | { |
179 | return 0x00040118 + i*8192; | 183 | return 0x00040118 + i*8192; |
@@ -198,6 +202,42 @@ static inline u32 pbdma_method0_r(u32 i) | |||
198 | { | 202 | { |
199 | return 0x000400c0 + i*8192; | 203 | return 0x000400c0 + i*8192; |
200 | } | 204 | } |
205 | static inline u32 pbdma_method0_fifo_size_v(void) | ||
206 | { | ||
207 | return 0x00000004; | ||
208 | } | ||
209 | static inline u32 pbdma_method0_addr_f(u32 v) | ||
210 | { | ||
211 | return (v & 0xfff) << 2; | ||
212 | } | ||
213 | static inline u32 pbdma_method0_addr_v(u32 r) | ||
214 | { | ||
215 | return (r >> 2) & 0xfff; | ||
216 | } | ||
217 | static inline u32 pbdma_method0_subch_v(u32 r) | ||
218 | { | ||
219 | return (r >> 16) & 0x7; | ||
220 | } | ||
221 | static inline u32 pbdma_method0_first_true_f(void) | ||
222 | { | ||
223 | return 0x400000; | ||
224 | } | ||
225 | static inline u32 pbdma_method0_valid_true_f(void) | ||
226 | { | ||
227 | return 0x80000000; | ||
228 | } | ||
229 | static inline u32 pbdma_method1_r(u32 i) | ||
230 | { | ||
231 | return 0x000400c8 + i*8192; | ||
232 | } | ||
233 | static inline u32 pbdma_method2_r(u32 i) | ||
234 | { | ||
235 | return 0x000400d0 + i*8192; | ||
236 | } | ||
237 | static inline u32 pbdma_method3_r(u32 i) | ||
238 | { | ||
239 | return 0x000400d8 + i*8192; | ||
240 | } | ||
201 | static inline u32 pbdma_data0_r(u32 i) | 241 | static inline u32 pbdma_data0_r(u32 i) |
202 | { | 242 | { |
203 | return 0x000400c4 + i*8192; | 243 | return 0x000400c4 + i*8192; |