drm_irq.c (166901) | drm_irq.c (182080) |
---|---|
1/* drm_irq.c -- IRQ IOCTL and function support 2 * Created: Fri Oct 18 2003 by anholt@FreeBSD.org 3 */ | |
4/*- 5 * Copyright 2003 Eric Anholt 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, --- 12 unchanged lines hidden (view full) --- 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * Authors: 27 * Eric Anholt <anholt@FreeBSD.org> 28 * 29 */ 30 31#include <sys/cdefs.h> | 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, --- 12 unchanged lines hidden (view full) --- 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 */ 27 28#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: head/sys/dev/drm/drm_irq.c 166901 2007-02-23 12:19:07Z piso $"); | 29__FBSDID("$FreeBSD: head/sys/dev/drm/drm_irq.c 182080 2008-08-23 20:59:12Z rnoland $"); |
33 | 30 |
31/** @file drm_irq.c 32 * Support code for handling setup/teardown of interrupt handlers and 33 * handing interrupt handlers off to the drivers. 34 */ 35 |
|
34#include "dev/drm/drmP.h" 35#include "dev/drm/drm.h" 36 | 36#include "dev/drm/drmP.h" 37#include "dev/drm/drm.h" 38 |
37int drm_irq_by_busid(DRM_IOCTL_ARGS) | 39static void drm_locked_task(void *context, int pending __unused); 40 41int drm_irq_by_busid(struct drm_device *dev, void *data, 42 struct drm_file *file_priv) |
38{ | 43{ |
39 DRM_DEVICE; 40 drm_irq_busid_t irq; | 44 drm_irq_busid_t *irq = data; |
41 | 45 |
42 DRM_COPY_FROM_USER_IOCTL(irq, (drm_irq_busid_t *)data, sizeof(irq)); 43 44 if ((irq.busnum >> 8) != dev->pci_domain || 45 (irq.busnum & 0xff) != dev->pci_bus || 46 irq.devnum != dev->pci_slot || 47 irq.funcnum != dev->pci_func) | 46 if ((irq->busnum >> 8) != dev->pci_domain || 47 (irq->busnum & 0xff) != dev->pci_bus || 48 irq->devnum != dev->pci_slot || 49 irq->funcnum != dev->pci_func) |
48 return EINVAL; 49 | 50 return EINVAL; 51 |
50 irq.irq = dev->irq; | 52 irq->irq = dev->irq; |
51 52 DRM_DEBUG("%d:%d:%d => IRQ %d\n", | 53 54 DRM_DEBUG("%d:%d:%d => IRQ %d\n", |
53 irq.busnum, irq.devnum, irq.funcnum, irq.irq); | 55 irq->busnum, irq->devnum, irq->funcnum, irq->irq); |
54 | 56 |
55 DRM_COPY_TO_USER_IOCTL( (drm_irq_busid_t *)data, irq, sizeof(irq) ); 56 | |
57 return 0; 58} 59 60#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 61static irqreturn_t 62drm_irq_handler_wrap(DRM_IRQ_ARGS) 63{ | 57 return 0; 58} 59 60#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 61static irqreturn_t 62drm_irq_handler_wrap(DRM_IRQ_ARGS) 63{ |
64 drm_device_t *dev = (drm_device_t *)arg; | 64 struct drm_device *dev = arg; |
65 66 DRM_SPINLOCK(&dev->irq_lock); 67 dev->driver.irq_handler(arg); 68 DRM_SPINUNLOCK(&dev->irq_lock); 69} 70#endif 71 | 65 66 DRM_SPINLOCK(&dev->irq_lock); 67 dev->driver.irq_handler(arg); 68 DRM_SPINUNLOCK(&dev->irq_lock); 69} 70#endif 71 |
72int drm_irq_install(drm_device_t *dev) | 72static void vblank_disable_fn(void *arg) |
73{ | 73{ |
74 struct drm_device *dev = (struct drm_device *)arg; 75 int i; 76 77 if (callout_pending(&dev->vblank_disable_timer)) { 78 /* callout was reset */ 79 return; 80 } 81 if (!callout_active(&dev->vblank_disable_timer)) { 82 /* callout was stopped */ 83 return; 84 } 85 callout_deactivate(&dev->vblank_disable_timer); 86 87 if (!dev->vblank_disable_allowed) 88 return; 89 90 for (i = 0; i < dev->num_crtcs; i++) { 91 if (atomic_read(&dev->vblank[i].refcount) == 0 && 92 dev->vblank[i].enabled) { 93 DRM_DEBUG("disabling vblank on crtc %d\n", i); 94 dev->vblank[i].last = 95 dev->driver.get_vblank_counter(dev, i); 96 dev->driver.disable_vblank(dev, i); 97 dev->vblank[i].enabled = 0; 98 } 99 } 100} 101 102static void drm_vblank_cleanup(struct drm_device *dev) 103{ 104 unsigned long irqflags; 105 106 /* Bail if the driver didn't call drm_vblank_init() */ 107 if (dev->num_crtcs == 0) 108 return; 109 110 DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 111 callout_stop(&dev->vblank_disable_timer); 112 DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 113 114 callout_drain(&dev->vblank_disable_timer); 115 116 vblank_disable_fn((void *)dev); 117 118 drm_free(dev->vblank, sizeof(struct drm_vblank_info) * dev->num_crtcs, 119 DRM_MEM_DRIVER); 120 121 dev->num_crtcs = 0; 122} 123 124int drm_vblank_init(struct drm_device *dev, int num_crtcs) 125{ 126 int i, ret = ENOMEM; 127 128 callout_init_mtx(&dev->vblank_disable_timer, &dev->vbl_lock, 0); 129 atomic_set(&dev->vbl_signal_pending, 0); 130 dev->num_crtcs = num_crtcs; 131 132 dev->vblank = drm_calloc(num_crtcs, sizeof(struct drm_vblank_info), 133 DRM_MEM_DRIVER); 134 if (!dev->vblank) 135 goto err; 136 137 /* Zero per-crtc vblank stuff */ 138 for (i = 0; i < num_crtcs; i++) { 139 DRM_INIT_WAITQUEUE(&dev->vblank[i].queue); 140 TAILQ_INIT(&dev->vblank[i].sigs); 141 atomic_set(&dev->vblank[i].count, 0); 142 atomic_set(&dev->vblank[i].refcount, 0); 143 } 144 145 dev->vblank_disable_allowed = 0; 146 147 return 0; 148 149err: 150 drm_vblank_cleanup(dev); 151 return ret; 152} 153 154int drm_irq_install(struct drm_device *dev) 155{ |
|
74 int retcode; 75#ifdef __NetBSD__ 76 pci_intr_handle_t ih; 77#endif 78 79 if (dev->irq == 0 || dev->dev_private == NULL) | 156 int retcode; 157#ifdef __NetBSD__ 158 pci_intr_handle_t ih; 159#endif 160 161 if (dev->irq == 0 || dev->dev_private == NULL) |
80 return DRM_ERR(EINVAL); | 162 return EINVAL; |
81 82 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); 83 84 DRM_LOCK(); 85 if (dev->irq_enabled) { 86 DRM_UNLOCK(); | 163 164 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); 165 166 DRM_LOCK(); 167 if (dev->irq_enabled) { 168 DRM_UNLOCK(); |
87 return DRM_ERR(EBUSY); | 169 return EBUSY; |
88 } 89 dev->irq_enabled = 1; 90 91 dev->context_flag = 0; 92 | 170 } 171 dev->irq_enabled = 1; 172 173 dev->context_flag = 0; 174 |
93 DRM_SPININIT(dev->irq_lock, "DRM IRQ lock"); 94 | |
95 /* Before installing handler */ 96 dev->driver.irq_preinstall(dev); 97 DRM_UNLOCK(); 98 99 /* Install handler */ 100#ifdef __FreeBSD__ 101 dev->irqrid = 0; 102 dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, 103 &dev->irqrid, RF_SHAREABLE); 104 if (!dev->irqr) { 105 retcode = ENOENT; 106 goto err; 107 } | 175 /* Before installing handler */ 176 dev->driver.irq_preinstall(dev); 177 DRM_UNLOCK(); 178 179 /* Install handler */ 180#ifdef __FreeBSD__ 181 dev->irqrid = 0; 182 dev->irqr = bus_alloc_resource_any(dev->device, SYS_RES_IRQ, 183 &dev->irqrid, RF_SHAREABLE); 184 if (!dev->irqr) { 185 retcode = ENOENT; 186 goto err; 187 } |
108#if __FreeBSD_version < 500000 109 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY, 110 dev->irq_handler, dev, &dev->irqh); 111#else 112 retcode = bus_setup_intr(dev->device, dev->irqr, INTR_TYPE_TTY | INTR_MPSAFE, | 188#if __FreeBSD_version >= 700031 189 retcode = bus_setup_intr(dev->device, dev->irqr, 190 INTR_TYPE_TTY | INTR_MPSAFE, |
113 NULL, drm_irq_handler_wrap, dev, &dev->irqh); | 191 NULL, drm_irq_handler_wrap, dev, &dev->irqh); |
192#else 193 retcode = bus_setup_intr(dev->device, dev->irqr, 194 INTR_TYPE_TTY | INTR_MPSAFE, 195 drm_irq_handler_wrap, dev, &dev->irqh); |
|
114#endif 115 if (retcode != 0) 116 goto err; 117#elif defined(__NetBSD__) || defined(__OpenBSD__) 118 if (pci_intr_map(&dev->pa, &ih) != 0) { 119 retcode = ENOENT; 120 goto err; 121 } --- 5 unchanged lines hidden (view full) --- 127 } 128#endif 129 130 /* After installing handler */ 131 DRM_LOCK(); 132 dev->driver.irq_postinstall(dev); 133 DRM_UNLOCK(); 134 | 196#endif 197 if (retcode != 0) 198 goto err; 199#elif defined(__NetBSD__) || defined(__OpenBSD__) 200 if (pci_intr_map(&dev->pa, &ih) != 0) { 201 retcode = ENOENT; 202 goto err; 203 } --- 5 unchanged lines hidden (view full) --- 209 } 210#endif 211 212 /* After installing handler */ 213 DRM_LOCK(); 214 dev->driver.irq_postinstall(dev); 215 DRM_UNLOCK(); 216 |
217 TASK_INIT(&dev->locked_task, 0, drm_locked_task, dev); |
|
135 return 0; 136err: 137 DRM_LOCK(); 138 dev->irq_enabled = 0; 139#ifdef ___FreeBSD__ 140 if (dev->irqrid != 0) { 141 bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, 142 dev->irqr); 143 dev->irqrid = 0; 144 } 145#endif | 218 return 0; 219err: 220 DRM_LOCK(); 221 dev->irq_enabled = 0; 222#ifdef ___FreeBSD__ 223 if (dev->irqrid != 0) { 224 bus_release_resource(dev->device, SYS_RES_IRQ, dev->irqrid, 225 dev->irqr); 226 dev->irqrid = 0; 227 } 228#endif |
146 DRM_SPINUNINIT(dev->irq_lock); | |
147 DRM_UNLOCK(); 148 return retcode; 149} 150 | 229 DRM_UNLOCK(); 230 return retcode; 231} 232 |
151int drm_irq_uninstall(drm_device_t *dev) | 233int drm_irq_uninstall(struct drm_device *dev) |
152{ 153#ifdef __FreeBSD__ 154 int irqrid; 155#endif 156 157 if (!dev->irq_enabled) | 234{ 235#ifdef __FreeBSD__ 236 int irqrid; 237#endif 238 239 if (!dev->irq_enabled) |
158 return DRM_ERR(EINVAL); | 240 return EINVAL; |
159 160 dev->irq_enabled = 0; 161#ifdef __FreeBSD__ 162 irqrid = dev->irqrid; 163 dev->irqrid = 0; 164#endif 165 166 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); 167 168 dev->driver.irq_uninstall(dev); 169 170#ifdef __FreeBSD__ 171 DRM_UNLOCK(); 172 bus_teardown_intr(dev->device, dev->irqr, dev->irqh); 173 bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); 174 DRM_LOCK(); 175#elif defined(__NetBSD__) || defined(__OpenBSD__) 176 pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh); 177#endif | 241 242 dev->irq_enabled = 0; 243#ifdef __FreeBSD__ 244 irqrid = dev->irqrid; 245 dev->irqrid = 0; 246#endif 247 248 DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, dev->irq ); 249 250 dev->driver.irq_uninstall(dev); 251 252#ifdef __FreeBSD__ 253 DRM_UNLOCK(); 254 bus_teardown_intr(dev->device, dev->irqr, dev->irqh); 255 bus_release_resource(dev->device, SYS_RES_IRQ, irqrid, dev->irqr); 256 DRM_LOCK(); 257#elif defined(__NetBSD__) || defined(__OpenBSD__) 258 pci_intr_disestablish(&dev->pa.pa_pc, dev->irqh); 259#endif |
178 DRM_SPINUNINIT(dev->irq_lock); | 260 drm_vblank_cleanup(dev); |
179 180 return 0; 181} 182 | 261 262 return 0; 263} 264 |
183int drm_control(DRM_IOCTL_ARGS) | 265int drm_control(struct drm_device *dev, void *data, struct drm_file *file_priv) |
184{ | 266{ |
185 DRM_DEVICE; 186 drm_control_t ctl; | 267 drm_control_t *ctl = data; |
187 int err; 188 | 268 int err; 269 |
189 DRM_COPY_FROM_USER_IOCTL( ctl, (drm_control_t *) data, sizeof(ctl) ); 190 191 switch ( ctl.func ) { | 270 switch ( ctl->func ) { |
192 case DRM_INST_HANDLER: 193 /* Handle drivers whose DRM used to require IRQ setup but the 194 * no longer does. 195 */ 196 if (!dev->driver.use_irq) 197 return 0; 198 if (dev->if_version < DRM_IF_VERSION(1, 2) && | 271 case DRM_INST_HANDLER: 272 /* Handle drivers whose DRM used to require IRQ setup but the 273 * no longer does. 274 */ 275 if (!dev->driver.use_irq) 276 return 0; 277 if (dev->if_version < DRM_IF_VERSION(1, 2) && |
199 ctl.irq != dev->irq) 200 return DRM_ERR(EINVAL); | 278 ctl->irq != dev->irq) 279 return EINVAL; |
201 return drm_irq_install(dev); 202 case DRM_UNINST_HANDLER: 203 if (!dev->driver.use_irq) 204 return 0; 205 DRM_LOCK(); 206 err = drm_irq_uninstall(dev); 207 DRM_UNLOCK(); 208 return err; 209 default: | 280 return drm_irq_install(dev); 281 case DRM_UNINST_HANDLER: 282 if (!dev->driver.use_irq) 283 return 0; 284 DRM_LOCK(); 285 err = drm_irq_uninstall(dev); 286 DRM_UNLOCK(); 287 return err; 288 default: |
210 return DRM_ERR(EINVAL); | 289 return EINVAL; |
211 } 212} 213 | 290 } 291} 292 |
214int drm_wait_vblank(DRM_IOCTL_ARGS) | 293u32 drm_vblank_count(struct drm_device *dev, int crtc) |
215{ | 294{ |
216 DRM_DEVICE; 217 drm_wait_vblank_t vblwait; 218 struct timeval now; 219 int ret; | 295 return atomic_read(&dev->vblank[crtc].count); 296} |
220 | 297 |
298static void drm_update_vblank_count(struct drm_device *dev, int crtc) 299{ 300 u32 cur_vblank, diff; 301 302 /* 303 * Interrupts were disabled prior to this call, so deal with counter 304 * wrap if needed. 305 * NOTE! It's possible we lost a full dev->max_vblank_count events 306 * here if the register is small or we had vblank interrupts off for 307 * a long time. 308 */ 309 cur_vblank = dev->driver.get_vblank_counter(dev, crtc); 310 diff = cur_vblank - dev->vblank[crtc].last; 311 if (cur_vblank < dev->vblank[crtc].last) { 312 diff += dev->max_vblank_count; 313 314 DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", 315 crtc, dev->vblank[crtc].last, cur_vblank, diff); 316 } 317 318 DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", 319 crtc, diff); 320 321 atomic_add(diff, &dev->vblank[crtc].count); 322} 323 324int drm_vblank_get(struct drm_device *dev, int crtc) 325{ 326 unsigned long irqflags; 327 int ret = 0; 328 329 DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 330 /* Going from 0->1 means we have to enable interrupts again */ 331 atomic_add_acq_int(&dev->vblank[crtc].refcount, 1); 332 if (dev->vblank[crtc].refcount == 1 && 333 !dev->vblank[crtc].enabled) { 334 ret = dev->driver.enable_vblank(dev, crtc); 335 if (ret) 336 atomic_dec(&dev->vblank[crtc].refcount); 337 else { 338 dev->vblank[crtc].enabled = 1; 339 drm_update_vblank_count(dev, crtc); 340 } 341 } 342 DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 343 344 return ret; 345} 346 347void drm_vblank_put(struct drm_device *dev, int crtc) 348{ 349 unsigned long irqflags; 350 351 DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 352 /* Last user schedules interrupt disable */ 353 atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1); 354 if (dev->vblank[crtc].refcount == 0) 355 callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ, 356 (timeout_t *)vblank_disable_fn, (void *)dev); 357 DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 358} 359 360int drm_modeset_ctl(struct drm_device *dev, void *data, 361 struct drm_file *file_priv) 362{ 363 struct drm_modeset_ctl *modeset = data; 364 unsigned long irqflags; 365 int crtc, ret = 0; 366 367 /* If drm_vblank_init() hasn't been called yet, just no-op */ 368 if (!dev->num_crtcs) 369 goto out; 370 371 crtc = modeset->crtc; 372 if (crtc >= dev->num_crtcs) { 373 ret = EINVAL; 374 goto out; 375 } 376 377 /* 378 * To avoid all the problems that might happen if interrupts 379 * were enabled/disabled around or between these calls, we just 380 * have the kernel take a reference on the CRTC (just once though 381 * to avoid corrupting the count if multiple, mismatch calls occur), 382 * so that interrupts remain enabled in the interim. 383 */ 384 switch (modeset->cmd) { 385 case _DRM_PRE_MODESET: 386 if (!dev->vblank[crtc].inmodeset) { 387 dev->vblank[crtc].inmodeset = 1; 388 drm_vblank_get(dev, crtc); 389 } 390 break; 391 case _DRM_POST_MODESET: 392 if (dev->vblank[crtc].inmodeset) { 393 DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags); 394 dev->vblank_disable_allowed = 1; 395 dev->vblank[crtc].inmodeset = 0; 396 DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags); 397 drm_vblank_put(dev, crtc); 398 } 399 break; 400 default: 401 ret = EINVAL; 402 break; 403 } 404 405out: 406 return ret; 407} 408 409int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) 410{ 411 drm_wait_vblank_t *vblwait = data; 412 int ret = 0; 413 int flags, seq, crtc; 414 |
|
221 if (!dev->irq_enabled) | 415 if (!dev->irq_enabled) |
222 return DRM_ERR(EINVAL); | 416 return EINVAL; |
223 | 417 |
224 DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data, 225 sizeof(vblwait) ); | 418 if (vblwait->request.type & 419 ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { 420 DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", 421 vblwait->request.type, 422 (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); 423 return EINVAL; 424 } |
226 | 425 |
227 if (vblwait.request.type & _DRM_VBLANK_RELATIVE) { 228 vblwait.request.sequence += atomic_read(&dev->vbl_received); 229 vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; | 426 flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; 427 crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; 428 429 if (crtc >= dev->num_crtcs) 430 return EINVAL; 431 432 ret = drm_vblank_get(dev, crtc); 433 if (ret) 434 return ret; 435 seq = drm_vblank_count(dev, crtc); 436 437 switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { 438 case _DRM_VBLANK_RELATIVE: 439 vblwait->request.sequence += seq; 440 vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; 441 case _DRM_VBLANK_ABSOLUTE: 442 break; 443 default: 444 ret = EINVAL; 445 goto done; |
230 } 231 | 446 } 447 |
232 flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; | 448 if ((flags & _DRM_VBLANK_NEXTONMISS) && 449 (seq - vblwait->request.sequence) <= (1<<23)) { 450 vblwait->request.sequence = seq + 1; 451 } 452 |
233 if (flags & _DRM_VBLANK_SIGNAL) { 234#if 0 /* disabled */ 235 drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM, 236 M_NOWAIT | M_ZERO); 237 if (vbl_sig == NULL) 238 return ENOMEM; 239 | 453 if (flags & _DRM_VBLANK_SIGNAL) { 454#if 0 /* disabled */ 455 drm_vbl_sig_t *vbl_sig = malloc(sizeof(drm_vbl_sig_t), M_DRM, 456 M_NOWAIT | M_ZERO); 457 if (vbl_sig == NULL) 458 return ENOMEM; 459 |
240 vbl_sig->sequence = vblwait.request.sequence; 241 vbl_sig->signo = vblwait.request.signal; | 460 vbl_sig->sequence = vblwait->request.sequence; 461 vbl_sig->signo = vblwait->request.signal; |
242 vbl_sig->pid = DRM_CURRENTPID; 243 | 462 vbl_sig->pid = DRM_CURRENTPID; 463 |
244 vblwait.reply.sequence = atomic_read(&dev->vbl_received); | 464 vblwait->reply.sequence = atomic_read(&dev->vbl_received); |
245 | 465 |
246 DRM_SPINLOCK(&dev->irq_lock); | 466 DRM_SPINLOCK(&dev->vbl_lock); |
247 TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); | 467 TAILQ_INSERT_HEAD(&dev->vbl_sig_list, vbl_sig, link); |
248 DRM_SPINUNLOCK(&dev->irq_lock); | 468 DRM_SPINUNLOCK(&dev->vbl_lock); |
249 ret = 0; 250#endif 251 ret = EINVAL; 252 } else { 253 DRM_LOCK(); | 469 ret = 0; 470#endif 471 ret = EINVAL; 472 } else { 473 DRM_LOCK(); |
254 ret = dev->driver.vblank_wait(dev, &vblwait.request.sequence); | 474 /* shared code returns -errno */ 475 476 DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ, 477 ((drm_vblank_count(dev, crtc) 478 - vblwait->request.sequence) <= (1 << 23))); |
255 DRM_UNLOCK(); 256 | 479 DRM_UNLOCK(); 480 |
257 microtime(&now); 258 vblwait.reply.tval_sec = now.tv_sec; 259 vblwait.reply.tval_usec = now.tv_usec; | 481 if (ret != EINTR) { 482 struct timeval now; 483 484 microtime(&now); 485 vblwait->reply.tval_sec = now.tv_sec; 486 vblwait->reply.tval_usec = now.tv_usec; 487 vblwait->reply.sequence = drm_vblank_count(dev, crtc); 488 } |
260 } 261 | 489 } 490 |
262 DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait, 263 sizeof(vblwait) ); 264 | 491done: 492 drm_vblank_put(dev, crtc); |
265 return ret; 266} 267 | 493 return ret; 494} 495 |
268void drm_vbl_send_signals(drm_device_t *dev) | 496void drm_vbl_send_signals(struct drm_device *dev, int crtc) |
269{ 270} 271 272#if 0 /* disabled */ | 497{ 498} 499 500#if 0 /* disabled */ |
273void drm_vbl_send_signals( drm_device_t *dev ) | 501void drm_vbl_send_signals(struct drm_device *dev, int crtc ) |
274{ 275 drm_vbl_sig_t *vbl_sig; 276 unsigned int vbl_seq = atomic_read( &dev->vbl_received ); 277 struct proc *p; 278 279 vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); 280 while (vbl_sig != NULL) { 281 drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); --- 5 unchanged lines hidden (view full) --- 287 288 TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); 289 DRM_FREE(vbl_sig,sizeof(*vbl_sig)); 290 } 291 vbl_sig = next; 292 } 293} 294#endif | 502{ 503 drm_vbl_sig_t *vbl_sig; 504 unsigned int vbl_seq = atomic_read( &dev->vbl_received ); 505 struct proc *p; 506 507 vbl_sig = TAILQ_FIRST(&dev->vbl_sig_list); 508 while (vbl_sig != NULL) { 509 drm_vbl_sig_t *next = TAILQ_NEXT(vbl_sig, link); --- 5 unchanged lines hidden (view full) --- 515 516 TAILQ_REMOVE(&dev->vbl_sig_list, vbl_sig, link); 517 DRM_FREE(vbl_sig,sizeof(*vbl_sig)); 518 } 519 vbl_sig = next; 520 } 521} 522#endif |
523 524void drm_handle_vblank(struct drm_device *dev, int crtc) 525{ 526 atomic_inc(&dev->vblank[crtc].count); 527 DRM_WAKEUP(&dev->vblank[crtc].queue); 528 drm_vbl_send_signals(dev, crtc); 529} 530 531static void drm_locked_task(void *context, int pending __unused) 532{ 533 struct drm_device *dev = context; 534 535 DRM_SPINLOCK(&dev->tsk_lock); 536 537 DRM_LOCK(); /* XXX drm_lock_take() should do it's own locking */ 538 if (dev->locked_task_call == NULL || 539 drm_lock_take(&dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT) == 0) { 540 DRM_UNLOCK(); 541 DRM_SPINUNLOCK(&dev->tsk_lock); 542 return; 543 } 544 545 dev->lock.file_priv = NULL; /* kernel owned */ 546 dev->lock.lock_time = jiffies; 547 atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); 548 549 DRM_UNLOCK(); 550 551 dev->locked_task_call(dev); 552 553 drm_lock_free(dev, &dev->lock.hw_lock->lock, DRM_KERNEL_CONTEXT); 554 555 dev->locked_task_call = NULL; 556 557 DRM_SPINUNLOCK(&dev->tsk_lock); 558} 559 560void 561drm_locked_tasklet(struct drm_device *dev, 562 void (*tasklet)(struct drm_device *dev)) 563{ 564 DRM_SPINLOCK(&dev->tsk_lock); 565 if (dev->locked_task_call != NULL) { 566 DRM_SPINUNLOCK(&dev->tsk_lock); 567 return; 568 } 569 570 dev->locked_task_call = tasklet; 571 DRM_SPINUNLOCK(&dev->tsk_lock); 572 taskqueue_enqueue(taskqueue_swi, &dev->locked_task); 573} |
|