summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2014-04-09 08:22:49 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:09:42 -0400
commit07a90307b09ee44701ed54af21fd234eba029986 (patch)
tree4201704dac76af2be886966392e5a69ab3b067f4 /drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
parent8a81389e6ff9350c991f0481fc2f062bc6594e0e (diff)
gpu: nvgpu: Implement gm20b fifo recovery
Implement gm20b version of fifo recovery. Bug 1495967 Change-Id: I2792b217178d157427f49e0c450d4ac620399962 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/394138 Reviewed-on: http://git-master/r/401402 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gm20b/fifo_gm20b.c')
-rw-r--r--drivers/gpu/nvgpu/gm20b/fifo_gm20b.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
index 83dc0f79..7e580136 100644
--- a/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/fifo_gm20b.c
@@ -13,10 +13,12 @@
13 * more details. 13 * more details.
14 */ 14 */
15 15
16#include <linux/delay.h>
16#include "gk20a/gk20a.h" 17#include "gk20a/gk20a.h"
17#include "fifo_gm20b.h" 18#include "fifo_gm20b.h"
18#include "hw_ccsr_gm20b.h" 19#include "hw_ccsr_gm20b.h"
19#include "hw_ram_gm20b.h" 20#include "hw_ram_gm20b.h"
21#include "hw_fifo_gm20b.h"
20 22
21static void channel_gm20b_bind(struct channel_gk20a *ch_gk20a) 23static void channel_gm20b_bind(struct channel_gk20a *ch_gk20a)
22{ 24{
@@ -41,7 +43,64 @@ static void channel_gm20b_bind(struct channel_gk20a *ch_gk20a)
41 ccsr_channel_enable_set_true_f()); 43 ccsr_channel_enable_set_true_f());
42} 44}
43 45
46static inline u32 gm20b_engine_id_to_mmu_id(u32 engine_id)
47{
48 switch (engine_id) {
49 case ENGINE_GR_GK20A:
50 return 0;
51 case ENGINE_CE2_GK20A:
52 return 1;
53 default:
54 return ~0;
55 }
56}
57
58static void gm20b_fifo_trigger_mmu_fault(struct gk20a *g,
59 unsigned long engine_ids)
60{
61 unsigned long end_jiffies = jiffies +
62 msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
63 unsigned long delay = GR_IDLE_CHECK_DEFAULT;
64 unsigned long engine_id;
65 int ret = -EBUSY;
66
67 /* trigger faults for all bad engines */
68 for_each_set_bit(engine_id, &engine_ids, 32) {
69 u32 engine_mmu_id;
70
71 if (engine_id > g->fifo.max_engines) {
72 gk20a_err(dev_from_gk20a(g),
73 "faulting unknown engine %ld", engine_id);
74 } else {
75 engine_mmu_id = gm20b_engine_id_to_mmu_id(engine_id);
76 gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_mmu_id),
77 fifo_trigger_mmu_fault_enable_f(1));
78 }
79 }
80
81 /* Wait for MMU fault to trigger */
82 do {
83 if (gk20a_readl(g, fifo_intr_0_r()) &
84 fifo_intr_0_mmu_fault_pending_f()) {
85 ret = 0;
86 break;
87 }
88
89 usleep_range(delay, delay * 2);
90 delay = min_t(u32, delay << 1, GR_IDLE_CHECK_MAX);
91 } while (time_before(jiffies, end_jiffies) ||
92 !tegra_platform_is_silicon());
93
94 if (ret)
95 gk20a_err(dev_from_gk20a(g), "mmu fault timeout");
96
97 /* release mmu fault trigger */
98 for_each_set_bit(engine_id, &engine_ids, 32)
99 gk20a_writel(g, fifo_trigger_mmu_fault_r(engine_id), 0);
100}
101
44void gm20b_init_fifo(struct gpu_ops *gops) 102void gm20b_init_fifo(struct gpu_ops *gops)
45{ 103{
46 gops->fifo.bind_channel = channel_gm20b_bind; 104 gops->fifo.bind_channel = channel_gm20b_bind;
105 gops->fifo.trigger_mmu_fault = gm20b_fifo_trigger_mmu_fault;
47} 106}