aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/drm_fops.c98
-rw-r--r--drivers/gpu/drm/drm_irq.c95
-rw-r--r--drivers/gpu/drm/drm_stub.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c1
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c45
5 files changed, 198 insertions, 43 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 251bc0e3b5ec..8ac7fbf6b2b7 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
257 257
258 INIT_LIST_HEAD(&priv->lhead); 258 INIT_LIST_HEAD(&priv->lhead);
259 INIT_LIST_HEAD(&priv->fbs); 259 INIT_LIST_HEAD(&priv->fbs);
260 INIT_LIST_HEAD(&priv->event_list);
261 init_waitqueue_head(&priv->event_wait);
262 priv->event_space = 4096; /* set aside 4k for event buffer */
260 263
261 if (dev->driver->driver_features & DRIVER_GEM) 264 if (dev->driver->driver_features & DRIVER_GEM)
262 drm_gem_open(dev, priv); 265 drm_gem_open(dev, priv);
@@ -413,6 +416,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp)
413 } 416 }
414} 417}
415 418
419static void drm_events_release(struct drm_file *file_priv)
420{
421 struct drm_device *dev = file_priv->minor->dev;
422 struct drm_pending_event *e, *et;
423 struct drm_pending_vblank_event *v, *vt;
424 unsigned long flags;
425
426 spin_lock_irqsave(&dev->event_lock, flags);
427
428 /* Remove pending flips */
429 list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link)
430 if (v->base.file_priv == file_priv) {
431 list_del(&v->base.link);
432 drm_vblank_put(dev, v->pipe);
433 v->base.destroy(&v->base);
434 }
435
436 /* Remove unconsumed events */
437 list_for_each_entry_safe(e, et, &file_priv->event_list, link)
438 e->destroy(e);
439
440 spin_unlock_irqrestore(&dev->event_lock, flags);
441}
442
416/** 443/**
417 * Release file. 444 * Release file.
418 * 445 *
@@ -451,6 +478,8 @@ int drm_release(struct inode *inode, struct file *filp)
451 if (file_priv->minor->master) 478 if (file_priv->minor->master)
452 drm_master_release(dev, filp); 479 drm_master_release(dev, filp);
453 480
481 drm_events_release(file_priv);
482
454 if (dev->driver->driver_features & DRIVER_GEM) 483 if (dev->driver->driver_features & DRIVER_GEM)
455 drm_gem_release(dev, file_priv); 484 drm_gem_release(dev, file_priv);
456 485
@@ -544,9 +573,74 @@ int drm_release(struct inode *inode, struct file *filp)
544} 573}
545EXPORT_SYMBOL(drm_release); 574EXPORT_SYMBOL(drm_release);
546 575
547/** No-op. */ 576static bool
577drm_dequeue_event(struct drm_file *file_priv,
578 size_t total, size_t max, struct drm_pending_event **out)
579{
580 struct drm_device *dev = file_priv->minor->dev;
581 struct drm_pending_event *e;
582 unsigned long flags;
583 bool ret = false;
584
585 spin_lock_irqsave(&dev->event_lock, flags);
586
587 *out = NULL;
588 if (list_empty(&file_priv->event_list))
589 goto out;
590 e = list_first_entry(&file_priv->event_list,
591 struct drm_pending_event, link);
592 if (e->event->length + total > max)
593 goto out;
594
595 file_priv->event_space += e->event->length;
596 list_del(&e->link);
597 *out = e;
598 ret = true;
599
600out:
601 spin_unlock_irqrestore(&dev->event_lock, flags);
602 return ret;
603}
604
605ssize_t drm_read(struct file *filp, char __user *buffer,
606 size_t count, loff_t *offset)
607{
608 struct drm_file *file_priv = filp->private_data;
609 struct drm_pending_event *e;
610 size_t total;
611 ssize_t ret;
612
613 ret = wait_event_interruptible(file_priv->event_wait,
614 !list_empty(&file_priv->event_list));
615 if (ret < 0)
616 return ret;
617
618 total = 0;
619 while (drm_dequeue_event(file_priv, total, count, &e)) {
620 if (copy_to_user(buffer + total,
621 e->event, e->event->length)) {
622 total = -EFAULT;
623 break;
624 }
625
626 total += e->event->length;
627 e->destroy(e);
628 }
629
630 return total;
631}
632EXPORT_SYMBOL(drm_read);
633
548unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) 634unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
549{ 635{
550 return 0; 636 struct drm_file *file_priv = filp->private_data;
637 unsigned int mask = 0;
638
639 poll_wait(filp, &file_priv->event_wait, wait);
640
641 if (!list_empty(&file_priv->event_list))
642 mask |= POLLIN | POLLRDNORM;
643
644 return mask;
551} 645}
552EXPORT_SYMBOL(drm_poll); 646EXPORT_SYMBOL(drm_poll);
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index f85aaf21e783..d9af7964f81c 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -523,6 +523,62 @@ out:
523 return ret; 523 return ret;
524} 524}
525 525
526static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
527 union drm_wait_vblank *vblwait,
528 struct drm_file *file_priv)
529{
530 struct drm_pending_vblank_event *e;
531 struct timeval now;
532 unsigned long flags;
533 unsigned int seq;
534
535 e = kzalloc(sizeof *e, GFP_KERNEL);
536 if (e == NULL)
537 return -ENOMEM;
538
539 e->pipe = pipe;
540 e->event.base.type = DRM_EVENT_VBLANK;
541 e->event.base.length = sizeof e->event;
542 e->event.user_data = vblwait->request.signal;
543 e->base.event = &e->event.base;
544 e->base.file_priv = file_priv;
545 e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
546
547 do_gettimeofday(&now);
548 spin_lock_irqsave(&dev->event_lock, flags);
549
550 if (file_priv->event_space < sizeof e->event) {
551 spin_unlock_irqrestore(&dev->event_lock, flags);
552 kfree(e);
553 return -ENOMEM;
554 }
555
556 file_priv->event_space -= sizeof e->event;
557 seq = drm_vblank_count(dev, pipe);
558 if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
559 (seq - vblwait->request.sequence) <= (1 << 23)) {
560 vblwait->request.sequence = seq + 1;
561 }
562
563 DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
564 vblwait->request.sequence, seq, pipe);
565
566 e->event.sequence = vblwait->request.sequence;
567 if ((seq - vblwait->request.sequence) <= (1 << 23)) {
568 e->event.tv_sec = now.tv_sec;
569 e->event.tv_usec = now.tv_usec;
570 drm_vblank_put(dev, e->pipe);
571 list_add_tail(&e->base.link, &e->base.file_priv->event_list);
572 wake_up_interruptible(&e->base.file_priv->event_wait);
573 } else {
574 list_add_tail(&e->base.link, &dev->vblank_event_list);
575 }
576
577 spin_unlock_irqrestore(&dev->event_lock, flags);
578
579 return 0;
580}
581
526/** 582/**
527 * Wait for VBLANK. 583 * Wait for VBLANK.
528 * 584 *
@@ -582,6 +638,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
582 goto done; 638 goto done;
583 } 639 }
584 640
641 if (flags & _DRM_VBLANK_EVENT)
642 return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
643
585 if ((flags & _DRM_VBLANK_NEXTONMISS) && 644 if ((flags & _DRM_VBLANK_NEXTONMISS) &&
586 (seq - vblwait->request.sequence) <= (1<<23)) { 645 (seq - vblwait->request.sequence) <= (1<<23)) {
587 vblwait->request.sequence = seq + 1; 646 vblwait->request.sequence = seq + 1;
@@ -614,6 +673,38 @@ done:
614 return ret; 673 return ret;
615} 674}
616 675
676void drm_handle_vblank_events(struct drm_device *dev, int crtc)
677{
678 struct drm_pending_vblank_event *e, *t;
679 struct timeval now;
680 unsigned long flags;
681 unsigned int seq;
682
683 do_gettimeofday(&now);
684 seq = drm_vblank_count(dev, crtc);
685
686 spin_lock_irqsave(&dev->event_lock, flags);
687
688 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
689 if (e->pipe != crtc)
690 continue;
691 if ((seq - e->event.sequence) > (1<<23))
692 continue;
693
694 DRM_DEBUG("vblank event on %d, current %d\n",
695 e->event.sequence, seq);
696
697 e->event.sequence = seq;
698 e->event.tv_sec = now.tv_sec;
699 e->event.tv_usec = now.tv_usec;
700 drm_vblank_put(dev, e->pipe);
701 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
702 wake_up_interruptible(&e->base.file_priv->event_wait);
703 }
704
705 spin_unlock_irqrestore(&dev->event_lock, flags);
706}
707
617/** 708/**
618 * drm_handle_vblank - handle a vblank event 709 * drm_handle_vblank - handle a vblank event
619 * @dev: DRM device 710 * @dev: DRM device
@@ -624,7 +715,11 @@ done:
624 */ 715 */
625void drm_handle_vblank(struct drm_device *dev, int crtc) 716void drm_handle_vblank(struct drm_device *dev, int crtc)
626{ 717{
718 if (!dev->num_crtcs)
719 return;
720
627 atomic_inc(&dev->_vblank_count[crtc]); 721 atomic_inc(&dev->_vblank_count[crtc]);
628 DRM_WAKEUP(&dev->vbl_queue[crtc]); 722 DRM_WAKEUP(&dev->vbl_queue[crtc]);
723 drm_handle_vblank_events(dev, crtc);
629} 724}
630EXPORT_SYMBOL(drm_handle_vblank); 725EXPORT_SYMBOL(drm_handle_vblank);
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index 55bb8a82d612..adb864dfef3e 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -220,9 +220,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
220 INIT_LIST_HEAD(&dev->ctxlist); 220 INIT_LIST_HEAD(&dev->ctxlist);
221 INIT_LIST_HEAD(&dev->vmalist); 221 INIT_LIST_HEAD(&dev->vmalist);
222 INIT_LIST_HEAD(&dev->maplist); 222 INIT_LIST_HEAD(&dev->maplist);
223 INIT_LIST_HEAD(&dev->vblank_event_list);
223 224
224 spin_lock_init(&dev->count_lock); 225 spin_lock_init(&dev->count_lock);
225 spin_lock_init(&dev->drw_lock); 226 spin_lock_init(&dev->drw_lock);
227 spin_lock_init(&dev->event_lock);
226 init_timer(&dev->timer); 228 init_timer(&dev->timer);
227 mutex_init(&dev->struct_mutex); 229 mutex_init(&dev->struct_mutex);
228 mutex_init(&dev->ctxlist_mutex); 230 mutex_init(&dev->ctxlist_mutex);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index dbe568c9327b..b81305e33c79 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -206,6 +206,7 @@ static struct drm_driver driver = {
206 .mmap = drm_gem_mmap, 206 .mmap = drm_gem_mmap,
207 .poll = drm_poll, 207 .poll = drm_poll,
208 .fasync = drm_fasync, 208 .fasync = drm_fasync,
209 .read = drm_read,
209#ifdef CONFIG_COMPAT 210#ifdef CONFIG_COMPAT
210 .compat_ioctl = i915_compat_ioctl, 211 .compat_ioctl = i915_compat_ioctl,
211#endif 212#endif
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index 4f7afc79dd82..0b2f9c2ad2c1 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -1941,8 +1941,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev)
1941 for (t = 0; t < dev_priv->usec_timeout; t++) { 1941 for (t = 0; t < dev_priv->usec_timeout; t++) {
1942 u32 done_age = GET_SCRATCH(dev_priv, 1); 1942 u32 done_age = GET_SCRATCH(dev_priv, 1);
1943 DRM_DEBUG("done_age = %d\n", done_age); 1943 DRM_DEBUG("done_age = %d\n", done_age);
1944 for (i = start; i < dma->buf_count; i++) { 1944 for (i = 0; i < dma->buf_count; i++) {
1945 buf = dma->buflist[i]; 1945 buf = dma->buflist[start];
1946 buf_priv = buf->dev_private; 1946 buf_priv = buf->dev_private;
1947 if (buf->file_priv == NULL || (buf->pending && 1947 if (buf->file_priv == NULL || (buf->pending &&
1948 buf_priv->age <= 1948 buf_priv->age <=
@@ -1951,7 +1951,8 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev)
1951 buf->pending = 0; 1951 buf->pending = 0;
1952 return buf; 1952 return buf;
1953 } 1953 }
1954 start = 0; 1954 if (++start >= dma->buf_count)
1955 start = 0;
1955 } 1956 }
1956 1957
1957 if (t) { 1958 if (t) {
@@ -1960,47 +1961,9 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev)
1960 } 1961 }
1961 } 1962 }
1962 1963
1963 DRM_DEBUG("returning NULL!\n");
1964 return NULL; 1964 return NULL;
1965} 1965}
1966 1966
1967#if 0
1968struct drm_buf *radeon_freelist_get(struct drm_device * dev)
1969{
1970 struct drm_device_dma *dma = dev->dma;
1971 drm_radeon_private_t *dev_priv = dev->dev_private;
1972 drm_radeon_buf_priv_t *buf_priv;
1973 struct drm_buf *buf;
1974 int i, t;
1975 int start;
1976 u32 done_age;
1977
1978 done_age = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1));
1979 if (++dev_priv->last_buf >= dma->buf_count)
1980 dev_priv->last_buf = 0;
1981
1982 start = dev_priv->last_buf;
1983 dev_priv->stats.freelist_loops++;
1984
1985 for (t = 0; t < 2; t++) {
1986 for (i = start; i < dma->buf_count; i++) {
1987 buf = dma->buflist[i];
1988 buf_priv = buf->dev_private;
1989 if (buf->file_priv == 0 || (buf->pending &&
1990 buf_priv->age <=
1991 done_age)) {
1992 dev_priv->stats.requested_bufs++;
1993 buf->pending = 0;
1994 return buf;
1995 }
1996 }
1997 start = 0;
1998 }
1999
2000 return NULL;
2001}
2002#endif
2003
2004void radeon_freelist_reset(struct drm_device * dev) 1967void radeon_freelist_reset(struct drm_device * dev)
2005{ 1968{
2006 struct drm_device_dma *dma = dev->dma; 1969 struct drm_device_dma *dma = dev->dma;