diff options
| -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); |
