diff options
author | David Nieto <dmartineznie@nvidia.com> | 2017-02-06 18:44:55 -0500 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-03-14 14:46:38 -0400 |
commit | 403874fa75dbb00e974a8d0f88b6e92be01ba42e (patch) | |
tree | 0492e82ded3c4ce7ee4438b29bcadc2db9472279 /drivers/gpu/nvgpu/gp10b/mc_gp10b.c | |
parent | 4deb494ad114088f5253d02d9ec31f9aaeb2778a (diff) |
gpu: nvgpu: refactor interrupt handling
JIRA: EVLR-1004
(*) Refactor the non-stalling interrupt path to execute clear on the
top half, so on dGPU case processing of stalling interrupts does not
block non-stalling one.
(*) Use a worker thread to do semaphore wakeups and allow batching of
the non-stalling operations.
(*) Fix a bug where some gpus will not properly track the completion
of interrupts, preventing safe driver unloads
Change-Id: Icc90a3acba544c97ec6a9285ab235d337ab9eefa
Signed-off-by: David Nieto <dmartineznie@nvidia.com>
Reviewed-on: http://git-master/r/1312796
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Lakshmanan M <lm@nvidia.com>
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: Navneet Kumar <navneetk@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu/gp10b/mc_gp10b.c')
-rw-r--r-- | drivers/gpu/nvgpu/gp10b/mc_gp10b.c | 72 |
1 files changed, 28 insertions, 44 deletions
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 | } |