Home | History | Annotate | Line # | Download | only in vmwgfx
      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
     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  */
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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  */
    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