aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2007-03-24 02:52:49 -0400
committerDave Airlie <airlied@linux.ie>2007-03-24 03:00:22 -0400
commitd7d8aac79dc38cbdef83b774e49bafdae9918137 (patch)
tree45eb61fb816117ac0913fbe63d2e430bbfaa65a2
parent040ac32048d5efabd557c1e0a6ab8aec2c710c56 (diff)
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: Dave Airlie <airlied@linux.ie>
-rw-r--r--drivers/char/drm/drm_vm.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index 239ac33a6e10..f7d4e29d5073 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -413,7 +413,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
413 * Create a new drm_vma_entry structure as the \p vma private data entry and 413 * Create a new drm_vma_entry structure as the \p vma private data entry and
414 * add it to drm_device::vmalist. 414 * add it to drm_device::vmalist.
415 */ 415 */
416static void drm_vm_open(struct vm_area_struct *vma) 416static void drm_vm_open_locked(struct vm_area_struct *vma)
417{ 417{
418 drm_file_t *priv = vma->vm_file->private_data; 418 drm_file_t *priv = vma->vm_file->private_data;
419 drm_device_t *dev = priv->head->dev; 419 drm_device_t *dev = priv->head->dev;
@@ -425,15 +425,23 @@ static void drm_vm_open(struct vm_area_struct *vma)
425 425
426 vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS); 426 vma_entry = drm_alloc(sizeof(*vma_entry), DRM_MEM_VMAS);
427 if (vma_entry) { 427 if (vma_entry) {
428 mutex_lock(&dev->struct_mutex);
429 vma_entry->vma = vma; 428 vma_entry->vma = vma;
430 vma_entry->next = dev->vmalist; 429 vma_entry->next = dev->vmalist;
431 vma_entry->pid = current->pid; 430 vma_entry->pid = current->pid;
432 dev->vmalist = vma_entry; 431 dev->vmalist = vma_entry;
433 mutex_unlock(&dev->struct_mutex);
434 } 432 }
435} 433}
436 434
435static void drm_vm_open(struct vm_area_struct *vma)
436{
437 drm_file_t *priv = vma->vm_file->private_data;
438 drm_device_t *dev = priv->head->dev;
439
440 mutex_lock(&dev->struct_mutex);
441 drm_vm_open_locked(vma);
442 mutex_unlock(&dev->struct_mutex);
443}
444
437/** 445/**
438 * \c close method for all virtual memory types. 446 * \c close method for all virtual memory types.
439 * 447 *
@@ -484,7 +492,6 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
484 drm_device_dma_t *dma; 492 drm_device_dma_t *dma;
485 unsigned long length = vma->vm_end - vma->vm_start; 493 unsigned long length = vma->vm_end - vma->vm_start;
486 494
487 lock_kernel();
488 dev = priv->head->dev; 495 dev = priv->head->dev;
489 dma = dev->dma; 496 dma = dev->dma;
490 DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", 497 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 499
493 /* Length must match exact page count */ 500 /* Length must match exact page count */
494 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { 501 if (!dma || (length >> PAGE_SHIFT) != dma->page_count) {
495 unlock_kernel();
496 return -EINVAL; 502 return -EINVAL;
497 } 503 }
498 unlock_kernel();
499 504
500 if (!capable(CAP_SYS_ADMIN) && 505 if (!capable(CAP_SYS_ADMIN) &&
501 (dma->flags & _DRM_DMA_USE_PCI_RO)) { 506 (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 vma->vm_flags |= VM_RESERVED; /* Don't swap */ 523 vma->vm_flags |= VM_RESERVED; /* Don't swap */
519 524
520 vma->vm_file = filp; /* Needed for drm_vm_open() */ 525 vma->vm_file = filp; /* Needed for drm_vm_open() */
521 drm_vm_open(vma); 526 drm_vm_open_locked(vma);
522 return 0; 527 return 0;
523} 528}
524 529
@@ -553,7 +558,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs);
553 * according to the mapping type and remaps the pages. Finally sets the file 558 * according to the mapping type and remaps the pages. Finally sets the file
554 * pointer and calls vm_open(). 559 * pointer and calls vm_open().
555 */ 560 */
556int drm_mmap(struct file *filp, struct vm_area_struct *vma) 561static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
557{ 562{
558 drm_file_t *priv = filp->private_data; 563 drm_file_t *priv = filp->private_data;
559 drm_device_t *dev = priv->head->dev; 564 drm_device_t *dev = priv->head->dev;
@@ -667,8 +672,20 @@ int drm_mmap(struct file *filp, struct vm_area_struct *vma)
667 vma->vm_flags |= VM_RESERVED; /* Don't swap */ 672 vma->vm_flags |= VM_RESERVED; /* Don't swap */
668 673
669 vma->vm_file = filp; /* Needed for drm_vm_open() */ 674 vma->vm_file = filp; /* Needed for drm_vm_open() */
670 drm_vm_open(vma); 675 drm_vm_open_locked(vma);
671 return 0; 676 return 0;
672} 677}
673 678
679int drm_mmap(struct file *filp, struct vm_area_struct *vma)
680{
681 drm_file_t *priv = filp->private_data;
682 drm_device_t *dev = priv->head->dev;
683 int ret;
684
685 mutex_lock(&dev->struct_mutex);
686 ret = drm_mmap_locked(filp, vma);
687 mutex_unlock(&dev->struct_mutex);
688
689 return ret;
690}
674EXPORT_SYMBOL(drm_mmap); 691EXPORT_SYMBOL(drm_mmap);