diff options
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/priv_ring_gp10b.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/priv_ring_gp10b.c b/drivers/gpu/nvgpu/gp10b/priv_ring_gp10b.c index 1a282a10..b780457f 100644 --- a/drivers/gpu/nvgpu/gp10b/priv_ring_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/priv_ring_gp10b.c | |||
@@ -39,10 +39,12 @@ void gp10b_priv_ring_isr(struct gk20a *g) | |||
39 | u32 cmd; | 39 | u32 cmd; |
40 | s32 retry = 100; | 40 | s32 retry = 100; |
41 | u32 gpc; | 41 | u32 gpc; |
42 | u32 gpc_stride = nvgpu_get_litter_value(g, GPU_LIT_GPC_STRIDE); | 42 | u32 gpc_stride, offset; |
43 | 43 | ||
44 | if (nvgpu_is_enabled(g, NVGPU_IS_FMODEL)) | 44 | if (nvgpu_is_enabled(g, NVGPU_IS_FMODEL)) { |
45 | nvgpu_info(g, "unhandled priv ring intr"); | ||
45 | return; | 46 | return; |
47 | } | ||
46 | 48 | ||
47 | status0 = gk20a_readl(g, pri_ringmaster_intr_status0_r()); | 49 | status0 = gk20a_readl(g, pri_ringmaster_intr_status0_r()); |
48 | status1 = gk20a_readl(g, pri_ringmaster_intr_status1_r()); | 50 | status1 = gk20a_readl(g, pri_ringmaster_intr_status1_r()); |
@@ -50,6 +52,16 @@ void gp10b_priv_ring_isr(struct gk20a *g) | |||
50 | nvgpu_err(g, "ringmaster intr status0: 0x%08x," | 52 | nvgpu_err(g, "ringmaster intr status0: 0x%08x," |
51 | "status1: 0x%08x", status0, status1); | 53 | "status1: 0x%08x", status0, status1); |
52 | 54 | ||
55 | if (pri_ringmaster_intr_status0_ring_start_conn_fault_v(status0) != 0) | ||
56 | nvgpu_err(g, | ||
57 | "BUG: connectivity problem on the startup sequence"); | ||
58 | |||
59 | if (pri_ringmaster_intr_status0_disconnect_fault_v(status0) != 0) | ||
60 | nvgpu_err(g, "ring disconnected"); | ||
61 | |||
62 | if (pri_ringmaster_intr_status0_overflow_fault_v(status0) != 0) | ||
63 | nvgpu_err(g, "ring overflowed"); | ||
64 | |||
53 | if (pri_ringmaster_intr_status0_gbl_write_error_sys_v(status0) != 0) { | 65 | if (pri_ringmaster_intr_status0_gbl_write_error_sys_v(status0) != 0) { |
54 | nvgpu_err(g, "SYS write error. ADR %08x WRDAT %08x INFO %08x, CODE %08x", | 66 | nvgpu_err(g, "SYS write error. ADR %08x WRDAT %08x INFO %08x, CODE %08x", |
55 | gk20a_readl(g, pri_ringstation_sys_priv_error_adr_r()), | 67 | gk20a_readl(g, pri_ringstation_sys_priv_error_adr_r()), |
@@ -58,27 +70,43 @@ void gp10b_priv_ring_isr(struct gk20a *g) | |||
58 | gk20a_readl(g, pri_ringstation_sys_priv_error_code_r())); | 70 | gk20a_readl(g, pri_ringstation_sys_priv_error_code_r())); |
59 | } | 71 | } |
60 | 72 | ||
61 | for (gpc = 0; gpc < g->gr.gpc_count; gpc++) { | 73 | if (status1) { |
62 | if (status1 & BIT(gpc)) { | 74 | gpc_stride = nvgpu_get_litter_value(g, GPU_LIT_GPC_STRIDE); |
63 | nvgpu_err(g, "GPC%u write error. ADR %08x WRDAT %08x INFO %08x, CODE %08x", gpc, | 75 | for (gpc = 0; gpc < g->gr.gpc_count; gpc++) { |
64 | gk20a_readl(g, pri_ringstation_gpc_gpc0_priv_error_adr_r() + gpc * gpc_stride), | 76 | offset = gpc * gpc_stride; |
65 | gk20a_readl(g, pri_ringstation_gpc_gpc0_priv_error_wrdat_r() + gpc * gpc_stride), | 77 | if (status1 & BIT(gpc)) { |
66 | gk20a_readl(g, pri_ringstation_gpc_gpc0_priv_error_info_r() + gpc * gpc_stride), | 78 | nvgpu_err(g, "GPC%u write error. ADR %08x " |
67 | gk20a_readl(g, pri_ringstation_gpc_gpc0_priv_error_code_r() + gpc * gpc_stride)); | 79 | "WRDAT %08x INFO %08x, CODE %08x", gpc, |
80 | gk20a_readl(g, | ||
81 | pri_ringstation_gpc_gpc0_priv_error_adr_r() + offset), | ||
82 | gk20a_readl(g, | ||
83 | pri_ringstation_gpc_gpc0_priv_error_wrdat_r() + offset), | ||
84 | gk20a_readl(g, | ||
85 | pri_ringstation_gpc_gpc0_priv_error_info_r() + offset), | ||
86 | gk20a_readl(g, | ||
87 | pri_ringstation_gpc_gpc0_priv_error_code_r() + offset)); | ||
88 | status1 = status1 & (~(BIT(gpc))); | ||
89 | if (!status1) | ||
90 | break; | ||
91 | } | ||
68 | } | 92 | } |
69 | } | 93 | } |
70 | 94 | /* clear interrupt */ | |
71 | cmd = gk20a_readl(g, pri_ringmaster_command_r()); | 95 | cmd = gk20a_readl(g, pri_ringmaster_command_r()); |
72 | cmd = set_field(cmd, pri_ringmaster_command_cmd_m(), | 96 | cmd = set_field(cmd, pri_ringmaster_command_cmd_m(), |
73 | pri_ringmaster_command_cmd_ack_interrupt_f()); | 97 | pri_ringmaster_command_cmd_ack_interrupt_f()); |
74 | gk20a_writel(g, pri_ringmaster_command_r(), cmd); | 98 | gk20a_writel(g, pri_ringmaster_command_r(), cmd); |
75 | 99 | ||
76 | do { | 100 | /* poll for clear interrupt done */ |
101 | cmd = pri_ringmaster_command_cmd_v( | ||
102 | gk20a_readl(g, pri_ringmaster_command_r())); | ||
103 | while (cmd != pri_ringmaster_command_cmd_no_cmd_v() && retry) { | ||
104 | nvgpu_udelay(20); | ||
77 | cmd = pri_ringmaster_command_cmd_v( | 105 | cmd = pri_ringmaster_command_cmd_v( |
78 | gk20a_readl(g, pri_ringmaster_command_r())); | 106 | gk20a_readl(g, pri_ringmaster_command_r())); |
79 | nvgpu_usleep_range(20, 40); | 107 | retry--; |
80 | } while (cmd != pri_ringmaster_command_cmd_no_cmd_v() && --retry); | 108 | } |
81 | 109 | ||
82 | if (retry <= 0) | 110 | if (retry == 0) |
83 | nvgpu_warn(g, "priv ringmaster cmd ack too many retries"); | 111 | nvgpu_err(g, "priv ringmaster intr ack failed"); |
84 | } | 112 | } |