diff options
author | Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | 2007-03-24 02:52:49 -0400 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-03-24 03:00:22 -0400 |
commit | d7d8aac79dc38cbdef83b774e49bafdae9918137 (patch) | |
tree | 45eb61fb816117ac0913fbe63d2e430bbfaa65a2 /drivers/char | |
parent | 040ac32048d5efabd557c1e0a6ab8aec2c710c56 (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>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/drm/drm_vm.c | 35 |
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 | */ |
416 | static void drm_vm_open(struct vm_area_struct *vma) | 416 | static 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 | ||
435 | static 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 | */ |
556 | int drm_mmap(struct file *filp, struct vm_area_struct *vma) | 561 | static 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 | ||
679 | int 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 | } | ||
674 | EXPORT_SYMBOL(drm_mmap); | 691 | EXPORT_SYMBOL(drm_mmap); |