diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 90 |
1 files changed, 55 insertions, 35 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index df5a7135c26..90b1d6753b9 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
35 | #include <linux/swap.h> | 35 | #include <linux/swap.h> |
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/intel-gtt.h> | ||
37 | 38 | ||
38 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); | 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); |
39 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); | 40 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); |
@@ -135,12 +136,13 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, | |||
135 | return -ENOMEM; | 136 | return -ENOMEM; |
136 | 137 | ||
137 | ret = drm_gem_handle_create(file_priv, obj, &handle); | 138 | ret = drm_gem_handle_create(file_priv, obj, &handle); |
139 | /* drop reference from allocate - handle holds it now */ | ||
138 | drm_gem_object_unreference_unlocked(obj); | 140 | drm_gem_object_unreference_unlocked(obj); |
139 | if (ret) | 141 | if (ret) { |
140 | return ret; | 142 | return ret; |
143 | } | ||
141 | 144 | ||
142 | args->handle = handle; | 145 | args->handle = handle; |
143 | |||
144 | return 0; | 146 | return 0; |
145 | } | 147 | } |
146 | 148 | ||
@@ -467,14 +469,17 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
467 | return -ENOENT; | 469 | return -ENOENT; |
468 | obj_priv = to_intel_bo(obj); | 470 | obj_priv = to_intel_bo(obj); |
469 | 471 | ||
470 | /* Bounds check source. | 472 | /* Bounds check source. */ |
471 | * | 473 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
472 | * XXX: This could use review for overflow issues... | 474 | ret = -EINVAL; |
473 | */ | 475 | goto err; |
474 | if (args->offset > obj->size || args->size > obj->size || | 476 | } |
475 | args->offset + args->size > obj->size) { | 477 | |
476 | drm_gem_object_unreference_unlocked(obj); | 478 | if (!access_ok(VERIFY_WRITE, |
477 | return -EINVAL; | 479 | (char __user *)(uintptr_t)args->data_ptr, |
480 | args->size)) { | ||
481 | ret = -EFAULT; | ||
482 | goto err; | ||
478 | } | 483 | } |
479 | 484 | ||
480 | if (i915_gem_object_needs_bit17_swizzle(obj)) { | 485 | if (i915_gem_object_needs_bit17_swizzle(obj)) { |
@@ -486,8 +491,8 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
486 | file_priv); | 491 | file_priv); |
487 | } | 492 | } |
488 | 493 | ||
494 | err: | ||
489 | drm_gem_object_unreference_unlocked(obj); | 495 | drm_gem_object_unreference_unlocked(obj); |
490 | |||
491 | return ret; | 496 | return ret; |
492 | } | 497 | } |
493 | 498 | ||
@@ -576,8 +581,6 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
576 | 581 | ||
577 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 582 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
578 | remain = args->size; | 583 | remain = args->size; |
579 | if (!access_ok(VERIFY_READ, user_data, remain)) | ||
580 | return -EFAULT; | ||
581 | 584 | ||
582 | 585 | ||
583 | mutex_lock(&dev->struct_mutex); | 586 | mutex_lock(&dev->struct_mutex); |
@@ -930,14 +933,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
930 | return -ENOENT; | 933 | return -ENOENT; |
931 | obj_priv = to_intel_bo(obj); | 934 | obj_priv = to_intel_bo(obj); |
932 | 935 | ||
933 | /* Bounds check destination. | 936 | /* Bounds check destination. */ |
934 | * | 937 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
935 | * XXX: This could use review for overflow issues... | 938 | ret = -EINVAL; |
936 | */ | 939 | goto err; |
937 | if (args->offset > obj->size || args->size > obj->size || | 940 | } |
938 | args->offset + args->size > obj->size) { | 941 | |
939 | drm_gem_object_unreference_unlocked(obj); | 942 | if (!access_ok(VERIFY_READ, |
940 | return -EINVAL; | 943 | (char __user *)(uintptr_t)args->data_ptr, |
944 | args->size)) { | ||
945 | ret = -EFAULT; | ||
946 | goto err; | ||
941 | } | 947 | } |
942 | 948 | ||
943 | /* We can only do the GTT pwrite on untiled buffers, as otherwise | 949 | /* We can only do the GTT pwrite on untiled buffers, as otherwise |
@@ -971,8 +977,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
971 | DRM_INFO("pwrite failed %d\n", ret); | 977 | DRM_INFO("pwrite failed %d\n", ret); |
972 | #endif | 978 | #endif |
973 | 979 | ||
980 | err: | ||
974 | drm_gem_object_unreference_unlocked(obj); | 981 | drm_gem_object_unreference_unlocked(obj); |
975 | |||
976 | return ret; | 982 | return ret; |
977 | } | 983 | } |
978 | 984 | ||
@@ -2347,14 +2353,21 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | |||
2347 | 2353 | ||
2348 | reg->obj = obj; | 2354 | reg->obj = obj; |
2349 | 2355 | ||
2350 | if (IS_GEN6(dev)) | 2356 | switch (INTEL_INFO(dev)->gen) { |
2357 | case 6: | ||
2351 | sandybridge_write_fence_reg(reg); | 2358 | sandybridge_write_fence_reg(reg); |
2352 | else if (IS_I965G(dev)) | 2359 | break; |
2360 | case 5: | ||
2361 | case 4: | ||
2353 | i965_write_fence_reg(reg); | 2362 | i965_write_fence_reg(reg); |
2354 | else if (IS_I9XX(dev)) | 2363 | break; |
2364 | case 3: | ||
2355 | i915_write_fence_reg(reg); | 2365 | i915_write_fence_reg(reg); |
2356 | else | 2366 | break; |
2367 | case 2: | ||
2357 | i830_write_fence_reg(reg); | 2368 | i830_write_fence_reg(reg); |
2369 | break; | ||
2370 | } | ||
2358 | 2371 | ||
2359 | trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg, | 2372 | trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg, |
2360 | obj_priv->tiling_mode); | 2373 | obj_priv->tiling_mode); |
@@ -2377,22 +2390,26 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) | |||
2377 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2390 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2378 | struct drm_i915_fence_reg *reg = | 2391 | struct drm_i915_fence_reg *reg = |
2379 | &dev_priv->fence_regs[obj_priv->fence_reg]; | 2392 | &dev_priv->fence_regs[obj_priv->fence_reg]; |
2393 | uint32_t fence_reg; | ||
2380 | 2394 | ||
2381 | if (IS_GEN6(dev)) { | 2395 | switch (INTEL_INFO(dev)->gen) { |
2396 | case 6: | ||
2382 | I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + | 2397 | I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + |
2383 | (obj_priv->fence_reg * 8), 0); | 2398 | (obj_priv->fence_reg * 8), 0); |
2384 | } else if (IS_I965G(dev)) { | 2399 | break; |
2400 | case 5: | ||
2401 | case 4: | ||
2385 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); | 2402 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); |
2386 | } else { | 2403 | break; |
2387 | uint32_t fence_reg; | 2404 | case 3: |
2388 | 2405 | if (obj_priv->fence_reg >= 8) | |
2389 | if (obj_priv->fence_reg < 8) | 2406 | fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 8) * 4; |
2390 | fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; | ||
2391 | else | 2407 | else |
2392 | fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - | 2408 | case 2: |
2393 | 8) * 4; | 2409 | fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; |
2394 | 2410 | ||
2395 | I915_WRITE(fence_reg, 0); | 2411 | I915_WRITE(fence_reg, 0); |
2412 | break; | ||
2396 | } | 2413 | } |
2397 | 2414 | ||
2398 | reg->obj = NULL; | 2415 | reg->obj = NULL; |
@@ -3243,6 +3260,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3243 | (int) reloc->offset, | 3260 | (int) reloc->offset, |
3244 | reloc->read_domains, | 3261 | reloc->read_domains, |
3245 | reloc->write_domain); | 3262 | reloc->write_domain); |
3263 | drm_gem_object_unreference(target_obj); | ||
3264 | i915_gem_object_unpin(obj); | ||
3246 | return -EINVAL; | 3265 | return -EINVAL; |
3247 | } | 3266 | } |
3248 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || | 3267 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || |
@@ -3585,6 +3604,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3585 | if (ret != 0) { | 3604 | if (ret != 0) { |
3586 | DRM_ERROR("copy %d cliprects failed: %d\n", | 3605 | DRM_ERROR("copy %d cliprects failed: %d\n", |
3587 | args->num_cliprects, ret); | 3606 | args->num_cliprects, ret); |
3607 | ret = -EFAULT; | ||
3588 | goto pre_mutex_err; | 3608 | goto pre_mutex_err; |
3589 | } | 3609 | } |
3590 | } | 3610 | } |