aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2014-08-06 13:16:59 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-08-06 16:35:37 -0400
commite6ae8687a87b1fe5c25e824c8ad300f5587eb622 (patch)
tree7aa020b26aaeff811c9d76206b13f00582f7a971 /drivers/gpu/drm/drm_irq.c
parentddde43711fdde505ac413102faa2352704cd858a (diff)
drm: idiot-proof vblank
After spending slightly more time than I'd care to admit debugging the various and presumably spectacular way things fail when you pass too low a value to drm_vblank_init() (thanks console-lock for not letting me see the carnage!), I decided it might be a good idea to add some sanity checking. Signed-off-by: Rob Clark <robdclark@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 0de123afdb34..6f16a104d6d0 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -730,6 +730,8 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
730 */ 730 */
731u32 drm_vblank_count(struct drm_device *dev, int crtc) 731u32 drm_vblank_count(struct drm_device *dev, int crtc)
732{ 732{
733 if (WARN_ON(crtc >= dev->num_crtcs))
734 return 0;
733 return atomic_read(&dev->vblank[crtc].count); 735 return atomic_read(&dev->vblank[crtc].count);
734} 736}
735EXPORT_SYMBOL(drm_vblank_count); 737EXPORT_SYMBOL(drm_vblank_count);
@@ -752,6 +754,9 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
752{ 754{
753 u32 cur_vblank; 755 u32 cur_vblank;
754 756
757 if (WARN_ON(crtc >= dev->num_crtcs))
758 return 0;
759
755 /* Read timestamp from slot of _vblank_time ringbuffer 760 /* Read timestamp from slot of _vblank_time ringbuffer
756 * that corresponds to current vblank count. Retry if 761 * that corresponds to current vblank count. Retry if
757 * count has incremented during readout. This works like 762 * count has incremented during readout. This works like
@@ -927,6 +932,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
927 unsigned long irqflags; 932 unsigned long irqflags;
928 int ret = 0; 933 int ret = 0;
929 934
935 if (WARN_ON(crtc >= dev->num_crtcs))
936 return -EINVAL;
937
930 spin_lock_irqsave(&dev->vbl_lock, irqflags); 938 spin_lock_irqsave(&dev->vbl_lock, irqflags);
931 /* Going from 0->1 means we have to enable interrupts again */ 939 /* Going from 0->1 means we have to enable interrupts again */
932 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { 940 if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
@@ -975,6 +983,9 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
975{ 983{
976 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); 984 BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
977 985
986 if (WARN_ON(crtc >= dev->num_crtcs))
987 return;
988
978 /* Last user schedules interrupt disable */ 989 /* Last user schedules interrupt disable */
979 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && 990 if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
980 (drm_vblank_offdelay > 0)) 991 (drm_vblank_offdelay > 0))
@@ -1019,6 +1030,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
1019 unsigned long irqflags; 1030 unsigned long irqflags;
1020 unsigned int seq; 1031 unsigned int seq;
1021 1032
1033 if (WARN_ON(crtc >= dev->num_crtcs))
1034 return;
1035
1022 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1036 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1023 vblank_disable_and_save(dev, crtc); 1037 vblank_disable_and_save(dev, crtc);
1024 wake_up(&dev->vblank[crtc].queue); 1038 wake_up(&dev->vblank[crtc].queue);
@@ -1078,6 +1092,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
1078{ 1092{
1079 unsigned long irqflags; 1093 unsigned long irqflags;
1080 1094
1095 if (WARN_ON(crtc >= dev->num_crtcs))
1096 return;
1097
1081 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1098 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1082 /* re-enable interrupts if there's are users left */ 1099 /* re-enable interrupts if there's are users left */
1083 if (atomic_read(&dev->vblank[crtc].refcount) != 0) 1100 if (atomic_read(&dev->vblank[crtc].refcount) != 0)
@@ -1131,6 +1148,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
1131 /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1148 /* vblank is not initialized (IRQ not installed ?), or has been freed */
1132 if (!dev->num_crtcs) 1149 if (!dev->num_crtcs)
1133 return; 1150 return;
1151
1152 if (WARN_ON(crtc >= dev->num_crtcs))
1153 return;
1154
1134 /* 1155 /*
1135 * To avoid all the problems that might happen if interrupts 1156 * To avoid all the problems that might happen if interrupts
1136 * were enabled/disabled around or between these calls, we just 1157 * were enabled/disabled around or between these calls, we just
@@ -1439,6 +1460,9 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1439 if (!dev->num_crtcs) 1460 if (!dev->num_crtcs)
1440 return false; 1461 return false;
1441 1462
1463 if (WARN_ON(crtc >= dev->num_crtcs))
1464 return false;
1465
1442 /* Need timestamp lock to prevent concurrent execution with 1466 /* Need timestamp lock to prevent concurrent execution with
1443 * vblank enable/disable, as this would cause inconsistent 1467 * vblank enable/disable, as this would cause inconsistent
1444 * or corrupted timestamps and vblank counts. 1468 * or corrupted timestamps and vblank counts.