diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 239 |
1 files changed, 186 insertions, 53 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9e81a0ddafa..0330c3aa803 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -3199,7 +3199,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
3199 | static int | 3199 | static int |
3200 | i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | 3200 | i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, |
3201 | struct drm_file *file_priv, | 3201 | struct drm_file *file_priv, |
3202 | struct drm_i915_gem_exec_object *entry, | 3202 | struct drm_i915_gem_exec_object2 *entry, |
3203 | struct drm_i915_gem_relocation_entry *relocs) | 3203 | struct drm_i915_gem_relocation_entry *relocs) |
3204 | { | 3204 | { |
3205 | struct drm_device *dev = obj->dev; | 3205 | struct drm_device *dev = obj->dev; |
@@ -3207,12 +3207,35 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3207 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 3207 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
3208 | int i, ret; | 3208 | int i, ret; |
3209 | void __iomem *reloc_page; | 3209 | void __iomem *reloc_page; |
3210 | bool need_fence; | ||
3211 | |||
3212 | need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
3213 | obj_priv->tiling_mode != I915_TILING_NONE; | ||
3214 | |||
3215 | /* Check fence reg constraints and rebind if necessary */ | ||
3216 | if (need_fence && !i915_obj_fenceable(dev, obj)) | ||
3217 | i915_gem_object_unbind(obj); | ||
3210 | 3218 | ||
3211 | /* Choose the GTT offset for our buffer and put it there. */ | 3219 | /* Choose the GTT offset for our buffer and put it there. */ |
3212 | ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); | 3220 | ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); |
3213 | if (ret) | 3221 | if (ret) |
3214 | return ret; | 3222 | return ret; |
3215 | 3223 | ||
3224 | /* | ||
3225 | * Pre-965 chips need a fence register set up in order to | ||
3226 | * properly handle blits to/from tiled surfaces. | ||
3227 | */ | ||
3228 | if (need_fence) { | ||
3229 | ret = i915_gem_object_get_fence_reg(obj); | ||
3230 | if (ret != 0) { | ||
3231 | if (ret != -EBUSY && ret != -ERESTARTSYS) | ||
3232 | DRM_ERROR("Failure to install fence: %d\n", | ||
3233 | ret); | ||
3234 | i915_gem_object_unpin(obj); | ||
3235 | return ret; | ||
3236 | } | ||
3237 | } | ||
3238 | |||
3216 | entry->offset = obj_priv->gtt_offset; | 3239 | entry->offset = obj_priv->gtt_offset; |
3217 | 3240 | ||
3218 | /* Apply the relocations, using the GTT aperture to avoid cache | 3241 | /* Apply the relocations, using the GTT aperture to avoid cache |
@@ -3374,7 +3397,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3374 | */ | 3397 | */ |
3375 | static int | 3398 | static int |
3376 | i915_dispatch_gem_execbuffer(struct drm_device *dev, | 3399 | i915_dispatch_gem_execbuffer(struct drm_device *dev, |
3377 | struct drm_i915_gem_execbuffer *exec, | 3400 | struct drm_i915_gem_execbuffer2 *exec, |
3378 | struct drm_clip_rect *cliprects, | 3401 | struct drm_clip_rect *cliprects, |
3379 | uint64_t exec_offset) | 3402 | uint64_t exec_offset) |
3380 | { | 3403 | { |
@@ -3464,7 +3487,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) | |||
3464 | } | 3487 | } |
3465 | 3488 | ||
3466 | static int | 3489 | static int |
3467 | i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, | 3490 | i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list, |
3468 | uint32_t buffer_count, | 3491 | uint32_t buffer_count, |
3469 | struct drm_i915_gem_relocation_entry **relocs) | 3492 | struct drm_i915_gem_relocation_entry **relocs) |
3470 | { | 3493 | { |
@@ -3479,8 +3502,10 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, | |||
3479 | } | 3502 | } |
3480 | 3503 | ||
3481 | *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); | 3504 | *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); |
3482 | if (*relocs == NULL) | 3505 | if (*relocs == NULL) { |
3506 | DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count); | ||
3483 | return -ENOMEM; | 3507 | return -ENOMEM; |
3508 | } | ||
3484 | 3509 | ||
3485 | for (i = 0; i < buffer_count; i++) { | 3510 | for (i = 0; i < buffer_count; i++) { |
3486 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 3511 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
@@ -3504,7 +3529,7 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, | |||
3504 | } | 3529 | } |
3505 | 3530 | ||
3506 | static int | 3531 | static int |
3507 | i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list, | 3532 | i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list, |
3508 | uint32_t buffer_count, | 3533 | uint32_t buffer_count, |
3509 | struct drm_i915_gem_relocation_entry *relocs) | 3534 | struct drm_i915_gem_relocation_entry *relocs) |
3510 | { | 3535 | { |
@@ -3537,7 +3562,7 @@ err: | |||
3537 | } | 3562 | } |
3538 | 3563 | ||
3539 | static int | 3564 | static int |
3540 | i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer *exec, | 3565 | i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, |
3541 | uint64_t exec_offset) | 3566 | uint64_t exec_offset) |
3542 | { | 3567 | { |
3543 | uint32_t exec_start, exec_len; | 3568 | uint32_t exec_start, exec_len; |
@@ -3590,18 +3615,18 @@ i915_gem_wait_for_pending_flip(struct drm_device *dev, | |||
3590 | } | 3615 | } |
3591 | 3616 | ||
3592 | int | 3617 | int |
3593 | i915_gem_execbuffer(struct drm_device *dev, void *data, | 3618 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, |
3594 | struct drm_file *file_priv) | 3619 | struct drm_file *file_priv, |
3620 | struct drm_i915_gem_execbuffer2 *args, | ||
3621 | struct drm_i915_gem_exec_object2 *exec_list) | ||
3595 | { | 3622 | { |
3596 | drm_i915_private_t *dev_priv = dev->dev_private; | 3623 | drm_i915_private_t *dev_priv = dev->dev_private; |
3597 | struct drm_i915_gem_execbuffer *args = data; | ||
3598 | struct drm_i915_gem_exec_object *exec_list = NULL; | ||
3599 | struct drm_gem_object **object_list = NULL; | 3624 | struct drm_gem_object **object_list = NULL; |
3600 | struct drm_gem_object *batch_obj; | 3625 | struct drm_gem_object *batch_obj; |
3601 | struct drm_i915_gem_object *obj_priv; | 3626 | struct drm_i915_gem_object *obj_priv; |
3602 | struct drm_clip_rect *cliprects = NULL; | 3627 | struct drm_clip_rect *cliprects = NULL; |
3603 | struct drm_i915_gem_relocation_entry *relocs; | 3628 | struct drm_i915_gem_relocation_entry *relocs; |
3604 | int ret, ret2, i, pinned = 0; | 3629 | int ret = 0, ret2, i, pinned = 0; |
3605 | uint64_t exec_offset; | 3630 | uint64_t exec_offset; |
3606 | uint32_t seqno, flush_domains, reloc_index; | 3631 | uint32_t seqno, flush_domains, reloc_index; |
3607 | int pin_tries, flips; | 3632 | int pin_tries, flips; |
@@ -3615,25 +3640,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3615 | DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); | 3640 | DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); |
3616 | return -EINVAL; | 3641 | return -EINVAL; |
3617 | } | 3642 | } |
3618 | /* Copy in the exec list from userland */ | ||
3619 | exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); | ||
3620 | object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); | 3643 | object_list = drm_malloc_ab(sizeof(*object_list), args->buffer_count); |
3621 | if (exec_list == NULL || object_list == NULL) { | 3644 | if (object_list == NULL) { |
3622 | DRM_ERROR("Failed to allocate exec or object list " | 3645 | DRM_ERROR("Failed to allocate object list for %d buffers\n", |
3623 | "for %d buffers\n", | ||
3624 | args->buffer_count); | 3646 | args->buffer_count); |
3625 | ret = -ENOMEM; | 3647 | ret = -ENOMEM; |
3626 | goto pre_mutex_err; | 3648 | goto pre_mutex_err; |
3627 | } | 3649 | } |
3628 | ret = copy_from_user(exec_list, | ||
3629 | (struct drm_i915_relocation_entry __user *) | ||
3630 | (uintptr_t) args->buffers_ptr, | ||
3631 | sizeof(*exec_list) * args->buffer_count); | ||
3632 | if (ret != 0) { | ||
3633 | DRM_ERROR("copy %d exec entries failed %d\n", | ||
3634 | args->buffer_count, ret); | ||
3635 | goto pre_mutex_err; | ||
3636 | } | ||
3637 | 3650 | ||
3638 | if (args->num_cliprects != 0) { | 3651 | if (args->num_cliprects != 0) { |
3639 | cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects), | 3652 | cliprects = kcalloc(args->num_cliprects, sizeof(*cliprects), |
@@ -3885,20 +3898,6 @@ err: | |||
3885 | 3898 | ||
3886 | mutex_unlock(&dev->struct_mutex); | 3899 | mutex_unlock(&dev->struct_mutex); |
3887 | 3900 | ||
3888 | if (!ret) { | ||
3889 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
3890 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
3891 | (uintptr_t) args->buffers_ptr, | ||
3892 | exec_list, | ||
3893 | sizeof(*exec_list) * args->buffer_count); | ||
3894 | if (ret) { | ||
3895 | ret = -EFAULT; | ||
3896 | DRM_ERROR("failed to copy %d exec entries " | ||
3897 | "back to user (%d)\n", | ||
3898 | args->buffer_count, ret); | ||
3899 | } | ||
3900 | } | ||
3901 | |||
3902 | /* Copy the updated relocations out regardless of current error | 3901 | /* Copy the updated relocations out regardless of current error |
3903 | * state. Failure to update the relocs would mean that the next | 3902 | * state. Failure to update the relocs would mean that the next |
3904 | * time userland calls execbuf, it would do so with presumed offset | 3903 | * time userland calls execbuf, it would do so with presumed offset |
@@ -3915,12 +3914,158 @@ err: | |||
3915 | 3914 | ||
3916 | pre_mutex_err: | 3915 | pre_mutex_err: |
3917 | drm_free_large(object_list); | 3916 | drm_free_large(object_list); |
3918 | drm_free_large(exec_list); | ||
3919 | kfree(cliprects); | 3917 | kfree(cliprects); |
3920 | 3918 | ||
3921 | return ret; | 3919 | return ret; |
3922 | } | 3920 | } |
3923 | 3921 | ||
3922 | /* | ||
3923 | * Legacy execbuffer just creates an exec2 list from the original exec object | ||
3924 | * list array and passes it to the real function. | ||
3925 | */ | ||
3926 | int | ||
3927 | i915_gem_execbuffer(struct drm_device *dev, void *data, | ||
3928 | struct drm_file *file_priv) | ||
3929 | { | ||
3930 | struct drm_i915_gem_execbuffer *args = data; | ||
3931 | struct drm_i915_gem_execbuffer2 exec2; | ||
3932 | struct drm_i915_gem_exec_object *exec_list = NULL; | ||
3933 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; | ||
3934 | int ret, i; | ||
3935 | |||
3936 | #if WATCH_EXEC | ||
3937 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | ||
3938 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | ||
3939 | #endif | ||
3940 | |||
3941 | if (args->buffer_count < 1) { | ||
3942 | DRM_ERROR("execbuf with %d buffers\n", args->buffer_count); | ||
3943 | return -EINVAL; | ||
3944 | } | ||
3945 | |||
3946 | /* Copy in the exec list from userland */ | ||
3947 | exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); | ||
3948 | exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); | ||
3949 | if (exec_list == NULL || exec2_list == NULL) { | ||
3950 | DRM_ERROR("Failed to allocate exec list for %d buffers\n", | ||
3951 | args->buffer_count); | ||
3952 | drm_free_large(exec_list); | ||
3953 | drm_free_large(exec2_list); | ||
3954 | return -ENOMEM; | ||
3955 | } | ||
3956 | ret = copy_from_user(exec_list, | ||
3957 | (struct drm_i915_relocation_entry __user *) | ||
3958 | (uintptr_t) args->buffers_ptr, | ||
3959 | sizeof(*exec_list) * args->buffer_count); | ||
3960 | if (ret != 0) { | ||
3961 | DRM_ERROR("copy %d exec entries failed %d\n", | ||
3962 | args->buffer_count, ret); | ||
3963 | drm_free_large(exec_list); | ||
3964 | drm_free_large(exec2_list); | ||
3965 | return -EFAULT; | ||
3966 | } | ||
3967 | |||
3968 | for (i = 0; i < args->buffer_count; i++) { | ||
3969 | exec2_list[i].handle = exec_list[i].handle; | ||
3970 | exec2_list[i].relocation_count = exec_list[i].relocation_count; | ||
3971 | exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; | ||
3972 | exec2_list[i].alignment = exec_list[i].alignment; | ||
3973 | exec2_list[i].offset = exec_list[i].offset; | ||
3974 | if (!IS_I965G(dev)) | ||
3975 | exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; | ||
3976 | else | ||
3977 | exec2_list[i].flags = 0; | ||
3978 | } | ||
3979 | |||
3980 | exec2.buffers_ptr = args->buffers_ptr; | ||
3981 | exec2.buffer_count = args->buffer_count; | ||
3982 | exec2.batch_start_offset = args->batch_start_offset; | ||
3983 | exec2.batch_len = args->batch_len; | ||
3984 | exec2.DR1 = args->DR1; | ||
3985 | exec2.DR4 = args->DR4; | ||
3986 | exec2.num_cliprects = args->num_cliprects; | ||
3987 | exec2.cliprects_ptr = args->cliprects_ptr; | ||
3988 | exec2.flags = 0; | ||
3989 | |||
3990 | ret = i915_gem_do_execbuffer(dev, data, file_priv, &exec2, exec2_list); | ||
3991 | if (!ret) { | ||
3992 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
3993 | for (i = 0; i < args->buffer_count; i++) | ||
3994 | exec_list[i].offset = exec2_list[i].offset; | ||
3995 | /* ... and back out to userspace */ | ||
3996 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
3997 | (uintptr_t) args->buffers_ptr, | ||
3998 | exec_list, | ||
3999 | sizeof(*exec_list) * args->buffer_count); | ||
4000 | if (ret) { | ||
4001 | ret = -EFAULT; | ||
4002 | DRM_ERROR("failed to copy %d exec entries " | ||
4003 | "back to user (%d)\n", | ||
4004 | args->buffer_count, ret); | ||
4005 | } | ||
4006 | } else { | ||
4007 | DRM_ERROR("i915_gem_do_execbuffer returns %d\n", ret); | ||
4008 | } | ||
4009 | |||
4010 | drm_free_large(exec_list); | ||
4011 | drm_free_large(exec2_list); | ||
4012 | return ret; | ||
4013 | } | ||
4014 | |||
4015 | int | ||
4016 | i915_gem_execbuffer2(struct drm_device *dev, void *data, | ||
4017 | struct drm_file *file_priv) | ||
4018 | { | ||
4019 | struct drm_i915_gem_execbuffer2 *args = data; | ||
4020 | struct drm_i915_gem_exec_object2 *exec2_list = NULL; | ||
4021 | int ret; | ||
4022 | |||
4023 | #if WATCH_EXEC | ||
4024 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | ||
4025 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | ||
4026 | #endif | ||
4027 | |||
4028 | if (args->buffer_count < 1) { | ||
4029 | DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count); | ||
4030 | return -EINVAL; | ||
4031 | } | ||
4032 | |||
4033 | exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); | ||
4034 | if (exec2_list == NULL) { | ||
4035 | DRM_ERROR("Failed to allocate exec list for %d buffers\n", | ||
4036 | args->buffer_count); | ||
4037 | return -ENOMEM; | ||
4038 | } | ||
4039 | ret = copy_from_user(exec2_list, | ||
4040 | (struct drm_i915_relocation_entry __user *) | ||
4041 | (uintptr_t) args->buffers_ptr, | ||
4042 | sizeof(*exec2_list) * args->buffer_count); | ||
4043 | if (ret != 0) { | ||
4044 | DRM_ERROR("copy %d exec entries failed %d\n", | ||
4045 | args->buffer_count, ret); | ||
4046 | drm_free_large(exec2_list); | ||
4047 | return -EFAULT; | ||
4048 | } | ||
4049 | |||
4050 | ret = i915_gem_do_execbuffer(dev, data, file_priv, args, exec2_list); | ||
4051 | if (!ret) { | ||
4052 | /* Copy the new buffer offsets back to the user's exec list. */ | ||
4053 | ret = copy_to_user((struct drm_i915_relocation_entry __user *) | ||
4054 | (uintptr_t) args->buffers_ptr, | ||
4055 | exec2_list, | ||
4056 | sizeof(*exec2_list) * args->buffer_count); | ||
4057 | if (ret) { | ||
4058 | ret = -EFAULT; | ||
4059 | DRM_ERROR("failed to copy %d exec entries " | ||
4060 | "back to user (%d)\n", | ||
4061 | args->buffer_count, ret); | ||
4062 | } | ||
4063 | } | ||
4064 | |||
4065 | drm_free_large(exec2_list); | ||
4066 | return ret; | ||
4067 | } | ||
4068 | |||
3924 | int | 4069 | int |
3925 | i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | 4070 | i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) |
3926 | { | 4071 | { |
@@ -3934,19 +4079,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
3934 | if (ret) | 4079 | if (ret) |
3935 | return ret; | 4080 | return ret; |
3936 | } | 4081 | } |
3937 | /* | 4082 | |
3938 | * Pre-965 chips need a fence register set up in order to | ||
3939 | * properly handle tiled surfaces. | ||
3940 | */ | ||
3941 | if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) { | ||
3942 | ret = i915_gem_object_get_fence_reg(obj); | ||
3943 | if (ret != 0) { | ||
3944 | if (ret != -EBUSY && ret != -ERESTARTSYS) | ||
3945 | DRM_ERROR("Failure to install fence: %d\n", | ||
3946 | ret); | ||
3947 | return ret; | ||
3948 | } | ||
3949 | } | ||
3950 | obj_priv->pin_count++; | 4083 | obj_priv->pin_count++; |
3951 | 4084 | ||
3952 | /* If the object is not active and not pending a flush, | 4085 | /* If the object is not active and not pending a flush, |