提交 cf65f162 编写于 作者: D Dave Airlie 提交者: Dave Airlie

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: NDave Airlie <airlied@linux.ie>
上级 33bc227e
...@@ -104,6 +104,10 @@ int drm_lock(struct inode *inode, struct file *filp, ...@@ -104,6 +104,10 @@ int drm_lock(struct inode *inode, struct file *filp,
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
remove_wait_queue(&dev->lock.lock_queue, &entry); remove_wait_queue(&dev->lock.lock_queue, &entry);
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock");
if (ret)
return ret;
sigemptyset(&dev->sigmask); sigemptyset(&dev->sigmask);
sigaddset(&dev->sigmask, SIGSTOP); sigaddset(&dev->sigmask, SIGSTOP);
sigaddset(&dev->sigmask, SIGTSTP); sigaddset(&dev->sigmask, SIGTSTP);
...@@ -116,8 +120,12 @@ int drm_lock(struct inode *inode, struct file *filp, ...@@ -116,8 +120,12 @@ int drm_lock(struct inode *inode, struct file *filp,
if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY)) if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY))
dev->driver->dma_ready(dev); dev->driver->dma_ready(dev);
if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) {
return dev->driver->dma_quiescent(dev); if (dev->driver->dma_quiescent(dev)) {
DRM_DEBUG("%d waiting for DMA quiescent\n", lock.context);
return DRM_ERR(EBUSY);
}
}
/* dev->driver->kernel_context_switch isn't used by any of the x86 /* dev->driver->kernel_context_switch isn't used by any of the x86
* drivers but is used by the Sparc driver. * drivers but is used by the Sparc driver.
...@@ -128,9 +136,7 @@ int drm_lock(struct inode *inode, struct file *filp, ...@@ -128,9 +136,7 @@ int drm_lock(struct inode *inode, struct file *filp,
dev->driver->kernel_context_switch(dev, dev->last_context, dev->driver->kernel_context_switch(dev, dev->last_context,
lock.context); lock.context);
} }
DRM_DEBUG("%d %s\n", lock.context, ret ? "interrupted" : "has lock"); return 0;
return ret;
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册