提交 d7d8aac7 编写于 作者: T Thomas Hellstrom 提交者: Dave Airlie

drm: fix up mmap locking in preparation for ttm changes

This change is needed to protect againt disappearing maps which aren't common.
The map lists are protected using sturct_mutex but drm_mmap never locked it.
Signed-off-by: NDave Airlie <airlied@linux.ie>
上级 040ac320
...@@ -413,7 +413,7 @@ static struct vm_operations_struct drm_vm_sg_ops = { ...@@ -413,7 +413,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
* Create a new drm_vma_entry structure as the \p vma private data entry and * Create a new drm_vma_entry structure as the \p vma private data entry and
* add it to drm_device::vmalist. * add it to drm_device::vmalist.
*/ */
static void drm_vm_open(struct vm_area_struct *vma) static void drm_vm_open_locked(struct vm_area_struct *vma)
{ {
drm_file_t *priv = vma->vm_file->private_data; drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev; drm_device_t *dev = priv->head->dev;
...@@ -425,15 +425,23 @@ static void drm_vm_open(struct vm_area_struct *vma) ...@@ -425,15 +425,23 @@ static void drm_vm_open(struct vm_area_struct *vma)
vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
if (vma_entry) { if (vma_entry) {
mutex_lock(&dev->struct_mutex);
vma_entry->vma = vma; vma_entry->vma = vma;
vma_entry->next = dev->vmalist; vma_entry->next = dev->vmalist;
vma_entry->pid = current->pid; vma_entry->pid = current->pid;
dev->vmalist = vma_entry; dev->vmalist = vma_entry;
mutex_unlock(&dev->struct_mutex);
} }
} }
static void drm_vm_open(struct vm_area_struct *vma)
{
drm_file_t *priv = vma->vm_file->private_data;
drm_device_t *dev = priv->head->dev;
mutex_lock(&dev->struct_mutex);
drm_vm_open_locked(vma);
mutex_unlock(&dev->struct_mutex);
}
/** /**
* \c close method for all virtual memory types. * \c close method for all virtual memory types.
* *
...@@ -484,7 +492,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) ...@@ -484,7 +492,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
drm_device_dma_t *dma; drm_device_dma_t *dma;
unsigned long length = vma->vm_end - vma->vm_start; unsigned long length = vma->vm_end - vma->vm_start;
lock_kernel();
dev = priv->head->dev; dev = priv->head->dev;
dma = dev->dma; dma = dev->dma;
DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n",
...@@ -492,10 +499,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) ...@@ -492,10 +499,8 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
/* Length must match exact page count */ /* Length must match exact page count */
if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
unlock_kernel();
return -EINVAL; return -EINVAL;
} }
unlock_kernel();
if (!capable(CAP_SYS_ADMIN) && if (!capable(CAP_SYS_ADMIN) &&
(dma->flags & _DRM_DMA_USE_PCI_RO)) { (dma->flags & _DRM_DMA_USE_PCI_RO)) {
...@@ -518,7 +523,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) ...@@ -518,7 +523,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
vma->vm_flags |= VM_RESERVED; /* Don't swap */ vma->vm_flags |= VM_RESERVED; /* Don't swap */
vma->vm_file = filp; /* Needed for drm_vm_open() */ vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma); drm_vm_open_locked(vma);
return 0; return 0;
} }
...@@ -553,7 +558,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); ...@@ -553,7 +558,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
* according to the mapping type and remaps the pages. Finally sets the file * according to the mapping type and remaps the pages. Finally sets the file
* pointer and calls vm_open(). * pointer and calls vm_open().
*/ */
int drm_mmap(struct file *filp, struct vm_area_struct *vma) static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
{ {
drm_file_t *priv = filp->private_data; drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev; drm_device_t *dev = priv->head->dev;
...@@ -667,8 +672,20 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma) ...@@ -667,8 +672,20 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_flags |= VM_RESERVED; /* Don't swap */ vma->vm_flags |= VM_RESERVED; /* Don't swap */
vma->vm_file = filp; /* Needed for drm_vm_open() */ vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open(vma); drm_vm_open_locked(vma);
return 0; return 0;
} }
int drm_mmap(struct file *filp, struct vm_area_struct *vma)
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->head->dev;
int ret;
mutex_lock(&dev->struct_mutex);
ret = drm_mmap_locked(filp, vma);
mutex_unlock(&dev->struct_mutex);
return ret;
}
EXPORT_SYMBOL(drm_mmap); EXPORT_SYMBOL(drm_mmap);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册