diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mc_gk20a.c | 128 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mc_gk20a.h | 7 |
4 files changed, 32 insertions, 117 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index e4d454fe..b038cd81 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -187,13 +187,6 @@ int gk20a_finalize_poweron(struct gk20a *g) | |||
187 | if (g->ops.clk.disable_slowboot) | 187 | if (g->ops.clk.disable_slowboot) |
188 | g->ops.clk.disable_slowboot(g); | 188 | g->ops.clk.disable_slowboot(g); |
189 | 189 | ||
190 | /* Enable interrupt workqueue */ | ||
191 | if (!g->nonstall_work_queue) { | ||
192 | g->nonstall_work_queue = alloc_workqueue("%s", | ||
193 | WQ_HIGHPRI, 1, "mc_nonstall"); | ||
194 | INIT_WORK(&g->nonstall_fn_work, g->ops.mc.isr_nonstall_cb); | ||
195 | } | ||
196 | |||
197 | gk20a_enable_priv_ring(g); | 190 | gk20a_enable_priv_ring(g); |
198 | 191 | ||
199 | /* TBD: move this after graphics init in which blcg/slcg is enabled. | 192 | /* TBD: move this after graphics init in which blcg/slcg is enabled. |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index bd93cc33..60494050 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -36,7 +36,6 @@ struct nvgpu_clk_pll_debug_data; | |||
36 | #include <linux/sched.h> | 36 | #include <linux/sched.h> |
37 | #include <nvgpu/lock.h> | 37 | #include <nvgpu/lock.h> |
38 | #include <nvgpu/thread.h> | 38 | #include <nvgpu/thread.h> |
39 | #include <linux/irqreturn.h> | ||
40 | #include <linux/version.h> | 39 | #include <linux/version.h> |
41 | #include <linux/cdev.h> | 40 | #include <linux/cdev.h> |
42 | #ifdef CONFIG_DEBUG_FS | 41 | #ifdef CONFIG_DEBUG_FS |
@@ -841,14 +840,14 @@ struct gpu_ops { | |||
841 | void (*intr_unit_config)(struct gk20a *g, | 840 | void (*intr_unit_config)(struct gk20a *g, |
842 | bool enable, bool is_stalling, u32 unit); | 841 | bool enable, bool is_stalling, u32 unit); |
843 | void (*isr_stall)(struct gk20a *g); | 842 | void (*isr_stall)(struct gk20a *g); |
844 | irqreturn_t (*isr_nonstall)(struct gk20a *g); | ||
845 | void (*isr_thread_nonstall)(struct gk20a *g, u32 intr); | ||
846 | void (*isr_nonstall_cb)(struct work_struct *work); | ||
847 | bool (*is_intr_hub_pending)(struct gk20a *g, u32 mc_intr); | 843 | bool (*is_intr_hub_pending)(struct gk20a *g, u32 mc_intr); |
848 | u32 intr_mask_restore[4]; | 844 | u32 intr_mask_restore[4]; |
849 | u32 (*intr_stall)(struct gk20a *g); | 845 | u32 (*intr_stall)(struct gk20a *g); |
850 | void (*intr_stall_pause)(struct gk20a *g); | 846 | void (*intr_stall_pause)(struct gk20a *g); |
851 | void (*intr_stall_resume)(struct gk20a *g); | 847 | void (*intr_stall_resume)(struct gk20a *g); |
848 | u32 (*intr_nonstall)(struct gk20a *g); | ||
849 | void (*intr_nonstall_pause)(struct gk20a *g); | ||
850 | void (*intr_nonstall_resume)(struct gk20a *g); | ||
852 | void (*enable)(struct gk20a *g, u32 units); | 851 | void (*enable)(struct gk20a *g, u32 units); |
853 | void (*disable)(struct gk20a *g, u32 units); | 852 | void (*disable)(struct gk20a *g, u32 units); |
854 | void (*reset)(struct gk20a *g, u32 units); | 853 | void (*reset)(struct gk20a *g, u32 units); |
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c index 2cdcaaeb..111872a2 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.c | |||
@@ -24,62 +24,6 @@ | |||
24 | 24 | ||
25 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> | 25 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> |
26 | 26 | ||
27 | void mc_gk20a_nonstall_cb(struct work_struct *work) | ||
28 | { | ||
29 | struct gk20a *g = container_of(work, struct gk20a, nonstall_fn_work); | ||
30 | u32 ops; | ||
31 | bool semaphore_wakeup, post_events; | ||
32 | |||
33 | do { | ||
34 | ops = atomic_xchg(&g->nonstall_ops, 0); | ||
35 | |||
36 | semaphore_wakeup = ops & gk20a_nonstall_ops_wakeup_semaphore; | ||
37 | post_events = ops & gk20a_nonstall_ops_post_events; | ||
38 | |||
39 | if (semaphore_wakeup) | ||
40 | gk20a_channel_semaphore_wakeup(g, post_events); | ||
41 | |||
42 | } while (atomic_read(&g->nonstall_ops) != 0); | ||
43 | } | ||
44 | |||
45 | irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g) | ||
46 | { | ||
47 | u32 mc_intr_1; | ||
48 | u32 hw_irq_count; | ||
49 | |||
50 | if (!g->power_on) | ||
51 | return IRQ_NONE; | ||
52 | |||
53 | /* not from gpu when sharing irq with others */ | ||
54 | mc_intr_1 = gk20a_readl(g, mc_intr_1_r()); | ||
55 | if (unlikely(!mc_intr_1)) | ||
56 | return IRQ_NONE; | ||
57 | |||
58 | gk20a_writel(g, mc_intr_en_1_r(), | ||
59 | mc_intr_en_1_inta_disabled_f()); | ||
60 | |||
61 | /* flush previous write */ | ||
62 | gk20a_readl(g, mc_intr_en_1_r()); | ||
63 | |||
64 | if (g->ops.mc.isr_thread_nonstall) | ||
65 | g->ops.mc.isr_thread_nonstall(g, mc_intr_1); | ||
66 | |||
67 | hw_irq_count = atomic_inc_return(&g->hw_irq_nonstall_count); | ||
68 | |||
69 | /* sync handled irq counter before re-enabling interrupts */ | ||
70 | atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count); | ||
71 | |||
72 | gk20a_writel(g, mc_intr_en_1_r(), | ||
73 | mc_intr_en_1_inta_hardware_f()); | ||
74 | |||
75 | /* flush previous write */ | ||
76 | gk20a_readl(g, mc_intr_en_1_r()); | ||
77 | |||
78 | wake_up_all(&g->sw_irq_nonstall_last_handled_wq); | ||
79 | |||
80 | return IRQ_HANDLED; | ||
81 | } | ||
82 | |||
83 | void mc_gk20a_isr_stall(struct gk20a *g) | 27 | void mc_gk20a_isr_stall(struct gk20a *g) |
84 | { | 28 | { |
85 | u32 mc_intr_0; | 29 | u32 mc_intr_0; |
@@ -128,49 +72,6 @@ void mc_gk20a_isr_stall(struct gk20a *g) | |||
128 | atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); | 72 | atomic_set(&g->sw_irq_stall_last_handled, hw_irq_count); |
129 | } | 73 | } |
130 | 74 | ||
131 | void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 mc_intr_1) | ||
132 | { | ||
133 | u32 engine_id_idx; | ||
134 | u32 active_engine_id = 0; | ||
135 | u32 engine_enum = ENGINE_INVAL_GK20A; | ||
136 | int ops_old, ops_new, ops = 0; | ||
137 | |||
138 | if (g->ops.mc.is_intr1_pending(g, NVGPU_UNIT_FIFO, mc_intr_1)) | ||
139 | ops |= gk20a_fifo_nonstall_isr(g); | ||
140 | |||
141 | for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines; | ||
142 | engine_id_idx++) { | ||
143 | active_engine_id = g->fifo.active_engines_list[engine_id_idx]; | ||
144 | |||
145 | if (mc_intr_1 & | ||
146 | g->fifo.engine_info[active_engine_id].intr_mask) { | ||
147 | engine_enum = g->fifo.engine_info[active_engine_id].engine_enum; | ||
148 | /* GR Engine */ | ||
149 | if (engine_enum == ENGINE_GR_GK20A) | ||
150 | ops |= gk20a_gr_nonstall_isr(g); | ||
151 | |||
152 | /* CE Engine */ | ||
153 | if (((engine_enum == ENGINE_GRCE_GK20A) || | ||
154 | (engine_enum == ENGINE_ASYNC_CE_GK20A)) && | ||
155 | g->ops.ce2.isr_nonstall) | ||
156 | ops |= g->ops.ce2.isr_nonstall(g, | ||
157 | g->fifo.engine_info[active_engine_id]. | ||
158 | inst_id, | ||
159 | g->fifo.engine_info[active_engine_id]. | ||
160 | pri_base); | ||
161 | } | ||
162 | } | ||
163 | if (ops) { | ||
164 | do { | ||
165 | ops_old = atomic_read(&g->nonstall_ops); | ||
166 | ops_new = ops_old | ops; | ||
167 | } while (ops_old != atomic_cmpxchg(&g->nonstall_ops, | ||
168 | ops_old, ops_new)); | ||
169 | |||
170 | queue_work(g->nonstall_work_queue, &g->nonstall_fn_work); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | void mc_gk20a_intr_enable(struct gk20a *g) | 75 | void mc_gk20a_intr_enable(struct gk20a *g) |
175 | { | 76 | { |
176 | u32 eng_intr_mask = gk20a_fifo_engine_interrupt_mask(g); | 77 | u32 eng_intr_mask = gk20a_fifo_engine_interrupt_mask(g); |
@@ -226,11 +127,34 @@ void mc_gk20a_intr_stall_resume(struct gk20a *g) | |||
226 | gk20a_readl(g, mc_intr_en_0_r()); | 127 | gk20a_readl(g, mc_intr_en_0_r()); |
227 | } | 128 | } |
228 | 129 | ||
130 | void mc_gk20a_intr_nonstall_pause(struct gk20a *g) | ||
131 | { | ||
132 | gk20a_writel(g, mc_intr_en_1_r(), | ||
133 | mc_intr_en_0_inta_disabled_f()); | ||
134 | |||
135 | /* flush previous write */ | ||
136 | gk20a_readl(g, mc_intr_en_1_r()); | ||
137 | } | ||
138 | |||
139 | void mc_gk20a_intr_nonstall_resume(struct gk20a *g) | ||
140 | { | ||
141 | gk20a_writel(g, mc_intr_en_1_r(), | ||
142 | mc_intr_en_0_inta_hardware_f()); | ||
143 | |||
144 | /* flush previous write */ | ||
145 | gk20a_readl(g, mc_intr_en_1_r()); | ||
146 | } | ||
147 | |||
229 | u32 mc_gk20a_intr_stall(struct gk20a *g) | 148 | u32 mc_gk20a_intr_stall(struct gk20a *g) |
230 | { | 149 | { |
231 | return gk20a_readl(g, mc_intr_0_r()); | 150 | return gk20a_readl(g, mc_intr_0_r()); |
232 | } | 151 | } |
233 | 152 | ||
153 | u32 mc_gk20a_intr_nonstall(struct gk20a *g) | ||
154 | { | ||
155 | return gk20a_readl(g, mc_intr_1_r()); | ||
156 | } | ||
157 | |||
234 | void gk20a_mc_disable(struct gk20a *g, u32 units) | 158 | void gk20a_mc_disable(struct gk20a *g, u32 units) |
235 | { | 159 | { |
236 | u32 pmc; | 160 | u32 pmc; |
@@ -320,9 +244,9 @@ void gk20a_init_mc(struct gpu_ops *gops) | |||
320 | gops->mc.intr_stall = mc_gk20a_intr_stall; | 244 | gops->mc.intr_stall = mc_gk20a_intr_stall; |
321 | gops->mc.intr_stall_pause = mc_gk20a_intr_stall_pause; | 245 | gops->mc.intr_stall_pause = mc_gk20a_intr_stall_pause; |
322 | gops->mc.intr_stall_resume = mc_gk20a_intr_stall_resume; | 246 | gops->mc.intr_stall_resume = mc_gk20a_intr_stall_resume; |
323 | gops->mc.isr_nonstall = mc_gk20a_isr_nonstall; | 247 | gops->mc.intr_nonstall = mc_gk20a_intr_nonstall; |
324 | gops->mc.isr_thread_nonstall = mc_gk20a_intr_thread_nonstall; | 248 | gops->mc.intr_nonstall_pause = mc_gk20a_intr_nonstall_pause; |
325 | gops->mc.isr_nonstall_cb = mc_gk20a_nonstall_cb; | 249 | gops->mc.intr_nonstall_resume = mc_gk20a_intr_nonstall_resume; |
326 | gops->mc.enable = gk20a_mc_enable; | 250 | gops->mc.enable = gk20a_mc_enable; |
327 | gops->mc.disable = gk20a_mc_disable; | 251 | gops->mc.disable = gk20a_mc_disable; |
328 | gops->mc.reset = gk20a_mc_reset; | 252 | gops->mc.reset = gk20a_mc_reset; |
diff --git a/drivers/gpu/nvgpu/gk20a/mc_gk20a.h b/drivers/gpu/nvgpu/gk20a/mc_gk20a.h index 6c0d159a..7ecd27bf 100644 --- a/drivers/gpu/nvgpu/gk20a/mc_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/mc_gk20a.h | |||
@@ -23,10 +23,9 @@ void mc_gk20a_isr_stall(struct gk20a *g); | |||
23 | u32 mc_gk20a_intr_stall(struct gk20a *g); | 23 | u32 mc_gk20a_intr_stall(struct gk20a *g); |
24 | void mc_gk20a_intr_stall_pause(struct gk20a *g); | 24 | void mc_gk20a_intr_stall_pause(struct gk20a *g); |
25 | void mc_gk20a_intr_stall_resume(struct gk20a *g); | 25 | void mc_gk20a_intr_stall_resume(struct gk20a *g); |
26 | irqreturn_t mc_gk20a_isr_nonstall(struct gk20a *g); | 26 | u32 mc_gk20a_intr_nonstall(struct gk20a *g); |
27 | irqreturn_t mc_gk20a_intr_thread_stall(struct gk20a *g); | 27 | void mc_gk20a_intr_nonstall_pause(struct gk20a *g); |
28 | void mc_gk20a_intr_thread_nonstall(struct gk20a *g, u32 intr); | 28 | void mc_gk20a_intr_nonstall_resume(struct gk20a *g); |
29 | void mc_gk20a_nonstall_cb(struct work_struct *work); | ||
30 | void gk20a_mc_enable(struct gk20a *g, u32 units); | 29 | void gk20a_mc_enable(struct gk20a *g, u32 units); |
31 | void gk20a_mc_disable(struct gk20a *g, u32 units); | 30 | void gk20a_mc_disable(struct gk20a *g, u32 units); |
32 | void gk20a_mc_reset(struct gk20a *g, u32 units); | 31 | void gk20a_mc_reset(struct gk20a *g, u32 units); |