diff options
| -rw-r--r-- | drivers/gpu/drm/drm_gem.c | 28 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 43 | ||||
| -rw-r--r-- | include/drm/drmP.h | 2 |
4 files changed, 57 insertions, 18 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 5dad6b9d0dec..88d3368ffddd 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
| @@ -463,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref) | |||
| 463 | } | 463 | } |
| 464 | EXPORT_SYMBOL(drm_gem_object_handle_free); | 464 | EXPORT_SYMBOL(drm_gem_object_handle_free); |
| 465 | 465 | ||
| 466 | void drm_gem_vm_open(struct vm_area_struct *vma) | ||
| 467 | { | ||
| 468 | struct drm_gem_object *obj = vma->vm_private_data; | ||
| 469 | |||
| 470 | drm_gem_object_reference(obj); | ||
| 471 | } | ||
| 472 | EXPORT_SYMBOL(drm_gem_vm_open); | ||
| 473 | |||
| 474 | void drm_gem_vm_close(struct vm_area_struct *vma) | ||
| 475 | { | ||
| 476 | struct drm_gem_object *obj = vma->vm_private_data; | ||
| 477 | struct drm_device *dev = obj->dev; | ||
| 478 | |||
| 479 | mutex_lock(&dev->struct_mutex); | ||
| 480 | drm_gem_object_unreference(obj); | ||
| 481 | mutex_unlock(&dev->struct_mutex); | ||
| 482 | } | ||
| 483 | EXPORT_SYMBOL(drm_gem_vm_close); | ||
| 484 | |||
| 485 | |||
| 466 | /** | 486 | /** |
| 467 | * drm_gem_mmap - memory map routine for GEM objects | 487 | * drm_gem_mmap - memory map routine for GEM objects |
| 468 | * @filp: DRM file pointer | 488 | * @filp: DRM file pointer |
| @@ -524,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 524 | #endif | 544 | #endif |
| 525 | vma->vm_page_prot = __pgprot(prot); | 545 | vma->vm_page_prot = __pgprot(prot); |
| 526 | 546 | ||
| 547 | /* Take a ref for this mapping of the object, so that the fault | ||
| 548 | * handler can dereference the mmap offset's pointer to the object. | ||
| 549 | * This reference is cleaned up by the corresponding vm_close | ||
| 550 | * (which should happen whether the vma was created by this call, or | ||
| 551 | * by a vm_open due to mremap or partial unmap or whatever). | ||
| 552 | */ | ||
| 553 | drm_gem_object_reference(obj); | ||
| 554 | |||
| 527 | vma->vm_file = filp; /* Needed for drm_vm_open() */ | 555 | vma->vm_file = filp; /* Needed for drm_vm_open() */ |
| 528 | drm_vm_open_locked(vma); | 556 | drm_vm_open_locked(vma); |
| 529 | 557 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index aac12ee31a46..a31cbdbc3c54 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -94,6 +94,8 @@ static int i915_resume(struct drm_device *dev) | |||
| 94 | 94 | ||
| 95 | static struct vm_operations_struct i915_gem_vm_ops = { | 95 | static struct vm_operations_struct i915_gem_vm_ops = { |
| 96 | .fault = i915_gem_fault, | 96 | .fault = i915_gem_fault, |
| 97 | .open = drm_gem_vm_open, | ||
| 98 | .close = drm_gem_vm_close, | ||
| 97 | }; | 99 | }; |
| 98 | 100 | ||
| 99 | static struct drm_driver driver = { | 101 | static struct drm_driver driver = { |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 078858178832..ac534c9a2f81 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -607,8 +607,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 607 | case -EAGAIN: | 607 | case -EAGAIN: |
| 608 | return VM_FAULT_OOM; | 608 | return VM_FAULT_OOM; |
| 609 | case -EFAULT: | 609 | case -EFAULT: |
| 610 | case -EBUSY: | ||
| 611 | DRM_ERROR("can't insert pfn?? fault or busy...\n"); | ||
| 612 | return VM_FAULT_SIGBUS; | 610 | return VM_FAULT_SIGBUS; |
| 613 | default: | 611 | default: |
| 614 | return VM_FAULT_NOPAGE; | 612 | return VM_FAULT_NOPAGE; |
| @@ -684,6 +682,30 @@ out_free_list: | |||
| 684 | return ret; | 682 | return ret; |
| 685 | } | 683 | } |
| 686 | 684 | ||
| 685 | static void | ||
| 686 | i915_gem_free_mmap_offset(struct drm_gem_object *obj) | ||
| 687 | { | ||
| 688 | struct drm_device *dev = obj->dev; | ||
| 689 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
| 690 | struct drm_gem_mm *mm = dev->mm_private; | ||
| 691 | struct drm_map_list *list; | ||
| 692 | |||
| 693 | list = &obj->map_list; | ||
| 694 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
| 695 | |||
| 696 | if (list->file_offset_node) { | ||
| 697 | drm_mm_put_block(list->file_offset_node); | ||
| 698 | list->file_offset_node = NULL; | ||
| 699 | } | ||
| 700 | |||
| 701 | if (list->map) { | ||
| 702 | drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER); | ||
| 703 | list->map = NULL; | ||
| 704 | } | ||
| 705 | |||
| 706 | obj_priv->mmap_offset = 0; | ||
| 707 | } | ||
| 708 | |||
| 687 | /** | 709 | /** |
| 688 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object | 710 | * i915_gem_get_gtt_alignment - return required GTT alignment for an object |
| 689 | * @obj: object to check | 711 | * @obj: object to check |
| @@ -2896,9 +2918,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) | |||
| 2896 | void i915_gem_free_object(struct drm_gem_object *obj) | 2918 | void i915_gem_free_object(struct drm_gem_object *obj) |
| 2897 | { | 2919 | { |
| 2898 | struct drm_device *dev = obj->dev; | 2920 | struct drm_device *dev = obj->dev; |
| 2899 | struct drm_gem_mm *mm = dev->mm_private; | ||
| 2900 | struct drm_map_list *list; | ||
| 2901 | struct drm_map *map; | ||
| 2902 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 2921 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 2903 | 2922 | ||
| 2904 | while (obj_priv->pin_count > 0) | 2923 | while (obj_priv->pin_count > 0) |
| @@ -2909,19 +2928,7 @@ void i915_gem_free_object(struct drm_gem_object *obj) | |||
| 2909 | 2928 | ||
| 2910 | i915_gem_object_unbind(obj); | 2929 | i915_gem_object_unbind(obj); |
| 2911 | 2930 | ||
| 2912 | list = &obj->map_list; | 2931 | i915_gem_free_mmap_offset(obj); |
| 2913 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
| 2914 | |||
| 2915 | if (list->file_offset_node) { | ||
| 2916 | drm_mm_put_block(list->file_offset_node); | ||
| 2917 | list->file_offset_node = NULL; | ||
| 2918 | } | ||
| 2919 | |||
| 2920 | map = list->map; | ||
| 2921 | if (map) { | ||
| 2922 | drm_free(map, sizeof(*map), DRM_MEM_DRIVER); | ||
| 2923 | list->map = NULL; | ||
| 2924 | } | ||
| 2925 | 2932 | ||
| 2926 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); | 2933 | drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); |
| 2927 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); | 2934 | drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 8190b9bcc2d9..e5f4ae989abf 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
| @@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref); | |||
| 1321 | struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, | 1321 | struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev, |
| 1322 | size_t size); | 1322 | size_t size); |
| 1323 | void drm_gem_object_handle_free(struct kref *kref); | 1323 | void drm_gem_object_handle_free(struct kref *kref); |
| 1324 | void drm_gem_vm_open(struct vm_area_struct *vma); | ||
| 1325 | void drm_gem_vm_close(struct vm_area_struct *vma); | ||
| 1324 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); | 1326 | int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); |
| 1325 | 1327 | ||
| 1326 | static inline void | 1328 | static inline void |
