diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-01-31 05:40:48 -0500 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-02-04 12:04:01 -0500 |
commit | 93533c291a0af78ca57115fc44d2e6c4c9517cd2 (patch) | |
tree | b3b0bf319cc00cee85cc005174b6b83f609bdaf7 /drivers | |
parent | 67026e03244d76b8f1fa725b079d4182fe8910aa (diff) |
drm/i915: Fix leak of relocs along do_execbuffer error path
Following a gpu hang, we would leak the relocation buffer. So simply
earrange the error path to always free the relocation buffer.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1ef7ec4f38fe..be0fd1a63321 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3584,6 +3584,9 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list, | |||
3584 | uint32_t reloc_count = 0, i; | 3584 | uint32_t reloc_count = 0, i; |
3585 | int ret = 0; | 3585 | int ret = 0; |
3586 | 3586 | ||
3587 | if (relocs == NULL) | ||
3588 | return 0; | ||
3589 | |||
3587 | for (i = 0; i < buffer_count; i++) { | 3590 | for (i = 0; i < buffer_count; i++) { |
3588 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 3591 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
3589 | int unwritten; | 3592 | int unwritten; |
@@ -3673,7 +3676,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3673 | struct drm_gem_object *batch_obj; | 3676 | struct drm_gem_object *batch_obj; |
3674 | struct drm_i915_gem_object *obj_priv; | 3677 | struct drm_i915_gem_object *obj_priv; |
3675 | struct drm_clip_rect *cliprects = NULL; | 3678 | struct drm_clip_rect *cliprects = NULL; |
3676 | struct drm_i915_gem_relocation_entry *relocs; | 3679 | struct drm_i915_gem_relocation_entry *relocs = NULL; |
3677 | int ret = 0, ret2, i, pinned = 0; | 3680 | int ret = 0, ret2, i, pinned = 0; |
3678 | uint64_t exec_offset; | 3681 | uint64_t exec_offset; |
3679 | uint32_t seqno, flush_domains, reloc_index; | 3682 | uint32_t seqno, flush_domains, reloc_index; |
@@ -3950,6 +3953,7 @@ err: | |||
3950 | 3953 | ||
3951 | mutex_unlock(&dev->struct_mutex); | 3954 | mutex_unlock(&dev->struct_mutex); |
3952 | 3955 | ||
3956 | pre_mutex_err: | ||
3953 | /* Copy the updated relocations out regardless of current error | 3957 | /* Copy the updated relocations out regardless of current error |
3954 | * state. Failure to update the relocs would mean that the next | 3958 | * state. Failure to update the relocs would mean that the next |
3955 | * time userland calls execbuf, it would do so with presumed offset | 3959 | * time userland calls execbuf, it would do so with presumed offset |
@@ -3964,7 +3968,6 @@ err: | |||
3964 | ret = ret2; | 3968 | ret = ret2; |
3965 | } | 3969 | } |
3966 | 3970 | ||
3967 | pre_mutex_err: | ||
3968 | drm_free_large(object_list); | 3971 | drm_free_large(object_list); |
3969 | kfree(cliprects); | 3972 | kfree(cliprects); |
3970 | 3973 | ||