aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2009-01-26 20:10:45 -0500
committerDave Airlie <airlied@linux.ie>2009-02-08 06:38:02 -0500
commit0f973f27888e4664b253ab2cf69c67c2eb80ab1b (patch)
tree1f921af14dff65311dd10106dfc10778e3730b1e /drivers/gpu/drm/i915/i915_gem.c
parentd9ddcb96e05cfbadf3dbf66859bcaf5eae25af0b (diff)
drm/i915: add fence register management to execbuf
Adds code to set up fence registers at execbuf time on pre-965 chips as necessary. Also fixes up a few bugs in the pre-965 tile register support (get_order != ffs). The number of fences available to the kernel defaults to the hw limit minus 3 (for legacy X front/back/depth), but a new parameter allows userspace to override that as needed. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index e1f831f166ca..6a9e3a875083 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -52,7 +52,7 @@ static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
52static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); 52static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
53static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, 53static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
54 unsigned alignment); 54 unsigned alignment);
55static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); 55static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write);
56static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); 56static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
57static int i915_gem_evict_something(struct drm_device *dev); 57static int i915_gem_evict_something(struct drm_device *dev);
58static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, 58static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
@@ -567,6 +567,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
567 pgoff_t page_offset; 567 pgoff_t page_offset;
568 unsigned long pfn; 568 unsigned long pfn;
569 int ret = 0; 569 int ret = 0;
570 bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
570 571
571 /* We don't use vmf->pgoff since that has the fake offset */ 572 /* We don't use vmf->pgoff since that has the fake offset */
572 page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> 573 page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
@@ -586,7 +587,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
586 /* Need a new fence register? */ 587 /* Need a new fence register? */
587 if (obj_priv->fence_reg == I915_FENCE_REG_NONE && 588 if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
588 obj_priv->tiling_mode != I915_TILING_NONE) { 589 obj_priv->tiling_mode != I915_TILING_NONE) {
589 ret = i915_gem_object_get_fence_reg(obj); 590 ret = i915_gem_object_get_fence_reg(obj, write);
590 if (ret != 0) 591 if (ret != 0)
591 return VM_FAULT_SIGBUS; 592 return VM_FAULT_SIGBUS;
592 } 593 }
@@ -1214,7 +1215,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj)
1214/** 1215/**
1215 * Unbinds an object from the GTT aperture. 1216 * Unbinds an object from the GTT aperture.
1216 */ 1217 */
1217static int 1218int
1218i915_gem_object_unbind(struct drm_gem_object *obj) 1219i915_gem_object_unbind(struct drm_gem_object *obj)
1219{ 1220{
1220 struct drm_device *dev = obj->dev; 1221 struct drm_device *dev = obj->dev;
@@ -1448,21 +1449,26 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
1448 drm_i915_private_t *dev_priv = dev->dev_private; 1449 drm_i915_private_t *dev_priv = dev->dev_private;
1449 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1450 struct drm_i915_gem_object *obj_priv = obj->driver_private;
1450 int regnum = obj_priv->fence_reg; 1451 int regnum = obj_priv->fence_reg;
1452 int tile_width;
1451 uint32_t val; 1453 uint32_t val;
1452 uint32_t pitch_val; 1454 uint32_t pitch_val;
1453 1455
1454 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || 1456 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
1455 (obj_priv->gtt_offset & (obj->size - 1))) { 1457 (obj_priv->gtt_offset & (obj->size - 1))) {
1456 WARN(1, "%s: object not 1M or size aligned\n", __func__); 1458 WARN(1, "%s: object 0x%08x not 1M or size (0x%x) aligned\n",
1459 __func__, obj_priv->gtt_offset, obj->size);
1457 return; 1460 return;
1458 } 1461 }
1459 1462
1460 if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) || 1463 if (obj_priv->tiling_mode == I915_TILING_Y &&
1461 IS_I945GM(dev) || 1464 HAS_128_BYTE_Y_TILING(dev))
1462 IS_G33(dev))) 1465 tile_width = 128;
1463 pitch_val = (obj_priv->stride / 128) - 1;
1464 else 1466 else
1465 pitch_val = (obj_priv->stride / 512) - 1; 1467 tile_width = 512;
1468
1469 /* Note: pitch better be a power of two tile widths */
1470 pitch_val = obj_priv->stride / tile_width;
1471 pitch_val = ffs(pitch_val) - 1;
1466 1472
1467 val = obj_priv->gtt_offset; 1473 val = obj_priv->gtt_offset;
1468 if (obj_priv->tiling_mode == I915_TILING_Y) 1474 if (obj_priv->tiling_mode == I915_TILING_Y)
@@ -1486,7 +1492,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
1486 1492
1487 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || 1493 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
1488 (obj_priv->gtt_offset & (obj->size - 1))) { 1494 (obj_priv->gtt_offset & (obj->size - 1))) {
1489 WARN(1, "%s: object not 1M or size aligned\n", __func__); 1495 WARN(1, "%s: object 0x%08x not 1M or size aligned\n",
1496 __func__, obj_priv->gtt_offset);
1490 return; 1497 return;
1491 } 1498 }
1492 1499
@@ -1506,6 +1513,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
1506/** 1513/**
1507 * i915_gem_object_get_fence_reg - set up a fence reg for an object 1514 * i915_gem_object_get_fence_reg - set up a fence reg for an object
1508 * @obj: object to map through a fence reg 1515 * @obj: object to map through a fence reg
1516 * @write: object is about to be written
1509 * 1517 *
1510 * When mapping objects through the GTT, userspace wants to be able to write 1518 * When mapping objects through the GTT, userspace wants to be able to write
1511 * to them without having to worry about swizzling if the object is tiled. 1519 * to them without having to worry about swizzling if the object is tiled.
@@ -1517,7 +1525,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
1517 * and tiling format. 1525 * and tiling format.
1518 */ 1526 */
1519static int 1527static int
1520i915_gem_object_get_fence_reg(struct drm_gem_object *obj) 1528i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
1521{ 1529{
1522 struct drm_device *dev = obj->dev; 1530 struct drm_device *dev = obj->dev;
1523 struct drm_i915_private *dev_priv = dev->dev_private; 1531 struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1530,12 +1538,18 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
1530 WARN(1, "allocating a fence for non-tiled object?\n"); 1538 WARN(1, "allocating a fence for non-tiled object?\n");
1531 break; 1539 break;
1532 case I915_TILING_X: 1540 case I915_TILING_X:
1533 WARN(obj_priv->stride & (512 - 1), 1541 if (!obj_priv->stride)
1534 "object is X tiled but has non-512B pitch\n"); 1542 return -EINVAL;
1543 WARN((obj_priv->stride & (512 - 1)),
1544 "object 0x%08x is X tiled but has non-512B pitch\n",
1545 obj_priv->gtt_offset);
1535 break; 1546 break;
1536 case I915_TILING_Y: 1547 case I915_TILING_Y:
1537 WARN(obj_priv->stride & (128 - 1), 1548 if (!obj_priv->stride)
1538 "object is Y tiled but has non-128B pitch\n"); 1549 return -EINVAL;
1550 WARN((obj_priv->stride & (128 - 1)),
1551 "object 0x%08x is Y tiled but has non-128B pitch\n",
1552 obj_priv->gtt_offset);
1539 break; 1553 break;
1540 } 1554 }
1541 1555
@@ -1637,7 +1651,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
1637 if (dev_priv->mm.suspended) 1651 if (dev_priv->mm.suspended)
1638 return -EBUSY; 1652 return -EBUSY;
1639 if (alignment == 0) 1653 if (alignment == 0)
1640 alignment = PAGE_SIZE; 1654 alignment = i915_gem_get_gtt_alignment(obj);
1641 if (alignment & (PAGE_SIZE - 1)) { 1655 if (alignment & (PAGE_SIZE - 1)) {
1642 DRM_ERROR("Invalid object alignment requested %u\n", alignment); 1656 DRM_ERROR("Invalid object alignment requested %u\n", alignment);
1643 return -EINVAL; 1657 return -EINVAL;
@@ -2658,6 +2672,14 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
2658 DRM_ERROR("Failure to bind: %d", ret); 2672 DRM_ERROR("Failure to bind: %d", ret);
2659 return ret; 2673 return ret;
2660 } 2674 }
2675 /*
2676 * Pre-965 chips need a fence register set up in order to
2677 * properly handle tiled surfaces.
2678 */
2679 if (!IS_I965G(dev) &&
2680 obj_priv->fence_reg == I915_FENCE_REG_NONE &&
2681 obj_priv->tiling_mode != I915_TILING_NONE)
2682 i915_gem_object_get_fence_reg(obj, true);
2661 } 2683 }
2662 obj_priv->pin_count++; 2684 obj_priv->pin_count++;
2663 2685
@@ -3297,7 +3319,7 @@ i915_gem_load(struct drm_device *dev)
3297 /* Old X drivers will take 0-2 for front, back, depth buffers */ 3319 /* Old X drivers will take 0-2 for front, back, depth buffers */
3298 dev_priv->fence_reg_start = 3; 3320 dev_priv->fence_reg_start = 3;
3299 3321
3300 if (IS_I965G(dev)) 3322 if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
3301 dev_priv->num_fence_regs = 16; 3323 dev_priv->num_fence_regs = 16;
3302 else 3324 else
3303 dev_priv->num_fence_regs = 8; 3325 dev_priv->num_fence_regs = 8;