diff options
author | Eric Anholt <eric@anholt.net> | 2009-03-11 15:30:04 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-03-27 17:47:34 -0400 |
commit | 201361a54ed187d8595a283e3a4ddb213bc8323b (patch) | |
tree | 12a5d23a45f72f8bd917161735d55985654b52e0 /drivers/gpu/drm/i915/i915_gem.c | |
parent | eb01459fbbccb4ca0b879cbfc97e33ac6eabf975 (diff) |
drm/i915: Fix lock order reversal with cliprects and cmdbuf in non-DRI2 paths.
This introduces allocation in the batch submission path that wasn't there
previously, but these are compatibility paths so we care about simplicity
more than performance.
kernel.org bug #12419.
Signed-off-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Keith Packard <keithp@keithp.com>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 010af908bdb6..2bda15197cce 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -2891,11 +2891,10 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
2891 | static int | 2891 | static int |
2892 | i915_dispatch_gem_execbuffer(struct drm_device *dev, | 2892 | i915_dispatch_gem_execbuffer(struct drm_device *dev, |
2893 | struct drm_i915_gem_execbuffer *exec, | 2893 | struct drm_i915_gem_execbuffer *exec, |
2894 | struct drm_clip_rect *cliprects, | ||
2894 | uint64_t exec_offset) | 2895 | uint64_t exec_offset) |
2895 | { | 2896 | { |
2896 | drm_i915_private_t *dev_priv = dev->dev_private; | 2897 | drm_i915_private_t *dev_priv = dev->dev_private; |
2897 | struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *) | ||
2898 | (uintptr_t) exec->cliprects_ptr; | ||
2899 | int nbox = exec->num_cliprects; | 2898 | int nbox = exec->num_cliprects; |
2900 | int i = 0, count; | 2899 | int i = 0, count; |
2901 | uint32_t exec_start, exec_len; | 2900 | uint32_t exec_start, exec_len; |
@@ -2916,7 +2915,7 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev, | |||
2916 | 2915 | ||
2917 | for (i = 0; i < count; i++) { | 2916 | for (i = 0; i < count; i++) { |
2918 | if (i < nbox) { | 2917 | if (i < nbox) { |
2919 | int ret = i915_emit_box(dev, boxes, i, | 2918 | int ret = i915_emit_box(dev, cliprects, i, |
2920 | exec->DR1, exec->DR4); | 2919 | exec->DR1, exec->DR4); |
2921 | if (ret) | 2920 | if (ret) |
2922 | return ret; | 2921 | return ret; |
@@ -2983,6 +2982,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2983 | struct drm_gem_object **object_list = NULL; | 2982 | struct drm_gem_object **object_list = NULL; |
2984 | struct drm_gem_object *batch_obj; | 2983 | struct drm_gem_object *batch_obj; |
2985 | struct drm_i915_gem_object *obj_priv; | 2984 | struct drm_i915_gem_object *obj_priv; |
2985 | struct drm_clip_rect *cliprects = NULL; | ||
2986 | int ret, i, pinned = 0; | 2986 | int ret, i, pinned = 0; |
2987 | uint64_t exec_offset; | 2987 | uint64_t exec_offset; |
2988 | uint32_t seqno, flush_domains; | 2988 | uint32_t seqno, flush_domains; |
@@ -3019,6 +3019,23 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3019 | goto pre_mutex_err; | 3019 | goto pre_mutex_err; |
3020 | } | 3020 | } |
3021 | 3021 | ||
3022 | if (args->num_cliprects != 0) { | ||
3023 | cliprects = drm_calloc(args->num_cliprects, sizeof(*cliprects), | ||
3024 | DRM_MEM_DRIVER); | ||
3025 | if (cliprects == NULL) | ||
3026 | goto pre_mutex_err; | ||
3027 | |||
3028 | ret = copy_from_user(cliprects, | ||
3029 | (struct drm_clip_rect __user *) | ||
3030 | (uintptr_t) args->cliprects_ptr, | ||
3031 | sizeof(*cliprects) * args->num_cliprects); | ||
3032 | if (ret != 0) { | ||
3033 | DRM_ERROR("copy %d cliprects failed: %d\n", | ||
3034 | args->num_cliprects, ret); | ||
3035 | goto pre_mutex_err; | ||
3036 | } | ||
3037 | } | ||
3038 | |||
3022 | mutex_lock(&dev->struct_mutex); | 3039 | mutex_lock(&dev->struct_mutex); |
3023 | 3040 | ||
3024 | i915_verify_inactive(dev, __FILE__, __LINE__); | 3041 | i915_verify_inactive(dev, __FILE__, __LINE__); |
@@ -3155,7 +3172,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3155 | #endif | 3172 | #endif |
3156 | 3173 | ||
3157 | /* Exec the batchbuffer */ | 3174 | /* Exec the batchbuffer */ |
3158 | ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset); | 3175 | ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset); |
3159 | if (ret) { | 3176 | if (ret) { |
3160 | DRM_ERROR("dispatch failed %d\n", ret); | 3177 | DRM_ERROR("dispatch failed %d\n", ret); |
3161 | goto err; | 3178 | goto err; |
@@ -3224,6 +3241,8 @@ pre_mutex_err: | |||
3224 | DRM_MEM_DRIVER); | 3241 | DRM_MEM_DRIVER); |
3225 | drm_free(exec_list, sizeof(*exec_list) * args->buffer_count, | 3242 | drm_free(exec_list, sizeof(*exec_list) * args->buffer_count, |
3226 | DRM_MEM_DRIVER); | 3243 | DRM_MEM_DRIVER); |
3244 | drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects, | ||
3245 | DRM_MEM_DRIVER); | ||
3227 | 3246 | ||
3228 | return ret; | 3247 | return ret; |
3229 | } | 3248 | } |