1 /* $NetBSD: vmwgfx_irq.c,v 1.6 2022/10/25 23:36:21 riastradh Exp $ */
2
3 // SPDX-License-Identifier: GPL-2.0 OR MIT
4 /**************************************************************************
5 *
6 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
24 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26 * USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: vmwgfx_irq.c,v 1.6 2022/10/25 23:36:21 riastradh Exp $");
32
33 #include <linux/sched/signal.h>
34
35 #include <drm/drm_irq.h>
36
37 #include "vmwgfx_drv.h"
38
39 #define VMW_FENCE_WRAP (1 << 24)
40
41 /**
42 * vmw_thread_fn - Deferred (process context) irq handler
43 *
44 * @irq: irq number
45 * @arg: Closure argument. Pointer to a struct drm_device cast to void *
46 *
47 * This function implements the deferred part of irq processing.
48 * The function is guaranteed to run at least once after the
49 * vmw_irq_handler has returned with IRQ_WAKE_THREAD.
50 *
51 */
52 #ifdef __NetBSD__
53 static void
vmw_thread_fn(struct work * work,void * arg)54 vmw_thread_fn(struct work *work, void *arg)
55 #else
56 static irqreturn_t vmw_thread_fn(int irq, void *arg)
57 #endif
58 {
59 struct drm_device *dev = (struct drm_device *)arg;
60 struct vmw_private *dev_priv = vmw_priv(dev);
61 irqreturn_t ret = IRQ_NONE;
62
63 #ifdef __NetBSD__
64 atomic_store_relaxed(&dev_priv->irqthread_scheduled, false);
65 #endif
66
67 if (test_and_clear_bit(VMW_IRQTHREAD_FENCE,
68 dev_priv->irqthread_pending)) {
69 spin_lock(&dev_priv->fence_lock);
70 vmw_fences_update(dev_priv->fman);
71 DRM_SPIN_WAKEUP_ALL(&dev_priv->fence_queue,
72 &dev_priv->fence_lock);
73 spin_unlock(&dev_priv->fence_lock);
74 ret = IRQ_HANDLED;
75 }
76
77 if (test_and_clear_bit(VMW_IRQTHREAD_CMDBUF,
78 dev_priv->irqthread_pending)) {
79 vmw_cmdbuf_irqthread(dev_priv->cman);
80 ret = IRQ_HANDLED;
81 }
82
83 #ifndef __NetBSD__
84 return ret;
85 #endif
86 }
87
88 /**
89 * vmw_irq_handler irq handler
90 *
91 * @irq: irq number
92 * @arg: Closure argument. Pointer to a struct drm_device cast to void *
93 *
94 * This function implements the quick part of irq processing.
95 * The function performs fast actions like clearing the device interrupt
96 * flags and also reasonably quick actions like waking processes waiting for
97 * FIFO space. Other IRQ actions are deferred to the IRQ thread.
98 */
vmw_irq_handler(int irq,void * arg)99 static irqreturn_t vmw_irq_handler(int irq, void *arg)
100 {
101 struct drm_device *dev = (struct drm_device *)arg;
102 struct vmw_private *dev_priv = vmw_priv(dev);
103 uint32_t status, masked_status;
104 irqreturn_t ret = IRQ_HANDLED;
105
106 #ifdef __NetBSD__
107 status = bus_space_read_4(dev_priv->iot, dev_priv->ioh,
108 VMWGFX_IRQSTATUS_PORT);
109 #else
110 status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
111 #endif
112 masked_status = status & READ_ONCE(dev_priv->irq_mask);
113
114 if (likely(status))
115 #ifdef __NetBSD__
116 bus_space_write_4(dev_priv->iot, dev_priv->ioh,
117 VMWGFX_IRQSTATUS_PORT, status);
118 #else
119 outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
120 #endif
121
122 if (!status)
123 return IRQ_NONE;
124
125 if (masked_status & SVGA_IRQFLAG_FIFO_PROGRESS) {
126 spin_lock(&dev_priv->fifo_lock);
127 DRM_SPIN_WAKEUP_ALL(&dev_priv->fifo_queue,
128 &dev_priv->fifo_lock);
129 spin_unlock(&dev_priv->fifo_lock);
130 }
131
132 if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE |
133 SVGA_IRQFLAG_FENCE_GOAL)) &&
134 !test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending))
135 ret = IRQ_WAKE_THREAD;
136
137 if ((masked_status & (SVGA_IRQFLAG_COMMAND_BUFFER |
138 SVGA_IRQFLAG_ERROR)) &&
139 !test_and_set_bit(VMW_IRQTHREAD_CMDBUF,
140 dev_priv->irqthread_pending))
141 ret = IRQ_WAKE_THREAD;
142
143 #ifdef __NetBSD__
144 if (ret == IRQ_WAKE_THREAD) {
145 if (atomic_swap_uint(&dev_priv->irqthread_scheduled, 1) == 0) {
146 workqueue_enqueue(dev_priv->irqthread_wq,
147 &dev_priv->irqthread_work, NULL);
148 }
149 ret = IRQ_HANDLED;
150 }
151 #endif
152
153 return ret;
154 }
155
vmw_fifo_idle(struct vmw_private * dev_priv,uint32_t seqno)156 static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno)
157 {
158
159 return (vmw_read(dev_priv, SVGA_REG_BUSY) == 0);
160 }
161
vmw_update_seqno(struct vmw_private * dev_priv,struct vmw_fifo_state * fifo_state)162 void vmw_update_seqno(struct vmw_private *dev_priv,
163 struct vmw_fifo_state *fifo_state)
164 {
165 u32 *fifo_mem = dev_priv->mmio_virt;
166 uint32_t seqno = vmw_mmio_read(fifo_mem + SVGA_FIFO_FENCE);
167
168 assert_spin_locked(&dev_priv->fence_lock);
169
170 if (dev_priv->last_read_seqno != seqno) {
171 dev_priv->last_read_seqno = seqno;
172 vmw_marker_pull(&fifo_state->marker_queue, seqno);
173 vmw_fences_update(dev_priv->fman);
174 }
175 }
176
vmw_seqno_passed(struct vmw_private * dev_priv,uint32_t seqno)177 bool vmw_seqno_passed(struct vmw_private *dev_priv,
178 uint32_t seqno)
179 {
180 struct vmw_fifo_state *fifo_state;
181 bool ret;
182
183 assert_spin_locked(&dev_priv->fence_lock);
184
185 if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
186 return true;
187
188 fifo_state = &dev_priv->fifo;
189 vmw_update_seqno(dev_priv, fifo_state);
190 if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP))
191 return true;
192
193 if (!(fifo_state->capabilities & SVGA_FIFO_CAP_FENCE) &&
194 vmw_fifo_idle(dev_priv, seqno))
195 return true;
196
197 /**
198 * Then check if the seqno is higher than what we've actually
199 * emitted. Then the fence is stale and signaled.
200 */
201
202 ret = ((atomic_read(&dev_priv->marker_seq) - seqno)
203 > VMW_FENCE_WRAP);
204
205 return ret;
206 }
207
vmw_fallback_wait(struct vmw_private * dev_priv,bool lazy,bool fifo_idle,uint32_t seqno,bool interruptible,unsigned long timeout)208 int vmw_fallback_wait(struct vmw_private *dev_priv,
209 bool lazy,
210 bool fifo_idle,
211 uint32_t seqno,
212 bool interruptible,
213 unsigned long timeout)
214 {
215 struct vmw_fifo_state *fifo_state = &dev_priv->fifo;
216
217 uint32_t count = 0;
218 uint32_t signal_seq;
219 int ret;
220 unsigned long end_jiffies = jiffies + timeout;
221 bool (*wait_condition)(struct vmw_private *, uint32_t);
222 #ifndef __NetBSD__
223 DEFINE_WAIT(__wait);
224 #endif
225
226 wait_condition = (fifo_idle) ? &vmw_fifo_idle :
227 &vmw_seqno_passed;
228
229 /**
230 * Block command submission while waiting for idle.
231 */
232
233 if (fifo_idle) {
234 down_read(&fifo_state->rwsem);
235 if (dev_priv->cman) {
236 ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible,
237 10*HZ);
238 if (ret)
239 goto out_err;
240 }
241 }
242
243 spin_lock(&dev_priv->fence_lock);
244
245 signal_seq = atomic_read(&dev_priv->marker_seq);
246 ret = 0;
247
248 for (;;) {
249 #ifdef __NetBSD__
250 if (!lazy) {
251 if (wait_condition(dev_priv, seqno))
252 break;
253 spin_unlock(&dev_priv->fence_lock);
254 if ((++count & 0xf) == 0)
255 yield();
256 spin_lock(&dev_priv->fence_lock);
257 } else if (interruptible) {
258 DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fence_queue,
259 &dev_priv->fence_lock, /*timeout*/1,
260 wait_condition(dev_priv, seqno));
261 } else {
262 DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret,
263 &dev_priv->fence_queue,
264 &dev_priv->fence_lock, /*timeout*/1,
265 wait_condition(dev_priv, seqno));
266 }
267 if (ret) { /* success or error but not timeout */
268 if (ret > 0) /* success */
269 ret = 0;
270 break;
271 }
272 if (time_after_eq(jiffies, end_jiffies)) {
273 DRM_ERROR("SVGA device lockup.\n");
274 break;
275 }
276 #else
277 prepare_to_wait(&dev_priv->fence_queue, &__wait,
278 (interruptible) ?
279 TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
280 if (wait_condition(dev_priv, seqno))
281 break;
282 if (time_after_eq(jiffies, end_jiffies)) {
283 DRM_ERROR("SVGA device lockup.\n");
284 break;
285 }
286 if (lazy)
287 schedule_timeout(1);
288 else if ((++count & 0x0F) == 0) {
289 /**
290 * FIXME: Use schedule_hr_timeout here for
291 * newer kernels and lower CPU utilization.
292 */
293
294 __set_current_state(TASK_RUNNING);
295 schedule();
296 __set_current_state((interruptible) ?
297 TASK_INTERRUPTIBLE :
298 TASK_UNINTERRUPTIBLE);
299 }
300 if (interruptible && signal_pending(current)) {
301 ret = -ERESTARTSYS;
302 break;
303 }
304 #endif
305 }
306 #ifndef __NetBSD__
307 finish_wait(&dev_priv->fence_queue, &__wait);
308 #endif
309 if (ret == 0 && fifo_idle) {
310 u32 *fifo_mem = dev_priv->mmio_virt;
311
312 vmw_mmio_write(signal_seq, fifo_mem + SVGA_FIFO_FENCE);
313 }
314 #ifdef __NetBSD__
315 DRM_SPIN_WAKEUP_ALL(&dev_priv->fence_queue, &dev_priv->fence_lock);
316 spin_unlock(&dev_priv->fence_lock);
317 #else
318 wake_up_all(&dev_priv->fence_queue);
319 #endif
320 out_err:
321 if (fifo_idle)
322 up_read(&fifo_state->rwsem);
323
324 return ret;
325 }
326
vmw_generic_waiter_add(struct vmw_private * dev_priv,u32 flag,int * waiter_count)327 void vmw_generic_waiter_add(struct vmw_private *dev_priv,
328 u32 flag, int *waiter_count)
329 {
330 spin_lock_bh(&dev_priv->waiter_lock);
331 if ((*waiter_count)++ == 0) {
332 #ifdef __NetBSD__
333 bus_space_write_4(dev_priv->iot, dev_priv->ioh,
334 VMWGFX_IRQSTATUS_PORT, flag);
335 #else
336 outl(flag, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
337 #endif
338 dev_priv->irq_mask |= flag;
339 vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
340 }
341 spin_unlock_bh(&dev_priv->waiter_lock);
342 }
343
vmw_generic_waiter_remove(struct vmw_private * dev_priv,u32 flag,int * waiter_count)344 void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
345 u32 flag, int *waiter_count)
346 {
347 spin_lock_bh(&dev_priv->waiter_lock);
348 if (--(*waiter_count) == 0) {
349 dev_priv->irq_mask &= ~flag;
350 vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask);
351 }
352 spin_unlock_bh(&dev_priv->waiter_lock);
353 }
354
vmw_seqno_waiter_add(struct vmw_private * dev_priv)355 void vmw_seqno_waiter_add(struct vmw_private *dev_priv)
356 {
357 vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
358 &dev_priv->fence_queue_waiters);
359 }
360
vmw_seqno_waiter_remove(struct vmw_private * dev_priv)361 void vmw_seqno_waiter_remove(struct vmw_private *dev_priv)
362 {
363 vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE,
364 &dev_priv->fence_queue_waiters);
365 }
366
vmw_goal_waiter_add(struct vmw_private * dev_priv)367 void vmw_goal_waiter_add(struct vmw_private *dev_priv)
368 {
369 vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
370 &dev_priv->goal_queue_waiters);
371 }
372
vmw_goal_waiter_remove(struct vmw_private * dev_priv)373 void vmw_goal_waiter_remove(struct vmw_private *dev_priv)
374 {
375 vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL,
376 &dev_priv->goal_queue_waiters);
377 }
378
vmw_wait_seqno(struct vmw_private * dev_priv,bool lazy,uint32_t seqno,bool interruptible,unsigned long timeout)379 int vmw_wait_seqno(struct vmw_private *dev_priv,
380 bool lazy, uint32_t seqno,
381 bool interruptible, unsigned long timeout)
382 {
383 long ret;
384 struct vmw_fifo_state *fifo = &dev_priv->fifo;
385
386 spin_lock(&dev_priv->fence_lock);
387 if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) {
388 spin_unlock(&dev_priv->fence_lock);
389 return 0;
390 }
391
392 if (likely(vmw_seqno_passed(dev_priv, seqno))) {
393 spin_unlock(&dev_priv->fence_lock);
394 return 0;
395 }
396
397 vmw_fifo_ping_host(dev_priv, SVGA_SYNC_GENERIC);
398
399 if (!(fifo->capabilities & SVGA_FIFO_CAP_FENCE)) {
400 spin_unlock(&dev_priv->fence_lock);
401 return vmw_fallback_wait(dev_priv, lazy, true, seqno,
402 interruptible, timeout);
403 }
404
405 if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) {
406 spin_unlock(&dev_priv->fence_lock);
407 return vmw_fallback_wait(dev_priv, lazy, false, seqno,
408 interruptible, timeout);
409 }
410
411 vmw_seqno_waiter_add(dev_priv);
412
413 if (interruptible)
414 DRM_SPIN_TIMED_WAIT_UNTIL(ret, &dev_priv->fence_queue,
415 &dev_priv->fence_lock, timeout,
416 vmw_seqno_passed(dev_priv, seqno));
417 else
418 DRM_SPIN_TIMED_WAIT_NOINTR_UNTIL(ret, &dev_priv->fence_queue,
419 &dev_priv->fence_lock, timeout,
420 vmw_seqno_passed(dev_priv, seqno));
421
422 vmw_seqno_waiter_remove(dev_priv);
423
424 spin_unlock(&dev_priv->fence_lock);
425
426 if (unlikely(ret == 0))
427 ret = -EBUSY;
428 else if (likely(ret > 0))
429 ret = 0;
430
431 return ret;
432 }
433
vmw_irq_preinstall(struct drm_device * dev)434 static void vmw_irq_preinstall(struct drm_device *dev)
435 {
436 struct vmw_private *dev_priv = vmw_priv(dev);
437 uint32_t status;
438
439 #ifdef __NetBSD__
440 status = bus_space_read_4(dev_priv->iot, dev_priv->ioh,
441 VMWGFX_IRQSTATUS_PORT);
442 bus_space_write_4(dev_priv->iot, dev_priv->ioh, VMWGFX_IRQSTATUS_PORT,
443 status);
444 #else
445 status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
446 outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
447 #endif
448 }
449
vmw_irq_uninstall(struct drm_device * dev)450 void vmw_irq_uninstall(struct drm_device *dev)
451 {
452 struct vmw_private *dev_priv = vmw_priv(dev);
453 uint32_t status;
454
455 if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK))
456 return;
457
458 if (!dev->irq_enabled)
459 return;
460
461 vmw_write(dev_priv, SVGA_REG_IRQMASK, 0);
462
463 #ifdef __NetBSD__
464 status = bus_space_read_4(dev_priv->iot, dev_priv->ioh,
465 VMWGFX_IRQSTATUS_PORT);
466 bus_space_write_4(dev_priv->iot, dev_priv->ioh, VMWGFX_IRQSTATUS_PORT,
467 status);
468 #else
469 status = inl(dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
470 outl(status, dev_priv->io_start + VMWGFX_IRQSTATUS_PORT);
471 #endif
472
473 dev->irq_enabled = false;
474 #ifdef __NetBSD__
475 int ret = drm_irq_uninstall(dev);
476 KASSERT(ret == 0);
477 workqueue_destroy(dev_priv->irqthread_wq);
478 #else
479 free_irq(dev->irq, dev);
480 #endif
481 }
482
483 /**
484 * vmw_irq_install - Install the irq handlers
485 *
486 * @dev: Pointer to the drm device.
487 * @irq: The irq number.
488 * Return: Zero if successful. Negative number otherwise.
489 */
vmw_irq_install(struct drm_device * dev,int irq)490 int vmw_irq_install(struct drm_device *dev, int irq)
491 {
492 int ret;
493
494 if (dev->irq_enabled)
495 return -EBUSY;
496
497 vmw_irq_preinstall(dev);
498
499 #ifdef __NetBSD__
500 /* XXX errno NetBSD->Linux */
501 ret = -workqueue_create(&vmw_priv(dev)->irqthread_wq, "vmwgfirq",
502 vmw_thread_fn, dev, PRI_NONE, IPL_DRM, WQ_MPSAFE);
503 if (ret < 0)
504 return ret;
505 ret = drm_irq_install(dev);
506 if (ret < 0) {
507 workqueue_destroy(vmw_priv(dev)->irqthread_wq);
508 vmw_priv(dev)->irqthread_wq = NULL;
509 }
510 #else
511 ret = request_threaded_irq(irq, vmw_irq_handler, vmw_thread_fn,
512 IRQF_SHARED, VMWGFX_DRIVER_NAME, dev);
513 #endif
514 if (ret < 0)
515 return ret;
516
517 dev->irq_enabled = true;
518 dev->irq = irq;
519
520 return ret;
521 }
522