aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-08-25 19:04:03 -0400
committerDave Airlie <airlied@redhat.com>2014-08-25 19:04:03 -0400
commitc0ee755fc57319a623e0d9ef839cf8fb26ce8d60 (patch)
tree727fe78a158757f75b54d7e037b383ad6a39843c /drivers/gpu/drm/drm_irq.c
parent52addcf9d6669fa439387610bc65c92fa0980cef (diff)
parent14f476fa24e81d0beea1aa14d763102958518d60 (diff)
Merge tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel into drm-next
So small drm stuff all over for 3.18. Biggest one is the cmdline parsing from Chris with a few fixes from me to make it work for stupid kernel configs. Plus the atomic prep series. Tested for more than a week in -nightly and Ville/Imre indeed discovered some fun which is now fixed (and i915 vblank patches postponed since the fixups need this branch plus drm-intel-next merged together). * tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel: drm: Use the type of the array element when reallocating drm: Don't return 0 for a value used as a denominator drm: Docbook fixes drm/irq: Implement a generic vblank_wait function drm: Add a plane->reset hook drm: trylock modest locking for fbdev panics drm: Move ->old_fb from crtc to plane drm: Handle legacy per-crtc locking with full acquire ctx drm: Move modeset_lock_all helpers to drm_modeset_lock.[hc] drm: Add drm_plane/connector_index drm: idiot-proof vblank drm: Warn when leaking flip events on close drm: Perform cmdline mode parsing during connector initialisation video/fbdev: Always built-in video= cmdline parsing drm: Don't grab an fb reference for the idr
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 08ba1209228e..5708c056fa1b 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -720,6 +720,8 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
720 */ 720 */
721u32 drm_vblank_count(struct drm_device *dev, int crtc) 721u32 drm_vblank_count(struct drm_device *dev, int crtc)
722{ 722{
723 if (WARN_ON(crtc >= dev->num_crtcs))
724 return 0;
723 return atomic_read(&dev->vblank[crtc].count); 725 return atomic_read(&dev->vblank[crtc].count);
724} 726}
725EXPORT_SYMBOL(drm_vblank_count); 727EXPORT_SYMBOL(drm_vblank_count);
@@ -742,6 +744,9 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
742{ 744{
743 u32 cur_vblank; 745 u32 cur_vblank;
744 746
747 if (WARN_ON(crtc >= dev->num_crtcs))
748 return 0;
749
745 /* Read timestamp from slot of _vblank_time ringbuffer 750 /* Read timestamp from slot of _vblank_time ringbuffer
746 * that corresponds to current vblank count. Retry if 751 * that corresponds to current vblank count. Retry if
747 * count has incremented during readout. This works like 752 * count has incremented during readout. This works like
@@ -917,6 +922,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
917 unsigned long irqflags; 922 unsigned long irqflags;
918 int ret = 0; 923 int ret = 0;
919 924
925 if (WARN_ON(crtc >= dev->num_crtcs))
926 return -EINVAL;
927
920 spin_lock_irqsave(&dev->vbl_lock, irqflags); 928 spin_lock_irqsave(&dev->vbl_lock, irqflags);
921 /* Going from 0->1 means we have to enable interrupts again */ 929 /* Going from 0->1 means we have to enable interrupts again */
922 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { 930 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
@@ -965,6 +973,9 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
965{ 973{
966 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); 974 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
967 975
976 if (WARN_ON(crtc >= dev->num_crtcs))
977 return;
978
968 /* Last user schedules interrupt disable */ 979 /* Last user schedules interrupt disable */
969 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && 980 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
970 (drm_vblank_offdelay > 0)) 981 (drm_vblank_offdelay > 0))
@@ -989,6 +1000,50 @@ void drm_crtc_vblank_put(struct drm_crtc *crtc)
989EXPORT_SYMBOL(drm_crtc_vblank_put); 1000EXPORT_SYMBOL(drm_crtc_vblank_put);
990 1001
991/** 1002/**
1003 * drm_wait_one_vblank - wait for one vblank
1004 * @dev: DRM device
1005 * @crtc: crtc index
1006 *
1007 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1008 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1009 * due to lack of driver support or because the crtc is off.
1010 */
1011void drm_wait_one_vblank(struct drm_device *dev, int crtc)
1012{
1013 int ret;
1014 u32 last;
1015
1016 ret = drm_vblank_get(dev, crtc);
1017 if (WARN_ON(ret))
1018 return;
1019
1020 last = drm_vblank_count(dev, crtc);
1021
1022 ret = wait_event_timeout(dev->vblank[crtc].queue,
1023 last != drm_vblank_count(dev, crtc),
1024 msecs_to_jiffies(100));
1025
1026 WARN_ON(ret == 0);
1027
1028 drm_vblank_put(dev, crtc);
1029}
1030EXPORT_SYMBOL(drm_wait_one_vblank);
1031
1032/**
1033 * drm_crtc_wait_one_vblank - wait for one vblank
1034 * @crtc: DRM crtc
1035 *
1036 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1037 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1038 * due to lack of driver support or because the crtc is off.
1039 */
1040void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
1041{
1042 drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
1043}
1044EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
1045
1046/**
992 * drm_vblank_off - disable vblank events on a CRTC 1047 * drm_vblank_off - disable vblank events on a CRTC
993 * @dev: DRM device 1048 * @dev: DRM device
994 * @crtc: CRTC in question 1049 * @crtc: CRTC in question
@@ -1009,6 +1064,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
1009 unsigned long irqflags; 1064 unsigned long irqflags;
1010 unsigned int seq; 1065 unsigned int seq;
1011 1066
1067 if (WARN_ON(crtc >= dev->num_crtcs))
1068 return;
1069
1012 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1070 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1013 vblank_disable_and_save(dev, crtc); 1071 vblank_disable_and_save(dev, crtc);
1014 wake_up(&dev->vblank[crtc].queue); 1072 wake_up(&dev->vblank[crtc].queue);
@@ -1068,6 +1126,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
1068{ 1126{
1069 unsigned long irqflags; 1127 unsigned long irqflags;
1070 1128
1129 if (WARN_ON(crtc >= dev->num_crtcs))
1130 return;
1131
1071 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1132 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1072 /* re-enable interrupts if there's are users left */ 1133 /* re-enable interrupts if there's are users left */
1073 if (atomic_read(&dev->vblank[crtc].refcount) != 0) 1134 if (atomic_read(&dev->vblank[crtc].refcount) != 0)
@@ -1121,6 +1182,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
1121 /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1182 /* vblank is not initialized (IRQ not installed ?), or has been freed */
1122 if (!dev->num_crtcs) 1183 if (!dev->num_crtcs)
1123 return; 1184 return;
1185
1186 if (WARN_ON(crtc >= dev->num_crtcs))
1187 return;
1188
1124 /* 1189 /*
1125 * To avoid all the problems that might happen if interrupts 1190 * To avoid all the problems that might happen if interrupts
1126 * were enabled/disabled around or between these calls, we just 1191 * were enabled/disabled around or between these calls, we just
@@ -1429,6 +1494,9 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1429 if (!dev->num_crtcs) 1494 if (!dev->num_crtcs)
1430 return false; 1495 return false;
1431 1496
1497 if (WARN_ON(crtc >= dev->num_crtcs))
1498 return false;
1499
1432 /* Need timestamp lock to prevent concurrent execution with 1500 /* Need timestamp lock to prevent concurrent execution with
1433 * vblank enable/disable, as this would cause inconsistent 1501 * vblank enable/disable, as this would cause inconsistent
1434 * or corrupted timestamps and vblank counts. 1502 * or corrupted timestamps and vblank counts.