aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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--include/drm/drm.h33
-rw-r--r--include/drm/drmP.h26
6 files changed, 251 insertions, 4 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 0a6f0b3bdc78..72754aca7abf 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -550,6 +550,62 @@ out:
550 return ret; 550 return ret;
551} 551}
552 552
553static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
554 union drm_wait_vblank *vblwait,
555 struct drm_file *file_priv)
556{
557 struct drm_pending_vblank_event *e;
558 struct timeval now;
559 unsigned long flags;
560 unsigned int seq;
561
562 e = kzalloc(sizeof *e, GFP_KERNEL);
563 if (e == NULL)
564 return -ENOMEM;
565
566 e->pipe = pipe;
567 e->event.base.type = DRM_EVENT_VBLANK;
568 e->event.base.length = sizeof e->event;
569 e->event.user_data = vblwait->request.signal;
570 e->base.event = &e->event.base;
571 e->base.file_priv = file_priv;
572 e->base.destroy = (void (*) (struct drm_pending_event *)) kfree;
573
574 do_gettimeofday(&now);
575 spin_lock_irqsave(&dev->event_lock, flags);
576
577 if (file_priv->event_space < sizeof e->event) {
578 spin_unlock_irqrestore(&dev->event_lock, flags);
579 kfree(e);
580 return -ENOMEM;
581 }
582
583 file_priv->event_space -= sizeof e->event;
584 seq = drm_vblank_count(dev, pipe);
585 if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
586 (seq - vblwait->request.sequence) <= (1 << 23)) {
587 vblwait->request.sequence = seq + 1;
588 }
589
590 DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
591 vblwait->request.sequence, seq, pipe);
592
593 e->event.sequence = vblwait->request.sequence;
594 if ((seq - vblwait->request.sequence) <= (1 << 23)) {
595 e->event.tv_sec = now.tv_sec;
596 e->event.tv_usec = now.tv_usec;
597 drm_vblank_put(dev, e->pipe);
598 list_add_tail(&e->base.link, &e->base.file_priv->event_list);
599 wake_up_interruptible(&e->base.file_priv->event_wait);
600 } else {
601 list_add_tail(&e->base.link, &dev->vblank_event_list);
602 }
603
604 spin_unlock_irqrestore(&dev->event_lock, flags);
605
606 return 0;
607}
608
553/** 609/**
554 * Wait for VBLANK. 610 * Wait for VBLANK.
555 * 611 *
@@ -609,6 +665,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
609 goto done; 665 goto done;
610 } 666 }
611 667
668 if (flags & _DRM_VBLANK_EVENT)
669 return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
670
612 if ((flags & _DRM_VBLANK_NEXTONMISS) && 671 if ((flags & _DRM_VBLANK_NEXTONMISS) &&
613 (seq - vblwait->request.sequence) <= (1<<23)) { 672 (seq - vblwait->request.sequence) <= (1<<23)) {
614 vblwait->request.sequence = seq + 1; 673 vblwait->request.sequence = seq + 1;
@@ -641,6 +700,38 @@ done:
641 return ret; 700 return ret;
642} 701}
643 702
703void drm_handle_vblank_events(struct drm_device *dev, int crtc)
704{
705 struct drm_pending_vblank_event *e, *t;
706 struct timeval now;
707 unsigned long flags;
708 unsigned int seq;
709
710 do_gettimeofday(&now);
711 seq = drm_vblank_count(dev, crtc);
712
713 spin_lock_irqsave(&dev->event_lock, flags);
714
715 list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
716 if (e->pipe != crtc)
717 continue;
718 if ((seq - e->event.sequence) > (1<<23))
719 continue;
720
721 DRM_DEBUG("vblank event on %d, current %d\n",
722 e->event.sequence, seq);
723
724 e->event.sequence = seq;
725 e->event.tv_sec = now.tv_sec;
726 e->event.tv_usec = now.tv_usec;
727 drm_vblank_put(dev, e->pipe);
728 list_move_tail(&e->base.link, &e->base.file_priv->event_list);
729 wake_up_interruptible(&e->base.file_priv->event_wait);
730 }
731
732 spin_unlock_irqrestore(&dev->event_lock, flags);
733}
734
644/** 735/**
645 * drm_handle_vblank - handle a vblank event 736 * drm_handle_vblank - handle a vblank event
646 * @dev: DRM device 737 * @dev: DRM device
@@ -651,7 +742,11 @@ done:
651 */ 742 */
652void drm_handle_vblank(struct drm_device *dev, int crtc) 743void drm_handle_vblank(struct drm_device *dev, int crtc)
653{ 744{
745 if (!dev->num_crtcs)
746 return;
747
654 atomic_inc(&dev->_vblank_count[crtc]); 748 atomic_inc(&dev->_vblank_count[crtc]);
655 DRM_WAKEUP(&dev->vbl_queue[crtc]); 749 DRM_WAKEUP(&dev->vbl_queue[crtc]);
750 drm_handle_vblank_events(dev, crtc);
656} 751}
657EXPORT_SYMBOL(drm_handle_vblank); 752EXPORT_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 7f436ec075f6..2fa217862058 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -333,6 +333,7 @@ static struct drm_driver driver = {
333 .mmap = drm_gem_mmap, 333 .mmap = drm_gem_mmap,
334 .poll = drm_poll, 334 .poll = drm_poll,
335 .fasync = drm_fasync, 335 .fasync = drm_fasync,
336 .read = drm_read,
336#ifdef CONFIG_COMPAT 337#ifdef CONFIG_COMPAT
337 .compat_ioctl = i915_compat_ioctl, 338 .compat_ioctl = i915_compat_ioctl,
338#endif 339#endif
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 7cb50bdde46d..fa6d9155873d 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -454,6 +454,7 @@ struct drm_irq_busid {
454enum drm_vblank_seq_type { 454enum drm_vblank_seq_type {
455 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ 455 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
456 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ 456 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
457 _DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */
457 _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */ 458 _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
458 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ 459 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
459 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ 460 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
@@ -461,8 +462,8 @@ enum drm_vblank_seq_type {
461}; 462};
462 463
463#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) 464#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
464#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY | \ 465#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \
465 _DRM_VBLANK_NEXTONMISS) 466 _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)
466 467
467struct drm_wait_vblank_request { 468struct drm_wait_vblank_request {
468 enum drm_vblank_seq_type type; 469 enum drm_vblank_seq_type type;
@@ -698,6 +699,34 @@ struct drm_gem_open {
698#define DRM_COMMAND_BASE 0x40 699#define DRM_COMMAND_BASE 0x40
699#define DRM_COMMAND_END 0xA0 700#define DRM_COMMAND_END 0xA0
700 701
702/**
703 * Header for events written back to userspace on the drm fd. The
704 * type defines the type of event, the length specifies the total
705 * length of the event (including the header), and user_data is
706 * typically a 64 bit value passed with the ioctl that triggered the
707 * event. A read on the drm fd will always only return complete
708 * events, that is, if for example the read buffer is 100 bytes, and
709 * there are two 64 byte events pending, only one will be returned.
710 *
711 * Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
712 * up are chipset specific.
713 */
714struct drm_event {
715 __u32 type;
716 __u32 length;
717};
718
719#define DRM_EVENT_VBLANK 0x01
720
721struct drm_event_vblank {
722 struct drm_event base;
723 __u64 user_data;
724 __u32 tv_sec;
725 __u32 tv_usec;
726 __u32 sequence;
727 __u32 reserved;
728};
729
701/* typedef area */ 730/* typedef area */
702#ifndef __KERNEL__ 731#ifndef __KERNEL__
703typedef struct drm_clip_rect drm_clip_rect_t; 732typedef struct drm_clip_rect drm_clip_rect_t;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index c8e64bbadbcf..b0b36838ab11 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -426,6 +426,14 @@ struct drm_buf_entry {
426 struct drm_freelist freelist; 426 struct drm_freelist freelist;
427}; 427};
428 428
429/* Event queued up for userspace to read */
430struct drm_pending_event {
431 struct drm_event *event;
432 struct list_head link;
433 struct drm_file *file_priv;
434 void (*destroy)(struct drm_pending_event *event);
435};
436
429/** File private data */ 437/** File private data */
430struct drm_file { 438struct drm_file {
431 int authenticated; 439 int authenticated;
@@ -449,6 +457,10 @@ struct drm_file {
449 struct drm_master *master; /* master this node is currently associated with 457 struct drm_master *master; /* master this node is currently associated with
450 N.B. not always minor->master */ 458 N.B. not always minor->master */
451 struct list_head fbs; 459 struct list_head fbs;
460
461 wait_queue_head_t event_wait;
462 struct list_head event_list;
463 int event_space;
452}; 464};
453 465
454/** Wait queue */ 466/** Wait queue */
@@ -900,6 +912,12 @@ struct drm_minor {
900 struct drm_mode_group mode_group; 912 struct drm_mode_group mode_group;
901}; 913};
902 914
915struct drm_pending_vblank_event {
916 struct drm_pending_event base;
917 int pipe;
918 struct drm_event_vblank event;
919};
920
903/** 921/**
904 * DRM device structure. This structure represent a complete card that 922 * DRM device structure. This structure represent a complete card that
905 * may contain multiple heads. 923 * may contain multiple heads.
@@ -999,6 +1017,12 @@ struct drm_device {
999 1017
1000 u32 max_vblank_count; /**< size of vblank counter register */ 1018 u32 max_vblank_count; /**< size of vblank counter register */
1001 1019
1020 /**
1021 * List of events
1022 */
1023 struct list_head vblank_event_list;
1024 spinlock_t event_lock;
1025
1002 /*@} */ 1026 /*@} */
1003 cycles_t ctx_start; 1027 cycles_t ctx_start;
1004 cycles_t lck_start; 1028 cycles_t lck_start;
@@ -1135,6 +1159,8 @@ extern int drm_lastclose(struct drm_device *dev);
1135extern int drm_open(struct inode *inode, struct file *filp); 1159extern int drm_open(struct inode *inode, struct file *filp);
1136extern int drm_stub_open(struct inode *inode, struct file *filp); 1160extern int drm_stub_open(struct inode *inode, struct file *filp);
1137extern int drm_fasync(int fd, struct file *filp, int on); 1161extern int drm_fasync(int fd, struct file *filp, int on);
1162extern ssize_t drm_read(struct file *filp, char __user *buffer,
1163 size_t count, loff_t *offset);
1138extern int drm_release(struct inode *inode, struct file *filp); 1164extern int drm_release(struct inode *inode, struct file *filp);
1139 1165
1140 /* Mapping support (drm_vm.h) */ 1166 /* Mapping support (drm_vm.h) */