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