diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gp10b')
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/ce_gp10b.c | 19 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/mc_gp10b.c | 72 |
2 files changed, 34 insertions, 57 deletions
diff --git a/drivers/gpu/nvgpu/gp10b/ce_gp10b.c b/drivers/gpu/nvgpu/gp10b/ce_gp10b.c index f19a4b0f..169309fa 100644 --- a/drivers/gpu/nvgpu/gp10b/ce_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/ce_gp10b.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Pascal GPU series Copy Engine. | 2 | * Pascal GPU series Copy Engine. |
3 | * | 3 | * |
4 | * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2011-2017, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
@@ -22,15 +22,6 @@ | |||
22 | 22 | ||
23 | #include <nvgpu/hw/gp10b/hw_ce_gp10b.h> | 23 | #include <nvgpu/hw/gp10b/hw_ce_gp10b.h> |
24 | 24 | ||
25 | static void ce_nonblockpipe_isr(struct gk20a *g, u32 fifo_intr) | ||
26 | { | ||
27 | gk20a_dbg(gpu_dbg_intr, "ce non-blocking pipe interrupt\n"); | ||
28 | |||
29 | /* wake theads waiting in this channel */ | ||
30 | gk20a_channel_semaphore_wakeup(g, true); | ||
31 | return; | ||
32 | } | ||
33 | |||
34 | static u32 ce_blockpipe_isr(struct gk20a *g, u32 fifo_intr) | 25 | static u32 ce_blockpipe_isr(struct gk20a *g, u32 fifo_intr) |
35 | { | 26 | { |
36 | gk20a_dbg(gpu_dbg_intr, "ce blocking pipe interrupt\n"); | 27 | gk20a_dbg(gpu_dbg_intr, "ce blocking pipe interrupt\n"); |
@@ -63,8 +54,9 @@ static void gp10b_ce_isr(struct gk20a *g, u32 inst_id, u32 pri_base) | |||
63 | return; | 54 | return; |
64 | } | 55 | } |
65 | 56 | ||
66 | static void gp10b_ce_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base) | 57 | static int gp10b_ce_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base) |
67 | { | 58 | { |
59 | int ops = 0; | ||
68 | u32 ce_intr = gk20a_readl(g, ce_intr_status_r(inst_id)); | 60 | u32 ce_intr = gk20a_readl(g, ce_intr_status_r(inst_id)); |
69 | 61 | ||
70 | gk20a_dbg(gpu_dbg_intr, "ce nonstall isr %08x %08x\n", ce_intr, inst_id); | 62 | gk20a_dbg(gpu_dbg_intr, "ce nonstall isr %08x %08x\n", ce_intr, inst_id); |
@@ -72,10 +64,11 @@ static void gp10b_ce_nonstall_isr(struct gk20a *g, u32 inst_id, u32 pri_base) | |||
72 | if (ce_intr & ce_intr_status_nonblockpipe_pending_f()) { | 64 | if (ce_intr & ce_intr_status_nonblockpipe_pending_f()) { |
73 | gk20a_writel(g, ce_intr_status_r(inst_id), | 65 | gk20a_writel(g, ce_intr_status_r(inst_id), |
74 | ce_intr_status_nonblockpipe_pending_f()); | 66 | ce_intr_status_nonblockpipe_pending_f()); |
75 | ce_nonblockpipe_isr(g, ce_intr); | 67 | ops |= (gk20a_nonstall_ops_wakeup_semaphore | |
68 | gk20a_nonstall_ops_post_events); | ||
76 | } | 69 | } |
77 | 70 | ||
78 | return; | 71 | return ops; |
79 | } | 72 | } |
80 | void gp10b_init_ce(struct gpu_ops *gops) | 73 | void gp10b_init_ce(struct gpu_ops *gops) |
81 | { | 74 | { |
diff --git a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c index 3f066c37..dfcbe398 100644 --- a/drivers/gpu/nvgpu/gp10b/mc_gp10b.c +++ b/drivers/gpu/nvgpu/gp10b/mc_gp10b.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | 17 | ||
18 | #include "gk20a/gk20a.h" | 18 | #include "gk20a/gk20a.h" |
19 | #include "gk20a/mc_gk20a.h" | ||
19 | 20 | ||
20 | #include "mc_gp10b.h" | 21 | #include "mc_gp10b.h" |
21 | 22 | ||
@@ -80,12 +81,15 @@ irqreturn_t mc_gp10b_isr_stall(struct gk20a *g) | |||
80 | 81 | ||
81 | gk20a_writel(g, mc_intr_en_clear_r(0), 0xffffffff); | 82 | gk20a_writel(g, mc_intr_en_clear_r(0), 0xffffffff); |
82 | 83 | ||
84 | atomic_inc(&g->hw_irq_stall_count); | ||
85 | |||
83 | return IRQ_WAKE_THREAD; | 86 | return IRQ_WAKE_THREAD; |
84 | } | 87 | } |
85 | 88 | ||
86 | irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g) | 89 | irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g) |
87 | { | 90 | { |
88 | u32 mc_intr_1; | 91 | u32 mc_intr_1; |
92 | u32 hw_irq_count; | ||
89 | 93 | ||
90 | if (!g->power_on) | 94 | if (!g->power_on) |
91 | return IRQ_NONE; | 95 | return IRQ_NONE; |
@@ -97,12 +101,27 @@ irqreturn_t mc_gp10b_isr_nonstall(struct gk20a *g) | |||
97 | 101 | ||
98 | gk20a_writel(g, mc_intr_en_clear_r(1), 0xffffffff); | 102 | gk20a_writel(g, mc_intr_en_clear_r(1), 0xffffffff); |
99 | 103 | ||
100 | return IRQ_WAKE_THREAD; | 104 | if (g->ops.mc.isr_thread_nonstall) |
105 | g->ops.mc.isr_thread_nonstall(g, mc_intr_1); | ||
106 | |||
107 | hw_irq_count = atomic_inc_return(&g->hw_irq_nonstall_count); | ||
108 | |||
109 | gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING), | ||
110 | g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]); | ||
111 | |||
112 | /* sync handled irq counter before re-enabling interrupts */ | ||
113 | atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count); | ||
114 | |||
115 | wake_up_all(&g->sw_irq_nonstall_last_handled_wq); | ||
116 | |||
117 | return IRQ_HANDLED; | ||
101 | } | 118 | } |
102 | 119 | ||
103 | irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) | 120 | irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) |
104 | { | 121 | { |
105 | u32 mc_intr_0; | 122 | u32 mc_intr_0; |
123 | int hw_irq_count; | ||
124 | |||
106 | u32 engine_id_idx; | 125 | u32 engine_id_idx; |
107 | u32 active_engine_id = 0; | 126 | u32 active_engine_id = 0; |
108 | u32 engine_enum = ENGINE_INVAL_GK20A; | 127 | u32 engine_enum = ENGINE_INVAL_GK20A; |
@@ -110,6 +129,7 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) | |||
110 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | 129 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); |
111 | 130 | ||
112 | mc_intr_0 = gk20a_readl(g, mc_intr_r(0)); | 131 | mc_intr_0 = gk20a_readl(g, mc_intr_r(0)); |
132 | hw_irq_count = atomic_read(&g->hw_irq_stall_count); | ||
113 | 133 | ||
114 | gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); | 134 | gk20a_dbg(gpu_dbg_intr, "stall intr %08x\n", mc_intr_0); |
115 | 135 | ||
@@ -146,51 +166,13 @@ irqreturn_t mc_gp10b_intr_thread_stall(struct gk20a *g) | |||
146 | if (mc_intr_0 & mc_intr_ltc_pending_f()) | 166 | if (mc_intr_0 & mc_intr_ltc_pending_f()) |
147 | g->ops.ltc.isr(g); | 167 | g->ops.ltc.isr(g); |
148 | 168 | ||
169 | /* sync handled irq counter before re-enabling interrupts */ | ||
170 | atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); | ||
171 | |||
149 | gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING), | 172 | gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_STALLING), |
150 | g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]); | 173 | g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_STALLING]); |
151 | 174 | ||
152 | return IRQ_HANDLED; | 175 | wake_up_all(&g->sw_irq_stall_last_handled_wq); |
153 | } | ||
154 | |||
155 | irqreturn_t mc_gp10b_intr_thread_nonstall(struct gk20a *g) | ||
156 | { | ||
157 | u32 mc_intr_1; | ||
158 | u32 engine_id_idx; | ||
159 | u32 active_engine_id = 0; | ||
160 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
161 | |||
162 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | ||
163 | |||
164 | mc_intr_1 = gk20a_readl(g, mc_intr_r(1)); | ||
165 | |||
166 | gk20a_dbg(gpu_dbg_intr, "non-stall intr %08x\n", mc_intr_1); | ||
167 | |||
168 | if (mc_intr_1 & mc_intr_pfifo_pending_f()) | ||
169 | gk20a_fifo_nonstall_isr(g); | ||
170 | |||
171 | for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; engine_id_idx++) { | ||
172 | active_engine_id = g->fifo.active_engines_list[engine_id_idx]; | ||
173 | |||
174 | if (mc_intr_1 & g->fifo.engine_info[active_engine_id].intr_mask) { | ||
175 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; | ||
176 | /* GR Engine */ | ||
177 | if (engine_enum == ENGINE_GR_GK20A) { | ||
178 | gk20a_gr_nonstall_isr(g); | ||
179 | } | ||
180 | |||
181 | /* CE Engine */ | ||
182 | if (((engine_enum == ENGINE_GRCE_GK20A) || | ||
183 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && | ||
184 | g->ops.ce2.isr_nonstall) { | ||
185 | g->ops.ce2.isr_nonstall(g, | ||
186 | g->fifo.engine_info[active_engine_id].inst_id, | ||
187 | g->fifo.engine_info[active_engine_id].pri_base); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | gk20a_writel(g, mc_intr_en_set_r(NVGPU_MC_INTR_NONSTALLING), | ||
193 | g->ops.mc.intr_mask_restore[NVGPU_MC_INTR_NONSTALLING]); | ||
194 | 176 | ||
195 | return IRQ_HANDLED; | 177 | return IRQ_HANDLED; |
196 | } | 178 | } |
@@ -202,5 +184,7 @@ void gp10b_init_mc(struct gpu_ops *gops) | |||
202 | gops->mc.isr_stall = mc_gp10b_isr_stall; | 184 | gops->mc.isr_stall = mc_gp10b_isr_stall; |
203 | gops->mc.isr_nonstall = mc_gp10b_isr_nonstall; | 185 | gops->mc.isr_nonstall = mc_gp10b_isr_nonstall; |
204 | gops->mc.isr_thread_stall = mc_gp10b_intr_thread_stall; | 186 | gops->mc.isr_thread_stall = mc_gp10b_intr_thread_stall; |
205 | gops->mc.isr_thread_nonstall = mc_gp10b_intr_thread_nonstall; | 187 | gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; |
188 | gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; | ||
189 | |||
206 | } | 190 | } |