1/* gamma_dma.c -- DMA support for GMX 2000 -*- linux-c -*- 2 * Created: Fri Mar 19 14:30:16 1999 by faith@precisioninsight.com 3 * 4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 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 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 * 27 * Authors: 28 * Rickard E. (Rik) Faith <faith@valinux.com> 29 * 30 */ 31 32#define __NO_VERSION__ 33#include "drmP.h" 34#include "gamma_drv.h" 35 36#include <linux/interrupt.h> /* For task queue support */ 37 38 39/* WARNING!!! MAGIC NUMBER!!! The number of regions already added to the 40 kernel must be specified here. Currently, the number is 2. This must 41 match the order the X server uses for instantiating register regions , 42 or must be passed in a new ioctl. */ 43#define GAMMA_REG(reg) \ 44 (2 \ 45 + ((reg < 0x1000) \ 46 ? 0 \ 47 : ((reg < 0x10000) ? 1 : ((reg < 0x11000) ? 2 : 3)))) 48 49#define GAMMA_OFF(reg) \ 50 ((reg < 0x1000) \ 51 ? reg \ 52 : ((reg < 0x10000) \ 53 ? (reg - 0x1000) \ 54 : ((reg < 0x11000) \ 55 ? (reg - 0x10000) \ 56 : (reg - 0x11000)))) 57 58#define GAMMA_BASE(reg) ((unsigned long)dev->maplist[GAMMA_REG(reg)]->handle) 59#define GAMMA_ADDR(reg) (GAMMA_BASE(reg) + GAMMA_OFF(reg)) 60#define GAMMA_DEREF(reg) *(__volatile__ int *)GAMMA_ADDR(reg) 61#define GAMMA_READ(reg) GAMMA_DEREF(reg) 62#define GAMMA_WRITE(reg,val) do { GAMMA_DEREF(reg) = val; } while (0) 63 64#define GAMMA_BROADCASTMASK 0x9378 65#define GAMMA_COMMANDINTENABLE 0x0c48 66#define GAMMA_DMAADDRESS 0x0028 67#define GAMMA_DMACOUNT 0x0030 68#define GAMMA_FILTERMODE 0x8c00 69#define GAMMA_GCOMMANDINTFLAGS 0x0c50 70#define GAMMA_GCOMMANDMODE 0x0c40 71#define GAMMA_GCOMMANDSTATUS 0x0c60 72#define GAMMA_GDELAYTIMER 0x0c38 73#define GAMMA_GDMACONTROL 0x0060 74#define GAMMA_GINTENABLE 0x0808 75#define GAMMA_GINTFLAGS 0x0810 76#define GAMMA_INFIFOSPACE 0x0018 77#define GAMMA_OUTFIFOWORDS 0x0020 78#define GAMMA_OUTPUTFIFO 0x2000 79#define GAMMA_SYNC 0x8c40 80#define GAMMA_SYNC_TAG 0x0188 81 82static inline void gamma_dma_dispatch(drm_device_t *dev, unsigned long address, 83 unsigned long length) 84{ 85 GAMMA_WRITE(GAMMA_DMAADDRESS, virt_to_phys((void *)address)); 86 while (GAMMA_READ(GAMMA_GCOMMANDSTATUS) != 4) 87 ; 88 GAMMA_WRITE(GAMMA_DMACOUNT, length / 4); 89} 90 91static inline void gamma_dma_quiescent_single(drm_device_t *dev) 92{ 93 while (GAMMA_READ(GAMMA_DMACOUNT)) 94 ; 95 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) 96 ; 97 98 GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); 99 GAMMA_WRITE(GAMMA_SYNC, 0); 100 101 do { 102 while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) 103 ; 104 } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); 105} 106 107static inline void gamma_dma_quiescent_dual(drm_device_t *dev) 108{ 109 while (GAMMA_READ(GAMMA_DMACOUNT)) 110 ; 111 while (GAMMA_READ(GAMMA_INFIFOSPACE) < 3) 112 ; 113 114 GAMMA_WRITE(GAMMA_BROADCASTMASK, 3); 115 116 GAMMA_WRITE(GAMMA_FILTERMODE, 1 << 10); 117 GAMMA_WRITE(GAMMA_SYNC, 0); 118 119 /* Read from first MX */ 120 do { 121 while (!GAMMA_READ(GAMMA_OUTFIFOWORDS)) 122 ; 123 } while (GAMMA_READ(GAMMA_OUTPUTFIFO) != GAMMA_SYNC_TAG); 124 125 /* Read from second MX */ 126 do { 127 while (!GAMMA_READ(GAMMA_OUTFIFOWORDS + 0x10000)) 128 ; 129 } while (GAMMA_READ(GAMMA_OUTPUTFIFO + 0x10000) != GAMMA_SYNC_TAG); 130} 131 132static inline void gamma_dma_ready(drm_device_t *dev) 133{ 134 while (GAMMA_READ(GAMMA_DMACOUNT)) 135 ; 136} 137 138static inline int gamma_dma_is_ready(drm_device_t *dev) 139{ 140 return !GAMMA_READ(GAMMA_DMACOUNT); 141} 142 143static void gamma_dma_service(int irq, void *device, struct pt_regs *regs) 144{ 145 drm_device_t *dev = (drm_device_t *)device; 146 drm_device_dma_t *dma = dev->dma; 147 148 atomic_inc(&dev->total_irq); 149 GAMMA_WRITE(GAMMA_GDELAYTIMER, 0xc350/2); /* 0x05S */ 150 GAMMA_WRITE(GAMMA_GCOMMANDINTFLAGS, 8); 151 GAMMA_WRITE(GAMMA_GINTFLAGS, 0x2001); 152 if (gamma_dma_is_ready(dev)) { 153 /* Free previous buffer */ 154 if (test_and_set_bit(0, &dev->dma_flag)) { 155 atomic_inc(&dma->total_missed_free); 156 return; 157 } 158 if (dma->this_buffer) { 159 drm_free_buffer(dev, dma->this_buffer); 160 dma->this_buffer = NULL; 161 } 162 clear_bit(0, &dev->dma_flag); 163 164 /* Dispatch new buffer */ 165 queue_task(&dev->tq, &tq_immediate); 166 mark_bh(IMMEDIATE_BH); 167 } 168} 169 170/* Only called by gamma_dma_schedule. */ 171static int gamma_do_dma(drm_device_t *dev, int locked) 172{ 173 unsigned long address; 174 unsigned long length; 175 drm_buf_t *buf; 176 int retcode = 0; 177 drm_device_dma_t *dma = dev->dma; 178#if DRM_DMA_HISTOGRAM 179 cycles_t dma_start, dma_stop; 180#endif 181 182 if (test_and_set_bit(0, &dev->dma_flag)) { 183 atomic_inc(&dma->total_missed_dma); 184 return -EBUSY; 185 } 186 187#if DRM_DMA_HISTOGRAM 188 dma_start = get_cycles(); 189#endif 190 191 if (!dma->next_buffer) { 192 DRM_ERROR("No next_buffer\n"); 193 clear_bit(0, &dev->dma_flag); 194 return -EINVAL; 195 } 196 197 buf = dma->next_buffer; 198 address = (unsigned long)buf->address; 199 length = buf->used; 200 201 DRM_DEBUG("context %d, buffer %d (%ld bytes)\n", 202 buf->context, buf->idx, length); 203 204 if (buf->list == DRM_LIST_RECLAIM) { 205 drm_clear_next_buffer(dev); 206 drm_free_buffer(dev, buf); 207 clear_bit(0, &dev->dma_flag); 208 return -EINVAL; 209 } 210 211 if (!length) { 212 DRM_ERROR("0 length buffer\n"); 213 drm_clear_next_buffer(dev); 214 drm_free_buffer(dev, buf); 215 clear_bit(0, &dev->dma_flag); 216 return 0; 217 } 218 219 if (!gamma_dma_is_ready(dev)) { 220 clear_bit(0, &dev->dma_flag); 221 return -EBUSY; 222 } 223 224 if (buf->while_locked) { 225 if (!_DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock)) { 226 DRM_ERROR("Dispatching buffer %d from pid %d" 227 " \"while locked\", but no lock held\n", 228 buf->idx, buf->pid); 229 } 230 } else { 231 if (!locked && !drm_lock_take(&dev->lock.hw_lock->lock, 232 DRM_KERNEL_CONTEXT)) { 233 atomic_inc(&dma->total_missed_lock); 234 clear_bit(0, &dev->dma_flag); 235 return -EBUSY; 236 } 237 } 238 239 if (dev->last_context != buf->context 240 && !(dev->queuelist[buf->context]->flags 241 & _DRM_CONTEXT_PRESERVED)) { 242 /* PRE: dev->last_context != buf->context */ 243 if (drm_context_switch(dev, dev->last_context, buf->context)) { 244 drm_clear_next_buffer(dev); 245 drm_free_buffer(dev, buf); 246 } 247 retcode = -EBUSY; 248 goto cleanup; 249 250 /* POST: we will wait for the context 251 switch and will dispatch on a later call 252 when dev->last_context == buf->context. 253 NOTE WE HOLD THE LOCK THROUGHOUT THIS 254 TIME! */ 255 } 256 257 drm_clear_next_buffer(dev); 258 buf->pending = 1; 259 buf->waiting = 0; 260 buf->list = DRM_LIST_PEND; 261#if DRM_DMA_HISTOGRAM 262 buf->time_dispatched = get_cycles(); 263#endif 264 265 gamma_dma_dispatch(dev, address, length); 266 drm_free_buffer(dev, dma->this_buffer); 267 dma->this_buffer = buf; 268 269 atomic_add(length, &dma->total_bytes); 270 atomic_inc(&dma->total_dmas); 271 272 if (!buf->while_locked && !dev->context_flag && !locked) { 273 if (drm_lock_free(dev, &dev->lock.hw_lock->lock, 274 DRM_KERNEL_CONTEXT)) { 275 DRM_ERROR("\n"); 276 } 277 } 278cleanup: 279 280 clear_bit(0, &dev->dma_flag); 281 282#if DRM_DMA_HISTOGRAM 283 dma_stop = get_cycles(); 284 atomic_inc(&dev->histo.dma[drm_histogram_slot(dma_stop - dma_start)]); 285#endif 286 287 return retcode; 288} 289 290static void gamma_dma_schedule_timer_wrapper(unsigned long dev) 291{ 292 gamma_dma_schedule((drm_device_t *)dev, 0); 293} 294 295static void gamma_dma_schedule_tq_wrapper(void *dev) 296{ 297 gamma_dma_schedule(dev, 0); 298} 299 300int gamma_dma_schedule(drm_device_t *dev, int locked) 301{ 302 int next; 303 drm_queue_t *q; 304 drm_buf_t *buf; 305 int retcode = 0; 306 int processed = 0; 307 int missed; 308 int expire = 20; 309 drm_device_dma_t *dma = dev->dma; 310#if DRM_DMA_HISTOGRAM 311 cycles_t schedule_start; 312#endif 313 314 if (test_and_set_bit(0, &dev->interrupt_flag)) { 315 /* Not reentrant */ 316 atomic_inc(&dma->total_missed_sched); 317 return -EBUSY; 318 } 319 missed = atomic_read(&dma->total_missed_sched); 320 321#if DRM_DMA_HISTOGRAM 322 schedule_start = get_cycles(); 323#endif 324 325again: 326 if (dev->context_flag) { 327 clear_bit(0, &dev->interrupt_flag); 328 return -EBUSY; 329 } 330 if (dma->next_buffer) { 331 /* Unsent buffer that was previously 332 selected, but that couldn't be sent 333 because the lock could not be obtained 334 or the DMA engine wasn't ready. Try 335 again. */ 336 atomic_inc(&dma->total_tried); 337 if (!(retcode = gamma_do_dma(dev, locked))) { 338 atomic_inc(&dma->total_hit); 339 ++processed; 340 } 341 } else { 342 do { 343 next = drm_select_queue(dev, 344 gamma_dma_schedule_timer_wrapper); 345 if (next >= 0) { 346 q = dev->queuelist[next]; 347 buf = drm_waitlist_get(&q->waitlist); 348 dma->next_buffer = buf; 349 dma->next_queue = q; 350 if (buf && buf->list == DRM_LIST_RECLAIM) { 351 drm_clear_next_buffer(dev); 352 drm_free_buffer(dev, buf); 353 } 354 } 355 } while (next >= 0 && !dma->next_buffer); 356 if (dma->next_buffer) { 357 if (!(retcode = gamma_do_dma(dev, locked))) { 358 ++processed; 359 } 360 } 361 } 362 363 if (--expire) { 364 if (missed != atomic_read(&dma->total_missed_sched)) { 365 atomic_inc(&dma->total_lost); 366 if (gamma_dma_is_ready(dev)) goto again; 367 } 368 if (processed && gamma_dma_is_ready(dev)) { 369 atomic_inc(&dma->total_lost); 370 processed = 0; 371 goto again; 372 } 373 } 374 375 clear_bit(0, &dev->interrupt_flag); 376 377#if DRM_DMA_HISTOGRAM 378 atomic_inc(&dev->histo.schedule[drm_histogram_slot(get_cycles() 379 - schedule_start)]); 380#endif 381 return retcode; 382} 383 384static int gamma_dma_priority(drm_device_t *dev, drm_dma_t *d) 385{ 386 unsigned long address; 387 unsigned long length; 388 int must_free = 0; 389 int retcode = 0; 390 int i; 391 int idx; 392 drm_buf_t *buf; 393 drm_buf_t *last_buf = NULL; 394 drm_device_dma_t *dma = dev->dma; 395 DECLARE_WAITQUEUE(entry, current); 396 397 /* Turn off interrupt handling */ 398 while (test_and_set_bit(0, &dev->interrupt_flag)) { 399 schedule(); 400 if (signal_pending(current)) return -EINTR; 401 } 402 if (!(d->flags & _DRM_DMA_WHILE_LOCKED)) { 403 while (!drm_lock_take(&dev->lock.hw_lock->lock, 404 DRM_KERNEL_CONTEXT)) { 405 schedule(); 406 if (signal_pending(current)) { 407 clear_bit(0, &dev->interrupt_flag); 408 return -EINTR; 409 } 410 } 411 ++must_free; 412 } 413 atomic_inc(&dma->total_prio); 414 415 for (i = 0; i < d->send_count; i++) { 416 idx = d->send_indices[i]; 417 if (idx < 0 || idx >= dma->buf_count) { 418 DRM_ERROR("Index %d (of %d max)\n", 419 d->send_indices[i], dma->buf_count - 1); 420 continue; 421 } 422 buf = dma->buflist[ idx ]; 423 if (buf->pid != current->pid) { 424 DRM_ERROR("Process %d using buffer owned by %d\n", 425 current->pid, buf->pid); 426 retcode = -EINVAL; 427 goto cleanup; 428 } 429 if (buf->list != DRM_LIST_NONE) { 430 DRM_ERROR("Process %d using %d's buffer on list %d\n", 431 current->pid, buf->pid, buf->list); 432 retcode = -EINVAL; 433 goto cleanup; 434 } 435 /* This isn't a race condition on 436 buf->list, since our concern is the 437 buffer reclaim during the time the 438 process closes the /dev/drm? handle, so 439 it can't also be doing DMA. */ 440 buf->list = DRM_LIST_PRIO; 441 buf->used = d->send_sizes[i]; 442 buf->context = d->context; 443 buf->while_locked = d->flags & _DRM_DMA_WHILE_LOCKED; 444 address = (unsigned long)buf->address; 445 length = buf->used; 446 if (!length) { 447 DRM_ERROR("0 length buffer\n"); 448 } 449 if (buf->pending) { 450 DRM_ERROR("Sending pending buffer:" 451 " buffer %d, offset %d\n", 452 d->send_indices[i], i); 453 retcode = -EINVAL; 454 goto cleanup; 455 } 456 if (buf->waiting) { 457 DRM_ERROR("Sending waiting buffer:" 458 " buffer %d, offset %d\n", 459 d->send_indices[i], i); 460 retcode = -EINVAL; 461 goto cleanup; 462 } 463 buf->pending = 1; 464 465 if (dev->last_context != buf->context 466 && !(dev->queuelist[buf->context]->flags 467 & _DRM_CONTEXT_PRESERVED)) { 468 add_wait_queue(&dev->context_wait, &entry); 469 current->state = TASK_INTERRUPTIBLE; 470 /* PRE: dev->last_context != buf->context */ 471 drm_context_switch(dev, dev->last_context, 472 buf->context); 473 /* POST: we will wait for the context 474 switch and will dispatch on a later call 475 when dev->last_context == buf->context. 476 NOTE WE HOLD THE LOCK THROUGHOUT THIS 477 TIME! */ 478 schedule(); 479 current->state = TASK_RUNNING; 480 remove_wait_queue(&dev->context_wait, &entry); 481 if (signal_pending(current)) { 482 retcode = -EINTR; 483 goto cleanup; 484 } 485 if (dev->last_context != buf->context) { 486 DRM_ERROR("Context mismatch: %d %d\n", 487 dev->last_context, 488 buf->context); 489 } 490 } 491 492#if DRM_DMA_HISTOGRAM 493 buf->time_queued = get_cycles(); 494 buf->time_dispatched = buf->time_queued; 495#endif 496 gamma_dma_dispatch(dev, address, length); 497 atomic_add(length, &dma->total_bytes); 498 atomic_inc(&dma->total_dmas); 499 500 if (last_buf) { 501 drm_free_buffer(dev, last_buf); 502 } 503 last_buf = buf; 504 } 505 506 507cleanup: 508 if (last_buf) { 509 gamma_dma_ready(dev); 510 drm_free_buffer(dev, last_buf); 511 } 512 513 if (must_free && !dev->context_flag) { 514 if (drm_lock_free(dev, &dev->lock.hw_lock->lock, 515 DRM_KERNEL_CONTEXT)) { 516 DRM_ERROR("\n"); 517 } 518 } 519 clear_bit(0, &dev->interrupt_flag); 520 return retcode; 521} 522 523static int gamma_dma_send_buffers(drm_device_t *dev, drm_dma_t *d) 524{ 525 DECLARE_WAITQUEUE(entry, current); 526 drm_buf_t *last_buf = NULL; 527 int retcode = 0; 528 drm_device_dma_t *dma = dev->dma; 529 530 if (d->flags & _DRM_DMA_BLOCK) { 531 last_buf = dma->buflist[d->send_indices[d->send_count-1]]; 532 add_wait_queue(&last_buf->dma_wait, &entry); 533 } 534 535 if ((retcode = drm_dma_enqueue(dev, d))) { 536 if (d->flags & _DRM_DMA_BLOCK) 537 remove_wait_queue(&last_buf->dma_wait, &entry); 538 return retcode; 539 } 540 541 gamma_dma_schedule(dev, 0); 542 543 if (d->flags & _DRM_DMA_BLOCK) { 544 DRM_DEBUG("%d waiting\n", current->pid); 545 for (;;) { 546 current->state = TASK_INTERRUPTIBLE; 547 if (!last_buf->waiting && !last_buf->pending) 548 break; /* finished */ 549 schedule(); 550 if (signal_pending(current)) { 551 retcode = -EINTR; /* Can't restart */ 552 break; 553 } 554 } 555 current->state = TASK_RUNNING; 556 DRM_DEBUG("%d running\n", current->pid); 557 remove_wait_queue(&last_buf->dma_wait, &entry); 558 if (!retcode 559 || (last_buf->list==DRM_LIST_PEND && !last_buf->pending)) { 560 if (!waitqueue_active(&last_buf->dma_wait)) { 561 drm_free_buffer(dev, last_buf); 562 } 563 } 564 if (retcode) { 565 DRM_ERROR("ctx%d w%d p%d c%d i%d l%d %d/%d\n", 566 d->context, 567 last_buf->waiting, 568 last_buf->pending, 569 DRM_WAITCOUNT(dev, d->context), 570 last_buf->idx, 571 last_buf->list, 572 last_buf->pid, 573 current->pid); 574 } 575 } 576 return retcode; 577} 578 579int gamma_dma(struct inode *inode, struct file *filp, unsigned int cmd, 580 unsigned long arg) 581{ 582 drm_file_t *priv = filp->private_data; 583 drm_device_t *dev = priv->dev; 584 drm_device_dma_t *dma = dev->dma; 585 int retcode = 0; 586 drm_dma_t d; 587 588 if (copy_from_user(&d, (drm_dma_t *)arg, sizeof(d))) 589 return -EFAULT; 590 DRM_DEBUG("%d %d: %d send, %d req\n", 591 current->pid, d.context, d.send_count, d.request_count); 592 593 if (d.context == DRM_KERNEL_CONTEXT || d.context >= dev->queue_slots) { 594 DRM_ERROR("Process %d using context %d\n", 595 current->pid, d.context); 596 return -EINVAL; 597 } 598 if (d.send_count < 0 || d.send_count > dma->buf_count) { 599 DRM_ERROR("Process %d trying to send %d buffers (of %d max)\n", 600 current->pid, d.send_count, dma->buf_count); 601 return -EINVAL; 602 } 603 if (d.request_count < 0 || d.request_count > dma->buf_count) { 604 DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", 605 current->pid, d.request_count, dma->buf_count); 606 return -EINVAL; 607 } 608 609 if (d.send_count) { 610 if (d.flags & _DRM_DMA_PRIORITY) 611 retcode = gamma_dma_priority(dev, &d); 612 else 613 retcode = gamma_dma_send_buffers(dev, &d); 614 } 615 616 d.granted_count = 0; 617 618 if (!retcode && d.request_count) { 619 retcode = drm_dma_get_buffers(dev, &d); 620 } 621 622 DRM_DEBUG("%d returning, granted = %d\n", 623 current->pid, d.granted_count); 624 if (copy_to_user((drm_dma_t *)arg, &d, sizeof(d))) 625 return -EFAULT; 626 627 return retcode; 628} 629 630int gamma_irq_install(drm_device_t *dev, int irq) 631{ 632 int retcode; 633 634 if (!irq) return -EINVAL; 635 636 down(&dev->struct_sem); 637 if (dev->irq) { 638 up(&dev->struct_sem); 639 return -EBUSY; 640 } 641 dev->irq = irq; 642 up(&dev->struct_sem); 643 644 DRM_DEBUG("%d\n", irq); 645 646 dev->context_flag = 0; 647 dev->interrupt_flag = 0; 648 dev->dma_flag = 0; 649 650 dev->dma->next_buffer = NULL; 651 dev->dma->next_queue = NULL; 652 dev->dma->this_buffer = NULL; 653 654 INIT_LIST_HEAD(&dev->tq.list); 655 dev->tq.sync = 0; 656 dev->tq.routine = gamma_dma_schedule_tq_wrapper; 657 dev->tq.data = dev; 658 659 660 /* Before installing handler */ 661 GAMMA_WRITE(GAMMA_GCOMMANDMODE, 0); 662 GAMMA_WRITE(GAMMA_GDMACONTROL, 0); 663 664 /* Install handler */ 665 if ((retcode = request_irq(dev->irq, 666 gamma_dma_service, 667 0, 668 dev->devname, 669 dev))) { 670 down(&dev->struct_sem); 671 dev->irq = 0; 672 up(&dev->struct_sem); 673 return retcode; 674 } 675 676 /* After installing handler */ 677 GAMMA_WRITE(GAMMA_GINTENABLE, 0x2001); 678 GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0x0008); 679 GAMMA_WRITE(GAMMA_GDELAYTIMER, 0x39090); 680 681 return 0; 682} 683 684int gamma_irq_uninstall(drm_device_t *dev) 685{ 686 int irq; 687 688 down(&dev->struct_sem); 689 irq = dev->irq; 690 dev->irq = 0; 691 up(&dev->struct_sem); 692 693 if (!irq) return -EINVAL; 694 695 DRM_DEBUG("%d\n", irq); 696 697 GAMMA_WRITE(GAMMA_GDELAYTIMER, 0); 698 GAMMA_WRITE(GAMMA_COMMANDINTENABLE, 0); 699 GAMMA_WRITE(GAMMA_GINTENABLE, 0); 700 free_irq(irq, dev); 701 702 return 0; 703} 704 705 706int gamma_control(struct inode *inode, struct file *filp, unsigned int cmd, 707 unsigned long arg) 708{ 709 drm_file_t *priv = filp->private_data; 710 drm_device_t *dev = priv->dev; 711 drm_control_t ctl; 712 int retcode; 713 714 if (copy_from_user(&ctl, (drm_control_t *)arg, sizeof(ctl))) 715 return -EFAULT; 716 717 switch (ctl.func) { 718 case DRM_INST_HANDLER: 719 if ((retcode = gamma_irq_install(dev, ctl.irq))) 720 return retcode; 721 break; 722 case DRM_UNINST_HANDLER: 723 if ((retcode = gamma_irq_uninstall(dev))) 724 return retcode; 725 break; 726 default: 727 return -EINVAL; 728 } 729 return 0; 730} 731 732int gamma_lock(struct inode *inode, struct file *filp, unsigned int cmd, 733 unsigned long arg) 734{ 735 drm_file_t *priv = filp->private_data; 736 drm_device_t *dev = priv->dev; 737 DECLARE_WAITQUEUE(entry, current); 738 int ret = 0; 739 drm_lock_t lock; 740 drm_queue_t *q; 741#if DRM_DMA_HISTOGRAM 742 cycles_t start; 743 744 dev->lck_start = start = get_cycles(); 745#endif 746 747 if (copy_from_user(&lock, (drm_lock_t *)arg, sizeof(lock))) 748 return -EFAULT; 749 750 if (lock.context == DRM_KERNEL_CONTEXT) { 751 DRM_ERROR("Process %d using kernel context %d\n", 752 current->pid, lock.context); 753 return -EINVAL; 754 } 755 756 DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", 757 lock.context, current->pid, dev->lock.hw_lock->lock, 758 lock.flags); 759 760 if (lock.context < 0 || lock.context >= dev->queue_count) 761 return -EINVAL; 762 q = dev->queuelist[lock.context]; 763 764 ret = drm_flush_block_and_flush(dev, lock.context, lock.flags); 765 766 if (!ret) { 767 if (_DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock) 768 != lock.context) { 769 long j = jiffies - dev->lock.lock_time; 770 771 if (j > 0 && j <= DRM_LOCK_SLICE) { 772 /* Can't take lock if we just had it and 773 there is contention. */ 774 current->state = TASK_INTERRUPTIBLE; 775 schedule_timeout(j); 776 } 777 } 778 add_wait_queue(&dev->lock.lock_queue, &entry); 779 for (;;) { 780 current->state = TASK_INTERRUPTIBLE; 781 if (!dev->lock.hw_lock) { 782 /* Device has been unregistered */ 783 ret = -EINTR; 784 break; 785 } 786 if (drm_lock_take(&dev->lock.hw_lock->lock, 787 lock.context)) { 788 dev->lock.pid = current->pid; 789 dev->lock.lock_time = jiffies; 790 atomic_inc(&dev->total_locks); 791 atomic_inc(&q->total_locks); 792 break; /* Got lock */ 793 } 794 795 /* Contention */ 796 atomic_inc(&dev->total_sleeps); 797 schedule(); 798 if (signal_pending(current)) { 799 ret = -ERESTARTSYS; 800 break; 801 } 802 } 803 current->state = TASK_RUNNING; 804 remove_wait_queue(&dev->lock.lock_queue, &entry); 805 } 806 807 drm_flush_unblock(dev, lock.context, lock.flags); /* cleanup phase */ 808 809 if (!ret) { 810 sigemptyset(&dev->sigmask); 811 sigaddset(&dev->sigmask, SIGSTOP); 812 sigaddset(&dev->sigmask, SIGTSTP); 813 sigaddset(&dev->sigmask, SIGTTIN); 814 sigaddset(&dev->sigmask, SIGTTOU); 815 dev->sigdata.context = lock.context; 816 dev->sigdata.lock = dev->lock.hw_lock; 817 block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); 818 819 if (lock.flags & _DRM_LOCK_READY) 820 gamma_dma_ready(dev); 821 if (lock.flags & _DRM_LOCK_QUIESCENT) { 822 if (gamma_found() == 1) { 823 gamma_dma_quiescent_single(dev); 824 } else { 825 gamma_dma_quiescent_dual(dev); 826 } 827 } 828 } 829 DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); 830 831#if DRM_DMA_HISTOGRAM 832 atomic_inc(&dev->histo.lacq[drm_histogram_slot(get_cycles() - start)]); 833#endif 834 835 return ret; 836} 837