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__
53static void
54vmw_thread_fn(struct work *work, void *arg)
55#else
56static 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 */
99static 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
156static 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
162void 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
177bool 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
208int 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
320out_err:
321	if (fifo_idle)
322		up_read(&fifo_state->rwsem);
323
324	return ret;
325}
326
327void 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
344void 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
355void 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
361void 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
367void 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
373void 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
379int 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
434static 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
450void 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 */
490int 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