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 |