diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux')
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/intr.c | 84 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/intr.h | 2 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/module.c | 9 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/linux/pci.c | 2 |
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 | ||
20 | irqreturn_t nvgpu_intr_stall(struct gk20a *g) | 22 | irqreturn_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 | ||
61 | irqreturn_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 | |||
126 | void 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 | ||
18 | irqreturn_t nvgpu_intr_stall(struct gk20a *g); | 18 | irqreturn_t nvgpu_intr_stall(struct gk20a *g); |
19 | irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g); | 19 | irqreturn_t nvgpu_intr_thread_stall(struct gk20a *g); |
20 | irqreturn_t nvgpu_intr_nonstall(struct gk20a *g); | ||
21 | void 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 | ||
498 | static irqreturn_t gk20a_intr_thread_stall(int irq, void *dev_id) | 505 | static 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 */ |