diff options
author | Rob Clark <robdclark@gmail.com> | 2014-08-06 13:16:59 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-08-06 16:35:37 -0400 |
commit | e6ae8687a87b1fe5c25e824c8ad300f5587eb622 (patch) | |
tree | 7aa020b26aaeff811c9d76206b13f00582f7a971 /drivers/gpu/drm/drm_irq.c | |
parent | ddde43711fdde505ac413102faa2352704cd858a (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.c | 24 |
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 | */ |
731 | u32 drm_vblank_count(struct drm_device *dev, int crtc) | 731 | u32 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 | } |
735 | EXPORT_SYMBOL(drm_vblank_count); | 737 | EXPORT_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. |