aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c37
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c67
3 files changed, 88 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 451b547352b7..7a84f04e8439 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -647,6 +647,7 @@ int i915_gem_object_unbind(struct drm_gem_object *obj);
647void i915_gem_lastclose(struct drm_device *dev); 647void i915_gem_lastclose(struct drm_device *dev);
648uint32_t i915_get_gem_seqno(struct drm_device *dev); 648uint32_t i915_get_gem_seqno(struct drm_device *dev);
649int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); 649int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
650int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
650void i915_gem_retire_requests(struct drm_device *dev); 651void i915_gem_retire_requests(struct drm_device *dev);
651void i915_gem_retire_work_handler(struct work_struct *work); 652void i915_gem_retire_work_handler(struct work_struct *work);
652void i915_gem_clflush_object(struct drm_gem_object *obj); 653void i915_gem_clflush_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 4f345414fe7c..174aef2d6481 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2162,7 +2162,6 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
2162 val |= I830_FENCE_REG_VALID; 2162 val |= I830_FENCE_REG_VALID;
2163 2163
2164 I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); 2164 I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
2165
2166} 2165}
2167 2166
2168/** 2167/**
@@ -2329,6 +2328,42 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
2329} 2328}
2330 2329
2331/** 2330/**
2331 * i915_gem_object_put_fence_reg - waits on outstanding fenced access
2332 * to the buffer to finish, and then resets the fence register.
2333 * @obj: tiled object holding a fence register.
2334 *
2335 * Zeroes out the fence register itself and clears out the associated
2336 * data structures in dev_priv and obj_priv.
2337 */
2338int
2339i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
2340{
2341 struct drm_device *dev = obj->dev;
2342 struct drm_i915_gem_object *obj_priv = obj->driver_private;
2343
2344 if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
2345 return 0;
2346
2347 /* On the i915, GPU access to tiled buffers is via a fence,
2348 * therefore we must wait for any outstanding access to complete
2349 * before clearing the fence.
2350 */
2351 if (!IS_I965G(dev)) {
2352 int ret;
2353
2354 i915_gem_object_flush_gpu_write_domain(obj);
2355 i915_gem_object_flush_gtt_write_domain(obj);
2356 ret = i915_gem_object_wait_rendering(obj);
2357 if (ret != 0)
2358 return ret;
2359 }
2360
2361 i915_gem_clear_fence_reg (obj);
2362
2363 return 0;
2364}
2365
2366/**
2332 * Finds free space in the GTT aperture and binds the object there. 2367 * Finds free space in the GTT aperture and binds the object there.
2333 */ 2368 */
2334static int 2369static int
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 9a05cadaa4ad..5c1ceec49f5b 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -408,7 +408,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
408 if (stride & (stride - 1)) 408 if (stride & (stride - 1))
409 return false; 409 return false;
410 410
411 /* We don't handle the aperture area covered by the fence being bigger 411 /* We don't 0handle the aperture area covered by the fence being bigger
412 * than the object size. 412 * than the object size.
413 */ 413 */
414 if (i915_get_fence_size(dev, size) != size) 414 if (i915_get_fence_size(dev, size) != size)
@@ -417,6 +417,33 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode)
417 return true; 417 return true;
418} 418}
419 419
420static bool
421i915_gem_object_fence_offset_ok(struct drm_gem_object *obj, int tiling_mode)
422{
423 struct drm_device *dev = obj->dev;
424 struct drm_i915_gem_object *obj_priv = obj->driver_private;
425
426 if (obj_priv->gtt_space == NULL)
427 return true;
428
429 if (tiling_mode == I915_TILING_NONE)
430 return true;
431
432 if (!IS_I965G(dev)) {
433 if (obj_priv->gtt_offset & (obj->size - 1))
434 return false;
435 if (IS_I9XX(dev)) {
436 if (obj_priv->gtt_offset & ~I915_FENCE_START_MASK)
437 return false;
438 } else {
439 if (obj_priv->gtt_offset & ~I830_FENCE_START_MASK)
440 return false;
441 }
442 }
443
444 return true;
445}
446
420/** 447/**
421 * Sets the tiling mode of an object, returning the required swizzling of 448 * Sets the tiling mode of an object, returning the required swizzling of
422 * bit 6 of addresses in the object. 449 * bit 6 of addresses in the object.
@@ -429,6 +456,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
429 drm_i915_private_t *dev_priv = dev->dev_private; 456 drm_i915_private_t *dev_priv = dev->dev_private;
430 struct drm_gem_object *obj; 457 struct drm_gem_object *obj;
431 struct drm_i915_gem_object *obj_priv; 458 struct drm_i915_gem_object *obj_priv;
459 int ret = 0;
432 460
433 obj = drm_gem_object_lookup(dev, file_priv, args->handle); 461 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
434 if (obj == NULL) 462 if (obj == NULL)
@@ -436,14 +464,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
436 obj_priv = obj->driver_private; 464 obj_priv = obj->driver_private;
437 465
438 if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) { 466 if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
467 mutex_lock(&dev->struct_mutex);
439 drm_gem_object_unreference(obj); 468 drm_gem_object_unreference(obj);
469 mutex_unlock(&dev->struct_mutex);
440 return -EINVAL; 470 return -EINVAL;
441 } 471 }
442 472
443 mutex_lock(&dev->struct_mutex);
444
445 if (args->tiling_mode == I915_TILING_NONE) { 473 if (args->tiling_mode == I915_TILING_NONE) {
446 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 474 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
475 args->stride = 0;
447 } else { 476 } else {
448 if (args->tiling_mode == I915_TILING_X) 477 if (args->tiling_mode == I915_TILING_X)
449 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x; 478 args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
@@ -466,32 +495,38 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
466 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) { 495 if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
467 args->tiling_mode = I915_TILING_NONE; 496 args->tiling_mode = I915_TILING_NONE;
468 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE; 497 args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
498 args->stride = 0;
469 } 499 }
470 } 500 }
471 if (args->tiling_mode != obj_priv->tiling_mode) {
472 int ret;
473 501
474 /* Unbind the object, as switching tiling means we're 502 mutex_lock(&dev->struct_mutex);
475 * switching the cache organization due to fencing, probably. 503 if (args->tiling_mode != obj_priv->tiling_mode ||
504 args->stride != obj_priv->stride) {
505 /* We need to rebind the object if its current allocation
506 * no longer meets the alignment restrictions for its new
507 * tiling mode. Otherwise we can just leave it alone, but
508 * need to ensure that any fence register is cleared.
476 */ 509 */
477 ret = i915_gem_object_unbind(obj); 510 if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
511 ret = i915_gem_object_unbind(obj);
512 else
513 ret = i915_gem_object_put_fence_reg(obj);
478 if (ret != 0) { 514 if (ret != 0) {
479 WARN(ret != -ERESTARTSYS, 515 WARN(ret != -ERESTARTSYS,
480 "failed to unbind object for tiling switch"); 516 "failed to reset object for tiling switch");
481 args->tiling_mode = obj_priv->tiling_mode; 517 args->tiling_mode = obj_priv->tiling_mode;
482 mutex_unlock(&dev->struct_mutex); 518 args->stride = obj_priv->stride;
483 drm_gem_object_unreference(obj); 519 goto err;
484
485 return ret;
486 } 520 }
521
487 obj_priv->tiling_mode = args->tiling_mode; 522 obj_priv->tiling_mode = args->tiling_mode;
523 obj_priv->stride = args->stride;
488 } 524 }
489 obj_priv->stride = args->stride; 525err:
490
491 drm_gem_object_unreference(obj); 526 drm_gem_object_unreference(obj);
492 mutex_unlock(&dev->struct_mutex); 527 mutex_unlock(&dev->struct_mutex);
493 528
494 return 0; 529 return ret;
495} 530}
496 531
497/** 532/**