1 /*- 2 * Copyright 2003 Eric Anholt 3 * All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * ERIC ANHOLT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Eric Anholt <anholt@FreeBSD.org> 25 * 26 * $FreeBSD: src/sys/dev/drm2/drm_irq.c,v 1.1 2012/05/22 11:07:44 kib Exp $ 27 */ 28 29 /** @file drm_irq.c 30 * Support code for handling setup/teardown of interrupt handlers and 31 * handing interrupt handlers off to the drivers. 32 */ 33 34 #include <linux/export.h> 35 #include <linux/mutex.h> 36 #include <linux/time.h> 37 #include <linux/timer.h> 38 #include <drm/drmP.h> 39 40 MALLOC_DEFINE(DRM_MEM_VBLANK, "drm_vblank", "DRM VBLANK Handling Data"); 41 42 /* Access macro for slots in vblank timestamp ringbuffer. */ 43 #define vblanktimestamp(dev, crtc, count) ( \ 44 (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ 45 ((count) % DRM_VBLANKTIME_RBSIZE)]) 46 47 /* Retry timestamp calculation up to 3 times to satisfy 48 * drm_timestamp_precision before giving up. 49 */ 50 #define DRM_TIMESTAMP_MAXRETRIES 3 51 52 /* Threshold in nanoseconds for detection of redundant 53 * vblank irq in drm_handle_vblank(). 1 msec should be ok. 54 */ 55 #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 56 57 int drm_irq_by_busid(struct drm_device *dev, void *data, 58 struct drm_file *file_priv) 59 { 60 struct drm_irq_busid *irq = data; 61 62 if ((irq->busnum >> 8) != dev->pci_domain || 63 (irq->busnum & 0xff) != dev->pci_bus || 64 irq->devnum != dev->pci_slot || 65 irq->funcnum != dev->pci_func) 66 return EINVAL; 67 68 irq->irq = dev->irq; 69 70 DRM_DEBUG("%d:%d:%d => IRQ %d\n", 71 irq->busnum, irq->devnum, irq->funcnum, irq->irq); 72 73 return 0; 74 } 75 76 /* 77 * Clear vblank timestamp buffer for a crtc. 78 */ 79 static void clear_vblank_timestamps(struct drm_device *dev, int crtc) 80 { 81 memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, 82 DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval)); 83 } 84 85 static int64_t 86 abs64(int64_t x) 87 { 88 89 return (x < 0 ? -x : x); 90 } 91 92 /* 93 * Disable vblank irq's on crtc, make sure that last vblank count 94 * of hardware and corresponding consistent software vblank counter 95 * are preserved, even if there are any spurious vblank irq's after 96 * disable. 97 */ 98 static void vblank_disable_and_save(struct drm_device *dev, int crtc) 99 { 100 u32 vblcount; 101 int64_t diff_ns; 102 int vblrc; 103 struct timeval tvblank; 104 105 /* Prevent vblank irq processing while disabling vblank irqs, 106 * so no updates of timestamps or count can happen after we've 107 * disabled. Needed to prevent races in case of delayed irq's. 108 */ 109 lockmgr(&dev->vblank_time_lock, LK_EXCLUSIVE); 110 111 dev->driver->disable_vblank(dev, crtc); 112 dev->vblank_enabled[crtc] = 0; 113 114 /* No further vblank irq's will be processed after 115 * this point. Get current hardware vblank count and 116 * vblank timestamp, repeat until they are consistent. 117 * 118 * FIXME: There is still a race condition here and in 119 * drm_update_vblank_count() which can cause off-by-one 120 * reinitialization of software vblank counter. If gpu 121 * vblank counter doesn't increment exactly at the leading 122 * edge of a vblank interval, then we can lose 1 count if 123 * we happen to execute between start of vblank and the 124 * delayed gpu counter increment. 125 */ 126 do { 127 dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); 128 vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); 129 } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc)); 130 131 /* Compute time difference to stored timestamp of last vblank 132 * as updated by last invocation of drm_handle_vblank() in vblank irq. 133 */ 134 vblcount = atomic_read(&dev->_vblank_count[crtc]); 135 diff_ns = timeval_to_ns(&tvblank) - 136 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); 137 138 /* If there is at least 1 msec difference between the last stored 139 * timestamp and tvblank, then we are currently executing our 140 * disable inside a new vblank interval, the tvblank timestamp 141 * corresponds to this new vblank interval and the irq handler 142 * for this vblank didn't run yet and won't run due to our disable. 143 * Therefore we need to do the job of drm_handle_vblank() and 144 * increment the vblank counter by one to account for this vblank. 145 * 146 * Skip this step if there isn't any high precision timestamp 147 * available. In that case we can't account for this and just 148 * hope for the best. 149 */ 150 if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { 151 atomic_inc(&dev->_vblank_count[crtc]); 152 } 153 154 /* Invalidate all timestamps while vblank irq's are off. */ 155 clear_vblank_timestamps(dev, crtc); 156 157 lockmgr(&dev->vblank_time_lock, LK_RELEASE); 158 } 159 160 static void vblank_disable_fn(unsigned long arg) 161 { 162 struct drm_device *dev = (struct drm_device *)arg; 163 int i; 164 165 if (!dev->vblank_disable_allowed) 166 return; 167 168 for (i = 0; i < dev->num_crtcs; i++) { 169 lockmgr(&dev->vbl_lock, LK_EXCLUSIVE); 170 if (atomic_read(&dev->vblank_refcount[i]) == 0 && 171 dev->vblank_enabled[i]) { 172 DRM_DEBUG("disabling vblank on crtc %d\n", i); 173 vblank_disable_and_save(dev, i); 174 } 175 lockmgr(&dev->vbl_lock, LK_RELEASE); 176 } 177 } 178 179 void drm_vblank_cleanup(struct drm_device *dev) 180 { 181 /* Bail if the driver didn't call drm_vblank_init() */ 182 if (dev->num_crtcs == 0) 183 return; 184 185 del_timer_sync(&dev->vblank_disable_timer); 186 187 vblank_disable_fn((unsigned long)dev); 188 189 drm_free(dev->_vblank_count, DRM_MEM_VBLANK); 190 drm_free(dev->vblank_refcount, DRM_MEM_VBLANK); 191 drm_free(dev->vblank_enabled, DRM_MEM_VBLANK); 192 drm_free(dev->last_vblank, DRM_MEM_VBLANK); 193 drm_free(dev->last_vblank_wait, DRM_MEM_VBLANK); 194 drm_free(dev->vblank_inmodeset, DRM_MEM_VBLANK); 195 drm_free(dev->_vblank_time, DRM_MEM_VBLANK); 196 197 dev->num_crtcs = 0; 198 } 199 EXPORT_SYMBOL(drm_vblank_cleanup); 200 201 int drm_vblank_init(struct drm_device *dev, int num_crtcs) 202 { 203 int i; 204 205 setup_timer(&dev->vblank_disable_timer, vblank_disable_fn, 206 (unsigned long)dev); 207 lockinit(&dev->vblank_time_lock, "drmvtl", 0, LK_CANRECURSE); 208 209 dev->num_crtcs = num_crtcs; 210 211 dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, 212 DRM_MEM_VBLANK, M_WAITOK); 213 214 dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, 215 DRM_MEM_VBLANK, M_WAITOK); 216 dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs, 217 DRM_MEM_VBLANK, M_WAITOK); 218 dev->vblank_enabled = kmalloc(num_crtcs * sizeof(int), 219 DRM_MEM_VBLANK, M_WAITOK | M_ZERO); 220 dev->last_vblank = kmalloc(num_crtcs * sizeof(u32), 221 DRM_MEM_VBLANK, M_WAITOK | M_ZERO); 222 dev->last_vblank_wait = kmalloc(num_crtcs * sizeof(u32), 223 DRM_MEM_VBLANK, M_WAITOK | M_ZERO); 224 dev->vblank_inmodeset = kmalloc(num_crtcs * sizeof(int), 225 DRM_MEM_VBLANK, M_WAITOK | M_ZERO); 226 dev->_vblank_time = kmalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE * 227 sizeof(struct timeval), DRM_MEM_VBLANK, M_WAITOK | M_ZERO); 228 DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); 229 230 /* Driver specific high-precision vblank timestamping supported? */ 231 if (dev->driver->get_vblank_timestamp) 232 DRM_INFO("Driver supports precise vblank timestamp query.\n"); 233 else 234 DRM_INFO("No driver support for vblank timestamp query.\n"); 235 236 /* Zero per-crtc vblank stuff */ 237 for (i = 0; i < num_crtcs; i++) { 238 init_waitqueue_head(&dev->vbl_queue[i]); 239 atomic_set(&dev->_vblank_count[i], 0); 240 atomic_set(&dev->vblank_refcount[i], 0); 241 } 242 243 dev->vblank_disable_allowed = 0; 244 return 0; 245 } 246 EXPORT_SYMBOL(drm_vblank_init); 247 248 /** 249 * Install IRQ handler. 250 * 251 * \param dev DRM device. 252 * 253 * Initializes the IRQ related data. Installs the handler, calling the driver 254 * \c irq_preinstall() and \c irq_postinstall() functions 255 * before and after the installation. 256 */ 257 int drm_irq_install(struct drm_device *dev) 258 { 259 int ret; 260 261 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 262 return -EINVAL; 263 264 if (dev->irq == 0) 265 return -EINVAL; 266 267 DRM_LOCK(dev); 268 269 /* Driver must have been initialized */ 270 if (!dev->dev_private) { 271 DRM_UNLOCK(dev); 272 return -EINVAL; 273 } 274 275 if (dev->irq_enabled) { 276 DRM_UNLOCK(dev); 277 return -EBUSY; 278 } 279 dev->irq_enabled = 1; 280 DRM_UNLOCK(dev); 281 282 DRM_DEBUG("irq=%d\n", dev->irq); 283 284 /* Before installing handler */ 285 if (dev->driver->irq_preinstall) 286 dev->driver->irq_preinstall(dev); 287 288 /* Install handler */ 289 ret = bus_setup_intr(dev->dev, dev->irqr, INTR_MPSAFE, 290 dev->driver->irq_handler, dev, &dev->irqh, &dev->irq_lock); 291 292 if (ret != 0) { 293 DRM_LOCK(dev); 294 dev->irq_enabled = 0; 295 DRM_UNLOCK(dev); 296 return ret; 297 } 298 299 /* After installing handler */ 300 if (dev->driver->irq_postinstall) 301 ret = dev->driver->irq_postinstall(dev); 302 303 if (ret < 0) { 304 DRM_LOCK(dev); 305 dev->irq_enabled = 0; 306 DRM_UNLOCK(dev); 307 bus_teardown_intr(dev->dev, dev->irqr, dev->irqh); 308 } 309 310 return ret; 311 } 312 EXPORT_SYMBOL(drm_irq_install); 313 314 /** 315 * Uninstall the IRQ handler. 316 * 317 * \param dev DRM device. 318 * 319 * Calls the driver's \c irq_uninstall() function, and stops the irq. 320 */ 321 int drm_irq_uninstall(struct drm_device *dev) 322 { 323 int irq_enabled, i; 324 325 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 326 return -EINVAL; 327 328 DRM_LOCK(dev); 329 irq_enabled = dev->irq_enabled; 330 dev->irq_enabled = 0; 331 DRM_UNLOCK(dev); 332 333 /* 334 * Wake up any waiters so they don't hang. 335 */ 336 if (dev->num_crtcs) { 337 lockmgr(&dev->vbl_lock, LK_EXCLUSIVE); 338 for (i = 0; i < dev->num_crtcs; i++) { 339 DRM_WAKEUP(&dev->vbl_queue[i]); 340 dev->vblank_enabled[i] = 0; 341 dev->last_vblank[i] = 342 dev->driver->get_vblank_counter(dev, i); 343 } 344 lockmgr(&dev->vbl_lock, LK_RELEASE); 345 } 346 347 if (!irq_enabled) 348 return -EINVAL; 349 350 DRM_DEBUG("irq=%d\n", dev->irq); 351 352 if (dev->driver->irq_uninstall) 353 dev->driver->irq_uninstall(dev); 354 355 bus_teardown_intr(dev->dev, dev->irqr, dev->irqh); 356 357 return 0; 358 } 359 EXPORT_SYMBOL(drm_irq_uninstall); 360 361 /** 362 * IRQ control ioctl. 363 * 364 * \param inode device inode. 365 * \param file_priv DRM file private. 366 * \param cmd command. 367 * \param arg user argument, pointing to a drm_control structure. 368 * \return zero on success or a negative number on failure. 369 * 370 * Calls irq_install() or irq_uninstall() according to \p arg. 371 */ 372 int drm_control(struct drm_device *dev, void *data, 373 struct drm_file *file_priv) 374 { 375 struct drm_control *ctl = data; 376 377 /* if we haven't irq we fallback for compatibility reasons - 378 * this used to be a separate function in drm_dma.h 379 */ 380 381 382 switch (ctl->func) { 383 case DRM_INST_HANDLER: 384 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 385 return 0; 386 if (drm_core_check_feature(dev, DRIVER_MODESET)) 387 return 0; 388 if (dev->if_version < DRM_IF_VERSION(1, 2) && 389 ctl->irq != dev->irq) 390 return -EINVAL; 391 return drm_irq_install(dev); 392 case DRM_UNINST_HANDLER: 393 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 394 return 0; 395 if (drm_core_check_feature(dev, DRIVER_MODESET)) 396 return 0; 397 return drm_irq_uninstall(dev); 398 default: 399 return -EINVAL; 400 } 401 } 402 403 void 404 drm_calc_timestamping_constants(struct drm_crtc *crtc) 405 { 406 int64_t linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; 407 uint64_t dotclock; 408 409 /* Dot clock in Hz: */ 410 dotclock = (uint64_t) crtc->hwmode.clock * 1000; 411 412 /* Fields of interlaced scanout modes are only halve a frame duration. 413 * Double the dotclock to get halve the frame-/line-/pixelduration. 414 */ 415 if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE) 416 dotclock *= 2; 417 418 /* Valid dotclock? */ 419 if (dotclock > 0) { 420 /* Convert scanline length in pixels and video dot clock to 421 * line duration, frame duration and pixel duration in 422 * nanoseconds: 423 */ 424 pixeldur_ns = (int64_t)1000000000 / dotclock; 425 linedur_ns = ((uint64_t)crtc->hwmode.crtc_htotal * 426 1000000000) / dotclock; 427 framedur_ns = (int64_t)crtc->hwmode.crtc_vtotal * linedur_ns; 428 } else 429 DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", 430 crtc->base.id); 431 432 crtc->pixeldur_ns = pixeldur_ns; 433 crtc->linedur_ns = linedur_ns; 434 crtc->framedur_ns = framedur_ns; 435 436 DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", 437 crtc->base.id, crtc->hwmode.crtc_htotal, 438 crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay); 439 DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", 440 crtc->base.id, (int) dotclock/1000, (int) framedur_ns, 441 (int) linedur_ns, (int) pixeldur_ns); 442 } 443 444 /** 445 * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms 446 * drivers. Implements calculation of exact vblank timestamps from 447 * given drm_display_mode timings and current video scanout position 448 * of a crtc. This can be called from within get_vblank_timestamp() 449 * implementation of a kms driver to implement the actual timestamping. 450 * 451 * Should return timestamps conforming to the OML_sync_control OpenML 452 * extension specification. The timestamp corresponds to the end of 453 * the vblank interval, aka start of scanout of topmost-leftmost display 454 * pixel in the following video frame. 455 * 456 * Requires support for optional dev->driver->get_scanout_position() 457 * in kms driver, plus a bit of setup code to provide a drm_display_mode 458 * that corresponds to the true scanout timing. 459 * 460 * The current implementation only handles standard video modes. It 461 * returns as no operation if a doublescan or interlaced video mode is 462 * active. Higher level code is expected to handle this. 463 * 464 * @dev: DRM device. 465 * @crtc: Which crtc's vblank timestamp to retrieve. 466 * @max_error: Desired maximum allowable error in timestamps (nanosecs). 467 * On return contains true maximum error of timestamp. 468 * @vblank_time: Pointer to struct timeval which should receive the timestamp. 469 * @flags: Flags to pass to driver: 470 * 0 = Default. 471 * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. 472 * @refcrtc: drm_crtc* of crtc which defines scanout timing. 473 * 474 * Returns negative value on error, failure or if not supported in current 475 * video mode: 476 * 477 * -EINVAL - Invalid crtc. 478 * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. 479 * -ENOTSUPP - Function not supported in current display mode. 480 * -EIO - Failed, e.g., due to failed scanout position query. 481 * 482 * Returns or'ed positive status flags on success: 483 * 484 * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. 485 * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. 486 * 487 */ 488 int 489 drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, 490 int *max_error, struct timeval *vblank_time, unsigned flags, 491 struct drm_crtc *refcrtc) 492 { 493 struct timeval stime, raw_time; 494 struct drm_display_mode *mode; 495 int vbl_status, vtotal, vdisplay; 496 int vpos, hpos, i; 497 int64_t framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; 498 bool invbl; 499 500 if (crtc < 0 || crtc >= dev->num_crtcs) { 501 DRM_ERROR("Invalid crtc %d\n", crtc); 502 return -EINVAL; 503 } 504 505 /* Scanout position query not supported? Should not happen. */ 506 if (!dev->driver->get_scanout_position) { 507 DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); 508 return -EIO; 509 } 510 511 mode = &refcrtc->hwmode; 512 vtotal = mode->crtc_vtotal; 513 vdisplay = mode->crtc_vdisplay; 514 515 /* Durations of frames, lines, pixels in nanoseconds. */ 516 framedur_ns = refcrtc->framedur_ns; 517 linedur_ns = refcrtc->linedur_ns; 518 pixeldur_ns = refcrtc->pixeldur_ns; 519 520 /* If mode timing undefined, just return as no-op: 521 * Happens during initial modesetting of a crtc. 522 */ 523 if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { 524 DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); 525 return -EAGAIN; 526 } 527 528 /* Get current scanout position with system timestamp. 529 * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times 530 * if single query takes longer than max_error nanoseconds. 531 * 532 * This guarantees a tight bound on maximum error if 533 * code gets preempted or delayed for some reason. 534 */ 535 for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { 536 /* Disable preemption to make it very likely to 537 * succeed in the first iteration. 538 */ 539 crit_enter(); 540 541 /* Get system timestamp before query. */ 542 getmicrouptime(&stime); 543 544 /* Get vertical and horizontal scanout pos. vpos, hpos. */ 545 vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); 546 547 /* Get system timestamp after query. */ 548 getmicrouptime(&raw_time); 549 550 crit_exit(); 551 552 /* Return as no-op if scanout query unsupported or failed. */ 553 if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { 554 DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", 555 crtc, vbl_status); 556 return -EIO; 557 } 558 559 duration_ns = timeval_to_ns(&raw_time) - timeval_to_ns(&stime); 560 561 /* Accept result with < max_error nsecs timing uncertainty. */ 562 if (duration_ns <= (int64_t) *max_error) 563 break; 564 } 565 566 /* Noisy system timing? */ 567 if (i == DRM_TIMESTAMP_MAXRETRIES) { 568 DRM_DEBUG("crtc %d: Noisy timestamp %d us > %d us [%d reps].\n", 569 crtc, (int) duration_ns/1000, *max_error/1000, i); 570 } 571 572 /* Return upper bound of timestamp precision error. */ 573 *max_error = (int) duration_ns; 574 575 /* Check if in vblank area: 576 * vpos is >=0 in video scanout area, but negative 577 * within vblank area, counting down the number of lines until 578 * start of scanout. 579 */ 580 invbl = vbl_status & DRM_SCANOUTPOS_INVBL; 581 582 /* Convert scanout position into elapsed time at raw_time query 583 * since start of scanout at first display scanline. delta_ns 584 * can be negative if start of scanout hasn't happened yet. 585 */ 586 delta_ns = (int64_t)vpos * linedur_ns + (int64_t)hpos * pixeldur_ns; 587 588 /* Is vpos outside nominal vblank area, but less than 589 * 1/100 of a frame height away from start of vblank? 590 * If so, assume this isn't a massively delayed vblank 591 * interrupt, but a vblank interrupt that fired a few 592 * microseconds before true start of vblank. Compensate 593 * by adding a full frame duration to the final timestamp. 594 * Happens, e.g., on ATI R500, R600. 595 * 596 * We only do this if DRM_CALLED_FROM_VBLIRQ. 597 */ 598 if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl && 599 ((vdisplay - vpos) < vtotal / 100)) { 600 delta_ns = delta_ns - framedur_ns; 601 602 /* Signal this correction as "applied". */ 603 vbl_status |= 0x8; 604 } 605 606 /* Subtract time delta from raw timestamp to get final 607 * vblank_time timestamp for end of vblank. 608 */ 609 *vblank_time = ns_to_timeval(timeval_to_ns(&raw_time) - delta_ns); 610 611 DRM_DEBUG("crtc %d : v %d p(%d,%d)@ %jd.%jd -> %jd.%jd [e %d us, %d rep]\n", 612 crtc, (int)vbl_status, hpos, vpos, (uintmax_t)raw_time.tv_sec, 613 (uintmax_t)raw_time.tv_usec, (uintmax_t)vblank_time->tv_sec, 614 (uintmax_t)vblank_time->tv_usec, (int)duration_ns/1000, i); 615 616 vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; 617 if (invbl) 618 vbl_status |= DRM_VBLANKTIME_INVBL; 619 620 return vbl_status; 621 } 622 623 static struct timeval get_drm_timestamp(void) 624 { 625 struct timeval now; 626 627 getmicrouptime(&now); 628 629 return now; 630 } 631 632 /** 633 * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent 634 * vblank interval. 635 * 636 * @dev: DRM device 637 * @crtc: which crtc's vblank timestamp to retrieve 638 * @tvblank: Pointer to target struct timeval which should receive the timestamp 639 * @flags: Flags to pass to driver: 640 * 0 = Default. 641 * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. 642 * 643 * Fetches the system timestamp corresponding to the time of the most recent 644 * vblank interval on specified crtc. May call into kms-driver to 645 * compute the timestamp with a high-precision GPU specific method. 646 * 647 * Returns zero if timestamp originates from uncorrected do_gettimeofday() 648 * call, i.e., it isn't very precisely locked to the true vblank. 649 * 650 * Returns non-zero if timestamp is considered to be very precise. 651 */ 652 u32 drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, 653 struct timeval *tvblank, unsigned flags) 654 { 655 int ret = 0; 656 657 /* Define requested maximum error on timestamps (nanoseconds). */ 658 int max_error = (int) drm_timestamp_precision * 1000; 659 660 /* Query driver if possible and precision timestamping enabled. */ 661 if (dev->driver->get_vblank_timestamp && (max_error > 0)) { 662 ret = dev->driver->get_vblank_timestamp(dev, crtc, &max_error, 663 tvblank, flags); 664 if (ret > 0) 665 return (u32) ret; 666 } 667 668 /* GPU high precision timestamp query unsupported or failed. 669 * Return gettimeofday timestamp as best estimate. 670 */ 671 microtime(tvblank); 672 673 return 0; 674 } 675 676 /** 677 * drm_vblank_count - retrieve "cooked" vblank counter value 678 * @dev: DRM device 679 * @crtc: which counter to retrieve 680 * 681 * Fetches the "cooked" vblank count value that represents the number of 682 * vblank events since the system was booted, including lost events due to 683 * modesetting activity. 684 */ 685 u32 drm_vblank_count(struct drm_device *dev, int crtc) 686 { 687 return atomic_read(&dev->_vblank_count[crtc]); 688 } 689 690 /** 691 * drm_vblank_count_and_time - retrieve "cooked" vblank counter value 692 * and the system timestamp corresponding to that vblank counter value. 693 * 694 * @dev: DRM device 695 * @crtc: which counter to retrieve 696 * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. 697 * 698 * Fetches the "cooked" vblank count value that represents the number of 699 * vblank events since the system was booted, including lost events due to 700 * modesetting activity. Returns corresponding system timestamp of the time 701 * of the vblank interval that corresponds to the current value vblank counter 702 * value. 703 */ 704 u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, 705 struct timeval *vblanktime) 706 { 707 u32 cur_vblank; 708 709 /* Read timestamp from slot of _vblank_time ringbuffer 710 * that corresponds to current vblank count. Retry if 711 * count has incremented during readout. This works like 712 * a seqlock. 713 */ 714 do { 715 cur_vblank = atomic_read(&dev->_vblank_count[crtc]); 716 *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); 717 cpu_lfence(); 718 } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); 719 720 return cur_vblank; 721 } 722 723 static void send_vblank_event(struct drm_device *dev, 724 struct drm_pending_vblank_event *e, 725 unsigned long seq, struct timeval *now) 726 { 727 KKASSERT(mutex_is_locked(&dev->event_lock)); 728 e->event.sequence = seq; 729 e->event.tv_sec = now->tv_sec; 730 e->event.tv_usec = now->tv_usec; 731 732 list_add_tail(&e->base.link, 733 &e->base.file_priv->event_list); 734 wakeup(&e->base.file_priv->event_list); 735 #if 0 736 trace_drm_vblank_event_delivered(e->base.pid, e->pipe, 737 e->event.sequence); 738 #endif 739 } 740 741 /** 742 * drm_send_vblank_event - helper to send vblank event after pageflip 743 * @dev: DRM device 744 * @crtc: CRTC in question 745 * @e: the event to send 746 * 747 * Updates sequence # and timestamp on event, and sends it to userspace. 748 * Caller must hold event lock. 749 */ 750 void drm_send_vblank_event(struct drm_device *dev, int crtc, 751 struct drm_pending_vblank_event *e) 752 { 753 struct timeval now; 754 unsigned int seq; 755 if (crtc >= 0) { 756 seq = drm_vblank_count_and_time(dev, crtc, &now); 757 } else { 758 seq = 0; 759 760 now = get_drm_timestamp(); 761 } 762 e->pipe = crtc; 763 send_vblank_event(dev, e, seq, &now); 764 } 765 EXPORT_SYMBOL(drm_send_vblank_event); 766 767 /** 768 * drm_update_vblank_count - update the master vblank counter 769 * @dev: DRM device 770 * @crtc: counter to update 771 * 772 * Call back into the driver to update the appropriate vblank counter 773 * (specified by @crtc). Deal with wraparound, if it occurred, and 774 * update the last read value so we can deal with wraparound on the next 775 * call if necessary. 776 * 777 * Only necessary when going from off->on, to account for frames we 778 * didn't get an interrupt for. 779 * 780 * Note: caller must hold dev->vbl_lock since this reads & writes 781 * device vblank fields. 782 */ 783 static void drm_update_vblank_count(struct drm_device *dev, int crtc) 784 { 785 u32 cur_vblank, diff, tslot, rc; 786 struct timeval t_vblank; 787 788 /* 789 * Interrupts were disabled prior to this call, so deal with counter 790 * wrap if needed. 791 * NOTE! It's possible we lost a full dev->max_vblank_count events 792 * here if the register is small or we had vblank interrupts off for 793 * a long time. 794 * 795 * We repeat the hardware vblank counter & timestamp query until 796 * we get consistent results. This to prevent races between gpu 797 * updating its hardware counter while we are retrieving the 798 * corresponding vblank timestamp. 799 */ 800 do { 801 cur_vblank = dev->driver->get_vblank_counter(dev, crtc); 802 rc = drm_get_last_vbltimestamp(dev, crtc, &t_vblank, 0); 803 } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); 804 805 /* Deal with counter wrap */ 806 diff = cur_vblank - dev->last_vblank[crtc]; 807 if (cur_vblank < dev->last_vblank[crtc]) { 808 diff += dev->max_vblank_count; 809 810 DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", 811 crtc, dev->last_vblank[crtc], cur_vblank, diff); 812 } 813 814 DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 815 crtc, diff); 816 817 /* Reinitialize corresponding vblank timestamp if high-precision query 818 * available. Skip this step if query unsupported or failed. Will 819 * reinitialize delayed at next vblank interrupt in that case. 820 */ 821 if (rc) { 822 tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; 823 vblanktimestamp(dev, crtc, tslot) = t_vblank; 824 } 825 826 atomic_add(diff, &dev->_vblank_count[crtc]); 827 } 828 829 /** 830 * drm_vblank_get - get a reference count on vblank events 831 * @dev: DRM device 832 * @crtc: which CRTC to own 833 * 834 * Acquire a reference count on vblank events to avoid having them disabled 835 * while in use. 836 * 837 * RETURNS 838 * Zero on success, nonzero on failure. 839 */ 840 int drm_vblank_get(struct drm_device *dev, int crtc) 841 { 842 int ret = 0; 843 844 lockmgr(&dev->vbl_lock, LK_EXCLUSIVE); 845 /* Going from 0->1 means we have to enable interrupts again */ 846 if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { 847 lockmgr(&dev->vblank_time_lock, LK_EXCLUSIVE); 848 if (!dev->vblank_enabled[crtc]) { 849 /* Enable vblank irqs under vblank_time_lock protection. 850 * All vblank count & timestamp updates are held off 851 * until we are done reinitializing master counter and 852 * timestamps. Filtercode in drm_handle_vblank() will 853 * prevent double-accounting of same vblank interval. 854 */ 855 ret = -dev->driver->enable_vblank(dev, crtc); 856 DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", 857 crtc, ret); 858 if (ret) 859 atomic_dec(&dev->vblank_refcount[crtc]); 860 else { 861 dev->vblank_enabled[crtc] = 1; 862 drm_update_vblank_count(dev, crtc); 863 } 864 } 865 lockmgr(&dev->vblank_time_lock, LK_RELEASE); 866 } else { 867 if (!dev->vblank_enabled[crtc]) { 868 atomic_dec(&dev->vblank_refcount[crtc]); 869 ret = EINVAL; 870 } 871 } 872 lockmgr(&dev->vbl_lock, LK_RELEASE); 873 874 return ret; 875 } 876 877 /** 878 * drm_vblank_put - give up ownership of vblank events 879 * @dev: DRM device 880 * @crtc: which counter to give up 881 * 882 * Release ownership of a given vblank counter, turning off interrupts 883 * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. 884 */ 885 void drm_vblank_put(struct drm_device *dev, int crtc) 886 { 887 BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); 888 889 /* Last user schedules interrupt disable */ 890 lockmgr(&dev->vblank_time_lock, LK_EXCLUSIVE); 891 if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && 892 (drm_vblank_offdelay > 0)) { 893 mod_timer(&dev->vblank_disable_timer, 894 jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); 895 } 896 lockmgr(&dev->vblank_time_lock, LK_RELEASE); 897 } 898 EXPORT_SYMBOL(drm_vblank_put); 899 900 void drm_vblank_off(struct drm_device *dev, int crtc) 901 { 902 struct drm_pending_vblank_event *e, *t; 903 struct timeval now; 904 unsigned int seq; 905 906 lockmgr(&dev->vbl_lock, LK_EXCLUSIVE); 907 vblank_disable_and_save(dev, crtc); 908 lockmgr(&dev->event_lock, LK_EXCLUSIVE); 909 wakeup(&dev->_vblank_count[crtc]); 910 911 /* Send any queued vblank events, lest the natives grow disquiet */ 912 seq = drm_vblank_count_and_time(dev, crtc, &now); 913 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { 914 if (e->pipe != crtc) 915 continue; 916 DRM_DEBUG("Sending premature vblank event on disable: \ 917 wanted %d, current %d\n", 918 e->event.sequence, seq); 919 list_del(&e->base.link); 920 drm_vblank_put(dev, e->pipe); 921 send_vblank_event(dev, e, seq, &now); 922 } 923 924 lockmgr(&dev->event_lock, LK_RELEASE); 925 lockmgr(&dev->vbl_lock, LK_RELEASE); 926 } 927 928 /** 929 * drm_vblank_pre_modeset - account for vblanks across mode sets 930 * @dev: DRM device 931 * @crtc: CRTC in question 932 * @post: post or pre mode set? 933 * 934 * Account for vblank events across mode setting events, which will likely 935 * reset the hardware frame counter. 936 */ 937 void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) 938 { 939 /* vblank is not initialized (IRQ not installed ?) */ 940 if (!dev->num_crtcs) 941 return; 942 /* 943 * To avoid all the problems that might happen if interrupts 944 * were enabled/disabled around or between these calls, we just 945 * have the kernel take a reference on the CRTC (just once though 946 * to avoid corrupting the count if multiple, mismatch calls occur), 947 * so that interrupts remain enabled in the interim. 948 */ 949 if (!dev->vblank_inmodeset[crtc]) { 950 dev->vblank_inmodeset[crtc] = 0x1; 951 if (drm_vblank_get(dev, crtc) == 0) 952 dev->vblank_inmodeset[crtc] |= 0x2; 953 } 954 } 955 956 void drm_vblank_post_modeset(struct drm_device *dev, int crtc) 957 { 958 959 if (dev->vblank_inmodeset[crtc]) { 960 lockmgr(&dev->vbl_lock, LK_EXCLUSIVE); 961 dev->vblank_disable_allowed = 1; 962 lockmgr(&dev->vbl_lock, LK_RELEASE); 963 964 if (dev->vblank_inmodeset[crtc] & 0x2) 965 drm_vblank_put(dev, crtc); 966 967 dev->vblank_inmodeset[crtc] = 0; 968 } 969 } 970 971 /** 972 * drm_modeset_ctl - handle vblank event counter changes across mode switch 973 * @DRM_IOCTL_ARGS: standard ioctl arguments 974 * 975 * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET 976 * ioctls around modesetting so that any lost vblank events are accounted for. 977 * 978 * Generally the counter will reset across mode sets. If interrupts are 979 * enabled around this call, we don't have to do anything since the counter 980 * will have already been incremented. 981 */ 982 int drm_modeset_ctl(struct drm_device *dev, void *data, 983 struct drm_file *file_priv) 984 { 985 struct drm_modeset_ctl *modeset = data; 986 int ret = 0; 987 unsigned int crtc; 988 989 /* If drm_vblank_init() hasn't been called yet, just no-op */ 990 if (!dev->num_crtcs) 991 goto out; 992 993 crtc = modeset->crtc; 994 if (crtc >= dev->num_crtcs) { 995 ret = -EINVAL; 996 goto out; 997 } 998 999 switch (modeset->cmd) { 1000 case _DRM_PRE_MODESET: 1001 drm_vblank_pre_modeset(dev, crtc); 1002 break; 1003 case _DRM_POST_MODESET: 1004 drm_vblank_post_modeset(dev, crtc); 1005 break; 1006 default: 1007 ret = -EINVAL; 1008 break; 1009 } 1010 1011 out: 1012 return ret; 1013 } 1014 1015 static void 1016 drm_vblank_event_destroy(struct drm_pending_event *e) 1017 { 1018 1019 drm_free(e, DRM_MEM_VBLANK); 1020 } 1021 1022 static int drm_queue_vblank_event(struct drm_device *dev, int pipe, 1023 union drm_wait_vblank *vblwait, 1024 struct drm_file *file_priv) 1025 { 1026 struct drm_pending_vblank_event *e; 1027 struct timeval now; 1028 unsigned int seq; 1029 int ret; 1030 1031 e = kmalloc(sizeof *e, DRM_MEM_VBLANK, M_WAITOK | M_ZERO); 1032 1033 e->pipe = pipe; 1034 e->base.pid = curproc->p_pid; 1035 e->event.base.type = DRM_EVENT_VBLANK; 1036 e->event.base.length = sizeof e->event; 1037 e->event.user_data = vblwait->request.signal; 1038 e->base.event = &e->event.base; 1039 e->base.file_priv = file_priv; 1040 e->base.destroy = drm_vblank_event_destroy; 1041 1042 lockmgr(&dev->event_lock, LK_EXCLUSIVE); 1043 1044 if (file_priv->event_space < sizeof e->event) { 1045 ret = EBUSY; 1046 goto err_unlock; 1047 } 1048 1049 file_priv->event_space -= sizeof e->event; 1050 seq = drm_vblank_count_and_time(dev, pipe, &now); 1051 1052 if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && 1053 (seq - vblwait->request.sequence) <= (1 << 23)) { 1054 vblwait->request.sequence = seq + 1; 1055 vblwait->reply.sequence = vblwait->request.sequence; 1056 } 1057 1058 DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n", 1059 vblwait->request.sequence, seq, pipe); 1060 1061 e->event.sequence = vblwait->request.sequence; 1062 if ((seq - vblwait->request.sequence) <= (1 << 23)) { 1063 drm_vblank_put(dev, pipe); 1064 send_vblank_event(dev, e, seq, &now); 1065 vblwait->reply.sequence = seq; 1066 } else { 1067 /* drm_handle_vblank_events will call drm_vblank_put */ 1068 list_add_tail(&e->base.link, &dev->vblank_event_list); 1069 vblwait->reply.sequence = vblwait->request.sequence; 1070 } 1071 1072 lockmgr(&dev->event_lock, LK_RELEASE); 1073 1074 return 0; 1075 1076 err_unlock: 1077 lockmgr(&dev->event_lock, LK_RELEASE); 1078 drm_free(e, DRM_MEM_VBLANK); 1079 drm_vblank_put(dev, pipe); 1080 return ret; 1081 } 1082 1083 /** 1084 * Wait for VBLANK. 1085 * 1086 * \param inode device inode. 1087 * \param file_priv DRM file private. 1088 * \param cmd command. 1089 * \param data user argument, pointing to a drm_wait_vblank structure. 1090 * \return zero on success or a negative number on failure. 1091 * 1092 * This function enables the vblank interrupt on the pipe requested, then 1093 * sleeps waiting for the requested sequence number to occur, and drops 1094 * the vblank interrupt refcount afterwards. (vblank irq disable follows that 1095 * after a timeout with no further vblank waits scheduled). 1096 */ 1097 int drm_wait_vblank(struct drm_device *dev, void *data, 1098 struct drm_file *file_priv) 1099 { 1100 union drm_wait_vblank *vblwait = data; 1101 int ret = 0; 1102 unsigned int flags, seq, crtc, high_crtc; 1103 1104 if (/*(!drm_dev_to_irq(dev)) || */(!dev->irq_enabled)) 1105 return (EINVAL); 1106 1107 if (vblwait->request.type & _DRM_VBLANK_SIGNAL) 1108 return (EINVAL); 1109 1110 if (vblwait->request.type & 1111 ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | 1112 _DRM_VBLANK_HIGH_CRTC_MASK)) { 1113 DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 1114 vblwait->request.type, 1115 (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK | 1116 _DRM_VBLANK_HIGH_CRTC_MASK)); 1117 return (EINVAL); 1118 } 1119 1120 flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 1121 high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK); 1122 if (high_crtc) 1123 crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT; 1124 else 1125 crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; 1126 if (crtc >= dev->num_crtcs) 1127 return (EINVAL); 1128 1129 ret = drm_vblank_get(dev, crtc); 1130 if (ret) { 1131 DRM_DEBUG("failed to acquire vblank counter, %d\n", ret); 1132 return (ret); 1133 } 1134 seq = drm_vblank_count(dev, crtc); 1135 1136 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 1137 case _DRM_VBLANK_RELATIVE: 1138 vblwait->request.sequence += seq; 1139 vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 1140 case _DRM_VBLANK_ABSOLUTE: 1141 break; 1142 default: 1143 ret = (EINVAL); 1144 goto done; 1145 } 1146 1147 if (flags & _DRM_VBLANK_EVENT) { 1148 /* must hold on to the vblank ref until the event fires 1149 * drm_vblank_put will be called asynchronously 1150 */ 1151 return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); 1152 } 1153 1154 if ((flags & _DRM_VBLANK_NEXTONMISS) && 1155 (seq - vblwait->request.sequence) <= (1<<23)) { 1156 vblwait->request.sequence = seq + 1; 1157 } 1158 1159 dev->last_vblank_wait[crtc] = vblwait->request.sequence; 1160 lockmgr(&dev->vblank_time_lock, LK_EXCLUSIVE); 1161 while (((drm_vblank_count(dev, crtc) - vblwait->request.sequence) > 1162 (1 << 23)) && dev->irq_enabled) { 1163 /* 1164 * The wakeups from the drm_irq_uninstall() and 1165 * drm_vblank_off() may be lost there since vbl_lock 1166 * is not held. Then, the timeout will wake us; the 3 1167 * seconds delay should not be a problem for 1168 * application when crtc is disabled or irq 1169 * uninstalled anyway. 1170 */ 1171 ret = lksleep(&dev->_vblank_count[crtc], &dev->vblank_time_lock, 1172 PCATCH, "drmvbl", 3 * hz); 1173 if (ret != 0) 1174 break; 1175 } 1176 lockmgr(&dev->vblank_time_lock, LK_RELEASE); 1177 if (ret != EINTR) { 1178 struct timeval now; 1179 long reply_seq; 1180 1181 reply_seq = drm_vblank_count_and_time(dev, crtc, &now); 1182 vblwait->reply.sequence = reply_seq; 1183 vblwait->reply.tval_sec = now.tv_sec; 1184 vblwait->reply.tval_usec = now.tv_usec; 1185 } 1186 1187 done: 1188 drm_vblank_put(dev, crtc); 1189 return ret; 1190 } 1191 1192 void drm_handle_vblank_events(struct drm_device *dev, int crtc) 1193 { 1194 struct drm_pending_vblank_event *e, *t; 1195 struct timeval now; 1196 unsigned int seq; 1197 1198 seq = drm_vblank_count_and_time(dev, crtc, &now); 1199 1200 lockmgr(&dev->event_lock, LK_EXCLUSIVE); 1201 1202 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { 1203 if (e->pipe != crtc) 1204 continue; 1205 if ((seq - e->event.sequence) > (1<<23)) 1206 continue; 1207 1208 DRM_DEBUG("vblank event on %d, current %d\n", 1209 e->event.sequence, seq); 1210 1211 list_del(&e->base.link); 1212 drm_vblank_put(dev, e->pipe); 1213 send_vblank_event(dev, e, seq, &now); 1214 } 1215 1216 lockmgr(&dev->event_lock, LK_RELEASE); 1217 } 1218 1219 /** 1220 * drm_handle_vblank - handle a vblank event 1221 * @dev: DRM device 1222 * @crtc: where this event occurred 1223 * 1224 * Drivers should call this routine in their vblank interrupt handlers to 1225 * update the vblank counter and send any signals that may be pending. 1226 */ 1227 bool drm_handle_vblank(struct drm_device *dev, int crtc) 1228 { 1229 u32 vblcount; 1230 int64_t diff_ns; 1231 struct timeval tvblank; 1232 1233 if (!dev->num_crtcs) 1234 return false; 1235 1236 /* Need timestamp lock to prevent concurrent execution with 1237 * vblank enable/disable, as this would cause inconsistent 1238 * or corrupted timestamps and vblank counts. 1239 */ 1240 lockmgr(&dev->vblank_time_lock, LK_EXCLUSIVE); 1241 1242 /* Vblank irq handling disabled. Nothing to do. */ 1243 if (!dev->vblank_enabled[crtc]) { 1244 lockmgr(&dev->vblank_time_lock, LK_RELEASE); 1245 return false; 1246 } 1247 1248 /* Fetch corresponding timestamp for this vblank interval from 1249 * driver and store it in proper slot of timestamp ringbuffer. 1250 */ 1251 1252 /* Get current timestamp and count. */ 1253 vblcount = atomic_read(&dev->_vblank_count[crtc]); 1254 drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); 1255 1256 /* Compute time difference to timestamp of last vblank */ 1257 diff_ns = timeval_to_ns(&tvblank) - 1258 timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); 1259 1260 /* Update vblank timestamp and count if at least 1261 * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds 1262 * difference between last stored timestamp and current 1263 * timestamp. A smaller difference means basically 1264 * identical timestamps. Happens if this vblank has 1265 * been already processed and this is a redundant call, 1266 * e.g., due to spurious vblank interrupts. We need to 1267 * ignore those for accounting. 1268 */ 1269 if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) { 1270 /* Store new timestamp in ringbuffer. */ 1271 vblanktimestamp(dev, crtc, vblcount + 1) = tvblank; 1272 1273 /* Increment cooked vblank count. This also atomically commits 1274 * the timestamp computed above. 1275 */ 1276 atomic_inc(&dev->_vblank_count[crtc]); 1277 } else { 1278 DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", 1279 crtc, (int) diff_ns); 1280 } 1281 1282 wakeup(&dev->_vblank_count[crtc]); 1283 drm_handle_vblank_events(dev, crtc); 1284 1285 lockmgr(&dev->vblank_time_lock, LK_RELEASE); 1286 return true; 1287 } 1288