aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c90
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
38static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); 39static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj);
39static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); 40static 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
494err:
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
980err:
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 }