diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-01-26 20:10:45 -0500 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2009-02-08 06:38:02 -0500 |
commit | 0f973f27888e4664b253ab2cf69c67c2eb80ab1b (patch) | |
tree | 1f921af14dff65311dd10106dfc10778e3730b1e /drivers/gpu/drm/i915/i915_gem.c | |
parent | d9ddcb96e05cfbadf3dbf66859bcaf5eae25af0b (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.c | 56 |
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); | |||
52 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); | 52 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); |
53 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, | 53 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, |
54 | unsigned alignment); | 54 | unsigned alignment); |
55 | static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj); | 55 | static int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write); |
56 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); | 56 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); |
57 | static int i915_gem_evict_something(struct drm_device *dev); | 57 | static int i915_gem_evict_something(struct drm_device *dev); |
58 | static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | 58 | static 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 | */ |
1217 | static int | 1218 | int |
1218 | i915_gem_object_unbind(struct drm_gem_object *obj) | 1219 | i915_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 | */ |
1519 | static int | 1527 | static int |
1520 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | 1528 | i915_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; |