drm/i915: Keep refs on the object over the lifetime of vmas for GTT mmap.
This fixes potential fault at fault time if the object was unreferenced while the mapping still existed. Now, while the mmap_offset only lives for the lifetime of the object, the object also stays alive while a vma exists that needs it. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
committed by
Dave Airlie
parent
496818f08a
commit
ab00b3e521
@@ -607,8 +607,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
case -EAGAIN:
|
||||
return VM_FAULT_OOM;
|
||||
case -EFAULT:
|
||||
case -EBUSY:
|
||||
DRM_ERROR("can't insert pfn?? fault or busy...\n");
|
||||
return VM_FAULT_SIGBUS;
|
||||
default:
|
||||
return VM_FAULT_NOPAGE;
|
||||
@@ -684,6 +682,30 @@ out_free_list:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
i915_gem_free_mmap_offset(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
struct drm_gem_mm *mm = dev->mm_private;
|
||||
struct drm_map_list *list;
|
||||
|
||||
list = &obj->map_list;
|
||||
drm_ht_remove_item(&mm->offset_hash, &list->hash);
|
||||
|
||||
if (list->file_offset_node) {
|
||||
drm_mm_put_block(list->file_offset_node);
|
||||
list->file_offset_node = NULL;
|
||||
}
|
||||
|
||||
if (list->map) {
|
||||
drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
|
||||
list->map = NULL;
|
||||
}
|
||||
|
||||
obj_priv->mmap_offset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_get_gtt_alignment - return required GTT alignment for an object
|
||||
* @obj: object to check
|
||||
@@ -2896,9 +2918,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
|
||||
void i915_gem_free_object(struct drm_gem_object *obj)
|
||||
{
|
||||
struct drm_device *dev = obj->dev;
|
||||
struct drm_gem_mm *mm = dev->mm_private;
|
||||
struct drm_map_list *list;
|
||||
struct drm_map *map;
|
||||
struct drm_i915_gem_object *obj_priv = obj->driver_private;
|
||||
|
||||
while (obj_priv->pin_count > 0)
|
||||
@@ -2909,19 +2928,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
|
||||
|
||||
i915_gem_object_unbind(obj);
|
||||
|
||||
list = &obj->map_list;
|
||||
drm_ht_remove_item(&mm->offset_hash, &list->hash);
|
||||
|
||||
if (list->file_offset_node) {
|
||||
drm_mm_put_block(list->file_offset_node);
|
||||
list->file_offset_node = NULL;
|
||||
}
|
||||
|
||||
map = list->map;
|
||||
if (map) {
|
||||
drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
|
||||
list->map = NULL;
|
||||
}
|
||||
i915_gem_free_mmap_offset(obj);
|
||||
|
||||
drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
|
||||
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
|
||||
|
Reference in New Issue
Block a user