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/gk20a/mc_gk20a.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/gk20a/mc_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mc_gk20a.c | 98 |
1 files changed, 60 insertions, 38 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c index 65f1a119..caab6b5e 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c | |||
@@ -21,6 +21,24 @@ | |||
21 | 21 | ||
22 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> | 22 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> |
23 | 23 | ||
24 | void mc_gk20a_nonstall_cb(struct work_struct *work) | ||
25 | { | ||
26 | struct gk20a *g = container_of(work, struct gk20a, nonstall_fn_work); | ||
27 | u32 ops; | ||
28 | bool semaphore_wakeup, post_events; | ||
29 | |||
30 | do { | ||
31 | ops = atomic_xchg(&g->nonstall_ops, 0); | ||
32 | |||
33 | semaphore_wakeup = ops & gk20a_nonstall_ops_wakeup_semaphore; | ||
34 | post_events = ops & gk20a_nonstall_ops_post_events; | ||
35 | |||
36 | if (semaphore_wakeup) | ||
37 | gk20a_channel_semaphore_wakeup(g, post_events); | ||
38 | |||
39 | } while (atomic_read(&g->nonstall_ops) != 0); | ||
40 | } | ||
41 | |||
24 | irqreturn_t mc_gk20a_isr_stall(struct gk20a *g) | 42 | irqreturn_t mc_gk20a_isr_stall(struct gk20a *g) |
25 | { | 43 | { |
26 | u32 mc_intr_0; | 44 | u32 mc_intr_0; |
@@ -51,6 +69,7 @@ irqreturn_t mc_gk20a_isr_stall(struct gk20a *g) | |||
51 | irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) | 69 | irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) |
52 | { | 70 | { |
53 | u32 mc_intr_1; | 71 | u32 mc_intr_1; |
72 | u32 hw_irq_count; | ||
54 | 73 | ||
55 | if (!g->power_on) | 74 | if (!g->power_on) |
56 | return IRQ_NONE; | 75 | return IRQ_NONE; |
@@ -66,9 +85,23 @@ irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) | |||
66 | /* flush previous write */ | 85 | /* flush previous write */ |
67 | gk20a_readl(g, mc_intr_en_1_r()); | 86 | gk20a_readl(g, mc_intr_en_1_r()); |
68 | 87 | ||
69 | atomic_inc(&g->hw_irq_nonstall_count); | 88 | if (g->ops.mc.isr_thread_nonstall) |
89 | g->ops.mc.isr_thread_nonstall(g, mc_intr_1); | ||
70 | 90 | ||
71 | return IRQ_WAKE_THREAD; | 91 | hw_irq_count = atomic_inc_return(&g->hw_irq_nonstall_count); |
92 | |||
93 | /* sync handled irq counter before re-enabling interrupts */ | ||
94 | atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count); | ||
95 | |||
96 | gk20a_writel(g, mc_intr_en_1_r(), | ||
97 | mc_intr_en_1_inta_hardware_f()); | ||
98 | |||
99 | /* flush previous write */ | ||
100 | gk20a_readl(g, mc_intr_en_1_r()); | ||
101 | |||
102 | wake_up_all(&g->sw_irq_nonstall_last_handled_wq); | ||
103 | |||
104 | return IRQ_HANDLED; | ||
72 | } | 105 | } |
73 | 106 | ||
74 | irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) | 107 | irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) |
@@ -137,59 +170,47 @@ irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g) | |||
137 | return IRQ_HANDLED; | 170 | return IRQ_HANDLED; |
138 | } | 171 | } |
139 | 172 | ||
140 | irqreturn_t mc_gk20a_intr_thread_nonstall(struct gk20a *g) | 173 | void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 mc_intr_1) |
141 | { | 174 | { |
142 | u32 mc_intr_1; | ||
143 | int hw_irq_count; | ||
144 | u32 engine_id_idx; | 175 | u32 engine_id_idx; |
145 | u32 active_engine_id = 0; | 176 | u32 active_engine_id = 0; |
146 | u32 engine_enum = ENGINE_INVAL_GK20A; | 177 | u32 engine_enum = ENGINE_INVAL_GK20A; |
147 | 178 | int ops_old, ops_new, ops = 0; | |
148 | gk20a_dbg(gpu_dbg_intr, "interrupt thread launched"); | ||
149 | |||
150 | mc_intr_1 = gk20a_readl(g, mc_intr_1_r()); | ||
151 | hw_irq_count = atomic_read(&g->hw_irq_nonstall_count); | ||
152 | |||
153 | gk20a_dbg(gpu_dbg_intr, "non-stall intr %08x\n", mc_intr_1); | ||
154 | 179 | ||
155 | if (mc_intr_1 & mc_intr_0_pfifo_pending_f()) | 180 | if (mc_intr_1 & mc_intr_0_pfifo_pending_f()) |
156 | gk20a_fifo_nonstall_isr(g); | 181 | ops |= gk20a_fifo_nonstall_isr(g); |
157 | if (mc_intr_1 & mc_intr_0_priv_ring_pending_f()) | ||
158 | gk20a_priv_ring_isr(g); | ||
159 | 182 | ||
160 | for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; engine_id_idx++) { | 183 | for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; |
184 | engine_id_idx++) { | ||
161 | active_engine_id = g->fifo.active_engines_list[engine_id_idx]; | 185 | active_engine_id = g->fifo.active_engines_list[engine_id_idx]; |
162 | 186 | ||
163 | if (mc_intr_1 & g->fifo.engine_info[active_engine_id].intr_mask) { | 187 | if (mc_intr_1 & |
188 | g->fifo.engine_info[active_engine_id].intr_mask) { | ||
164 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; | 189 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; |
165 | /* GR Engine */ | 190 | /* GR Engine */ |
166 | if (engine_enum == ENGINE_GR_GK20A) { | 191 | if (engine_enum == ENGINE_GR_GK20A) |
167 | gk20a_gr_nonstall_isr(g); | 192 | ops |= gk20a_gr_nonstall_isr(g); |
168 | } | ||
169 | 193 | ||
170 | /* CE Engine */ | 194 | /* CE Engine */ |
171 | if (((engine_enum == ENGINE_GRCE_GK20A) || | 195 | if (((engine_enum == ENGINE_GRCE_GK20A) || |
172 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && | 196 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && |
173 | g->ops.ce2.isr_nonstall) { | 197 | g->ops.ce2.isr_nonstall) |
174 | g->ops.ce2.isr_nonstall(g, | 198 | ops |= g->ops.ce2.isr_nonstall(g, |
175 | g->fifo.engine_info[active_engine_id].inst_id, | 199 | g->fifo.engine_info[active_engine_id]. |
176 | g->fifo.engine_info[active_engine_id].pri_base); | 200 | inst_id, |
177 | } | 201 | g->fifo.engine_info[active_engine_id]. |
202 | pri_base); | ||
178 | } | 203 | } |
179 | } | 204 | } |
180 | 205 | if (ops) { | |
181 | /* sync handled irq counter before re-enabling interrupts */ | 206 | do { |
182 | atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count); | 207 | ops_old = atomic_read(&g->nonstall_ops); |
183 | 208 | ops_new = ops_old | ops; | |
184 | gk20a_writel(g, mc_intr_en_1_r(), | 209 | } while (ops_old != atomic_cmpxchg(&g->nonstall_ops, |
185 | mc_intr_en_1_inta_hardware_f()); | 210 | ops_old, ops_new)); |
186 | 211 | ||
187 | /* flush previous write */ | 212 | queue_work(g->nonstall_work_queue, &g->nonstall_fn_work); |
188 | gk20a_readl(g, mc_intr_en_1_r()); | 213 | } |
189 | |||
190 | wake_up_all(&g->sw_irq_nonstall_last_handled_wq); | ||
191 | |||
192 | return IRQ_HANDLED; | ||
193 | } | 214 | } |
194 | 215 | ||
195 | void mc_gk20a_intr_enable(struct gk20a *g) | 216 | void mc_gk20a_intr_enable(struct gk20a *g) |
@@ -237,4 +258,5 @@ void gk20a_init_mc(struct gpu_ops *gops) | |||
237 | gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; | 258 | gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; |
238 | gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall; | 259 | gops->mc.isr_thread_stall = mc_gk20a_intr_thread_stall; |
239 | gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; | 260 | gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; |
261 | gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; | ||
240 | } | 262 | } |