summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common')
-rw-r--r--drivers/gpu/nvgpu/common/linux/intr.c84
-rw-r--r--drivers/gpu/nvgpu/common/linux/intr.h2
-rw-r--r--drivers/gpu/nvgpu/common/linux/module.c9
-rw-r--r--drivers/gpu/nvgpu/common/linux/pci.c2
4 files changed, 95 insertions, 2 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/intr.c b/drivers/gpu/nvgpu/common/linux/intr.c
index 77e44dd9..7d699dee 100644
--- a/drivers/gpu/nvgpu/common/linux/intr.c
+++ b/drivers/gpu/nvgpu/common/linux/intr.c
@@ -12,10 +12,12 @@
12 */ 12 */
13 13
14#include <trace/events/gk20a.h> 14#include <trace/events/gk20a.h>
15#include <linux/irqreturn.h>
15 16
16#include "gk20a/gk20a.h" 17#include "gk20a/gk20a.h"
17 18
18#include <nvgpu/atomic.h> 19#include <nvgpu/atomic.h>
20#include <nvgpu/unit.h>
19 21
20irqreturn_t nvgpu_intr_stall(struct gk20a *g) 22irqreturn_t nvgpu_intr_stall(struct gk20a *g)
21{ 23{
@@ -56,3 +58,85 @@ irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g)
56 return IRQ_HANDLED; 58 return IRQ_HANDLED;
57} 59}
58 60
61irqreturn_t nvgpu_intr_nonstall(struct gk20a *g)
62{
63 u32 mc_intr_1;
64 u32 hw_irq_count;
65 u32 engine_id_idx;
66 u32 active_engine_id = 0;
67 u32 engine_enum = ENGINE_INVAL_GK20A;
68 int ops_old, ops_new, ops = 0;
69 if (!g->power_on)
70 return IRQ_NONE;
71
72 /* not from gpu when sharing irq with others */
73 mc_intr_1 = g->ops.mc.intr_nonstall(g);
74 if (unlikely(!mc_intr_1))
75 return IRQ_NONE;
76
77 g->ops.mc.intr_nonstall_pause(g);
78
79 if (g->ops.mc.is_intr1_pending(g, NVGPU_UNIT_FIFO, mc_intr_1))
80 ops |= gk20a_fifo_nonstall_isr(g);
81
82 for (engine_id_idx = 0; engine_id_idx < g->fifo.num_engines;
83 engine_id_idx++) {
84 struct fifo_engine_info_gk20a *engine_info;
85
86 active_engine_id = g->fifo.active_engines_list[engine_id_idx];
87 engine_info = &g->fifo.engine_info[active_engine_id];
88
89 if (mc_intr_1 & engine_info->intr_mask) {
90 engine_enum = engine_info->engine_enum;
91 /* GR Engine */
92 if (engine_enum == ENGINE_GR_GK20A)
93 ops |= gk20a_gr_nonstall_isr(g);
94
95 /* CE Engine */
96 if (((engine_enum == ENGINE_GRCE_GK20A) ||
97 (engine_enum == ENGINE_ASYNC_CE_GK20A)) &&
98 g->ops.ce2.isr_nonstall)
99 ops |= g->ops.ce2.isr_nonstall(g,
100 engine_info->inst_id,
101 engine_info->pri_base);
102 }
103 }
104 if (ops) {
105 do {
106 ops_old = atomic_read(&g->nonstall_ops);
107 ops_new = ops_old | ops;
108 } while (ops_old != atomic_cmpxchg(&g->nonstall_ops,
109 ops_old, ops_new));
110
111 queue_work(g->nonstall_work_queue, &g->nonstall_fn_work);
112 }
113
114 hw_irq_count = atomic_inc_return(&g->hw_irq_nonstall_count);
115
116 /* sync handled irq counter before re-enabling interrupts */
117 atomic_set(&g->sw_irq_nonstall_last_handled, hw_irq_count);
118
119 g->ops.mc.intr_nonstall_resume(g);
120
121 wake_up_all(&g->sw_irq_nonstall_last_handled_wq);
122
123 return IRQ_HANDLED;
124}
125
126void nvgpu_intr_nonstall_cb(struct work_struct *work)
127{
128 struct gk20a *g = container_of(work, struct gk20a, nonstall_fn_work);
129 u32 ops;
130 bool semaphore_wakeup, post_events;
131
132 do {
133 ops = atomic_xchg(&g->nonstall_ops, 0);
134
135 semaphore_wakeup = ops & gk20a_nonstall_ops_wakeup_semaphore;
136 post_events = ops & gk20a_nonstall_ops_post_events;
137
138 if (semaphore_wakeup)
139 gk20a_channel_semaphore_wakeup(g, post_events);
140
141 } while (atomic_read(&g->nonstall_ops) != 0);
142}
diff --git a/drivers/gpu/nvgpu/common/linux/intr.h b/drivers/gpu/nvgpu/common/linux/intr.h
index 243d8f51..d43cdccb 100644
--- a/drivers/gpu/nvgpu/common/linux/intr.h
+++ b/drivers/gpu/nvgpu/common/linux/intr.h
@@ -17,4 +17,6 @@ struct gk20a;
17 17
18irqreturn_t nvgpu_intr_stall(struct gk20a *g); 18irqreturn_t nvgpu_intr_stall(struct gk20a *g);
19irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g); 19irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g);
20irqreturn_t nvgpu_intr_nonstall(struct gk20a *g);
21void nvgpu_intr_nonstall_cb(struct work_struct *work);
20#endif 22#endif
diff --git a/drivers/gpu/nvgpu/common/linux/module.c b/drivers/gpu/nvgpu/common/linux/module.c
index 4f7fc3fa..34a0ded6 100644
--- a/drivers/gpu/nvgpu/common/linux/module.c
+++ b/drivers/gpu/nvgpu/common/linux/module.c
@@ -162,6 +162,13 @@ int gk20a_pm_finalize_poweron(struct device *dev)
162 nice_value = task_nice(current); 162 nice_value = task_nice(current);
163 set_user_nice(current, -20); 163 set_user_nice(current, -20);
164 164
165 /* Enable interrupt workqueue */
166 if (!g->nonstall_work_queue) {
167 g->nonstall_work_queue = alloc_workqueue("%s",
168 WQ_HIGHPRI, 1, "mc_nonstall");
169 INIT_WORK(&g->nonstall_fn_work, nvgpu_intr_nonstall_cb);
170 }
171
165 err = gk20a_finalize_poweron(g); 172 err = gk20a_finalize_poweron(g);
166 set_user_nice(current, nice_value); 173 set_user_nice(current, nice_value);
167 if (err) 174 if (err)
@@ -492,7 +499,7 @@ static irqreturn_t gk20a_intr_isr_nonstall(int irq, void *dev_id)
492{ 499{
493 struct gk20a *g = dev_id; 500 struct gk20a *g = dev_id;
494 501
495 return g->ops.mc.isr_nonstall(g); 502 return nvgpu_intr_nonstall(g);
496} 503}
497 504
498static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) 505static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id)
diff --git a/drivers/gpu/nvgpu/common/linux/pci.c b/drivers/gpu/nvgpu/common/linux/pci.c
index b66a6658..4351ba5b 100644
--- a/drivers/gpu/nvgpu/common/linux/pci.c
+++ b/drivers/gpu/nvgpu/common/linux/pci.c
@@ -235,7 +235,7 @@ static irqreturn_t nvgpu_pci_isr(int irq, void *dev_id)
235 irqreturn_t ret_nonstall; 235 irqreturn_t ret_nonstall;
236 236
237 ret_stall = nvgpu_intr_stall(g); 237 ret_stall = nvgpu_intr_stall(g);
238 ret_nonstall = g->ops.mc.isr_nonstall(g); 238 ret_nonstall = nvgpu_intr_nonstall(g);
239 239
240#if defined(CONFIG_PCI_MSI) 240#if defined(CONFIG_PCI_MSI)
241 /* Send MSI EOI */ 241 /* Send MSI EOI */