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