drm: fix quiescent locking

A fix for a locking bug which is triggered when a client tries to lock with
flag DMA_QUIESCENT (typically the X server), but gets interrupted by a signal.
The locking IOCTL should then return an error, but if DMA_QUIESCENT succeeds
it returns 0, and the client falsely thinks it has the lock. In addition
The client waits for DMA_QUISCENT and possibly DMA_READY without having the lock.

From: Thomas Hellstrom
Signed-off-by: Dave Airlie <airlied@linux.ie>

authored by Dave Airlie and committed by Dave Airlie cf65f162 33bc227e

+11 -5
+11 -5
drivers/char/drm/drm_lock.c
··· 104 104 __set_current_state(TASK_RUNNING); 105 105 remove_wait_queue(&dev->lock.lock_queue, &entry); 106 106 107 + DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); 108 + if (ret) 109 + return ret; 110 + 107 111 sigemptyset(&dev->sigmask); 108 112 sigaddset(&dev->sigmask, SIGSTOP); 109 113 sigaddset(&dev->sigmask, SIGTSTP); ··· 120 116 if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY)) 121 117 dev->driver->dma_ready(dev); 122 118 123 - if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) 124 - return dev->driver->dma_quiescent(dev); 119 + if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) { 120 + if (dev->driver->dma_quiescent(dev)) { 121 + DRM_DEBUG("%d waiting for DMA quiescent\n", lock.context); 122 + return DRM_ERR(EBUSY); 123 + } 124 + } 125 125 126 126 /* dev->driver->kernel_context_switch isn't used by any of the x86 127 127 * drivers but is used by the Sparc driver. ··· 136 128 dev->driver->kernel_context_switch(dev, dev->last_context, 137 129 lock.context); 138 130 } 139 - DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); 140 - 141 - return ret; 131 + return 0; 142 132 } 143 133 144 134 /**