diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-02-13 03:44:22 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-13 03:44:22 -0500 |
commit | f8a6b2b9cee298a9663cbe38ce1eb5240987cb62 (patch) | |
tree | b356490269c9e77d164dcc1477792b882fbb8bdb /drivers/gpu/drm/i915/i915_gem.c | |
parent | ba1511bf7fbda452138e4096bf10d5a382710f4f (diff) | |
parent | 071a0bc2ceace31266836801510879407a3701fa (diff) |
Merge branch 'linus' into x86/apic
Conflicts:
arch/x86/kernel/acpi/boot.c
arch/x86/mm/fault.c
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 83 |
1 files changed, 55 insertions, 28 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index debad5c04cc0..818576654092 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 void 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) >> |
@@ -585,8 +586,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
585 | 586 | ||
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 | i915_gem_object_get_fence_reg(obj); | 590 | ret = i915_gem_object_get_fence_reg(obj, write); |
591 | if (ret) { | ||
592 | mutex_unlock(&dev->struct_mutex); | ||
593 | return VM_FAULT_SIGBUS; | ||
594 | } | ||
595 | } | ||
590 | 596 | ||
591 | pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + | 597 | pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + |
592 | page_offset; | 598 | page_offset; |
@@ -1211,7 +1217,7 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) | |||
1211 | /** | 1217 | /** |
1212 | * Unbinds an object from the GTT aperture. | 1218 | * Unbinds an object from the GTT aperture. |
1213 | */ | 1219 | */ |
1214 | static int | 1220 | int |
1215 | i915_gem_object_unbind(struct drm_gem_object *obj) | 1221 | i915_gem_object_unbind(struct drm_gem_object *obj) |
1216 | { | 1222 | { |
1217 | struct drm_device *dev = obj->dev; | 1223 | struct drm_device *dev = obj->dev; |
@@ -1445,21 +1451,26 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1445 | drm_i915_private_t *dev_priv = dev->dev_private; | 1451 | drm_i915_private_t *dev_priv = dev->dev_private; |
1446 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1452 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
1447 | int regnum = obj_priv->fence_reg; | 1453 | int regnum = obj_priv->fence_reg; |
1454 | int tile_width; | ||
1448 | uint32_t val; | 1455 | uint32_t val; |
1449 | uint32_t pitch_val; | 1456 | uint32_t pitch_val; |
1450 | 1457 | ||
1451 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1458 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
1452 | (obj_priv->gtt_offset & (obj->size - 1))) { | 1459 | (obj_priv->gtt_offset & (obj->size - 1))) { |
1453 | WARN(1, "%s: object not 1M or size aligned\n", __func__); | 1460 | WARN(1, "%s: object 0x%08x not 1M or size (0x%zx) aligned\n", |
1461 | __func__, obj_priv->gtt_offset, obj->size); | ||
1454 | return; | 1462 | return; |
1455 | } | 1463 | } |
1456 | 1464 | ||
1457 | if (obj_priv->tiling_mode == I915_TILING_Y && (IS_I945G(dev) || | 1465 | if (obj_priv->tiling_mode == I915_TILING_Y && |
1458 | IS_I945GM(dev) || | 1466 | HAS_128_BYTE_Y_TILING(dev)) |
1459 | IS_G33(dev))) | 1467 | tile_width = 128; |
1460 | pitch_val = (obj_priv->stride / 128) - 1; | ||
1461 | else | 1468 | else |
1462 | pitch_val = (obj_priv->stride / 512) - 1; | 1469 | tile_width = 512; |
1470 | |||
1471 | /* Note: pitch better be a power of two tile widths */ | ||
1472 | pitch_val = obj_priv->stride / tile_width; | ||
1473 | pitch_val = ffs(pitch_val) - 1; | ||
1463 | 1474 | ||
1464 | val = obj_priv->gtt_offset; | 1475 | val = obj_priv->gtt_offset; |
1465 | if (obj_priv->tiling_mode == I915_TILING_Y) | 1476 | if (obj_priv->tiling_mode == I915_TILING_Y) |
@@ -1483,7 +1494,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1483 | 1494 | ||
1484 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1495 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
1485 | (obj_priv->gtt_offset & (obj->size - 1))) { | 1496 | (obj_priv->gtt_offset & (obj->size - 1))) { |
1486 | WARN(1, "%s: object not 1M or size aligned\n", __func__); | 1497 | WARN(1, "%s: object 0x%08x not 1M or size aligned\n", |
1498 | __func__, obj_priv->gtt_offset); | ||
1487 | return; | 1499 | return; |
1488 | } | 1500 | } |
1489 | 1501 | ||
@@ -1503,6 +1515,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1503 | /** | 1515 | /** |
1504 | * i915_gem_object_get_fence_reg - set up a fence reg for an object | 1516 | * i915_gem_object_get_fence_reg - set up a fence reg for an object |
1505 | * @obj: object to map through a fence reg | 1517 | * @obj: object to map through a fence reg |
1518 | * @write: object is about to be written | ||
1506 | * | 1519 | * |
1507 | * When mapping objects through the GTT, userspace wants to be able to write | 1520 | * When mapping objects through the GTT, userspace wants to be able to write |
1508 | * to them without having to worry about swizzling if the object is tiled. | 1521 | * to them without having to worry about swizzling if the object is tiled. |
@@ -1513,8 +1526,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
1513 | * It then sets up the reg based on the object's properties: address, pitch | 1526 | * It then sets up the reg based on the object's properties: address, pitch |
1514 | * and tiling format. | 1527 | * and tiling format. |
1515 | */ | 1528 | */ |
1516 | static void | 1529 | static int |
1517 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | 1530 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) |
1518 | { | 1531 | { |
1519 | struct drm_device *dev = obj->dev; | 1532 | struct drm_device *dev = obj->dev; |
1520 | struct drm_i915_private *dev_priv = dev->dev_private; | 1533 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -1527,12 +1540,18 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | |||
1527 | WARN(1, "allocating a fence for non-tiled object?\n"); | 1540 | WARN(1, "allocating a fence for non-tiled object?\n"); |
1528 | break; | 1541 | break; |
1529 | case I915_TILING_X: | 1542 | case I915_TILING_X: |
1530 | WARN(obj_priv->stride & (512 - 1), | 1543 | if (!obj_priv->stride) |
1531 | "object is X tiled but has non-512B pitch\n"); | 1544 | return -EINVAL; |
1545 | WARN((obj_priv->stride & (512 - 1)), | ||
1546 | "object 0x%08x is X tiled but has non-512B pitch\n", | ||
1547 | obj_priv->gtt_offset); | ||
1532 | break; | 1548 | break; |
1533 | case I915_TILING_Y: | 1549 | case I915_TILING_Y: |
1534 | WARN(obj_priv->stride & (128 - 1), | 1550 | if (!obj_priv->stride) |
1535 | "object is Y tiled but has non-128B pitch\n"); | 1551 | return -EINVAL; |
1552 | WARN((obj_priv->stride & (128 - 1)), | ||
1553 | "object 0x%08x is Y tiled but has non-128B pitch\n", | ||
1554 | obj_priv->gtt_offset); | ||
1536 | break; | 1555 | break; |
1537 | } | 1556 | } |
1538 | 1557 | ||
@@ -1563,10 +1582,11 @@ try_again: | |||
1563 | * objects to finish before trying again. | 1582 | * objects to finish before trying again. |
1564 | */ | 1583 | */ |
1565 | if (i == dev_priv->num_fence_regs) { | 1584 | if (i == dev_priv->num_fence_regs) { |
1566 | ret = i915_gem_object_wait_rendering(reg->obj); | 1585 | ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); |
1567 | if (ret) { | 1586 | if (ret) { |
1568 | WARN(ret, "wait_rendering failed: %d\n", ret); | 1587 | WARN(ret != -ERESTARTSYS, |
1569 | return; | 1588 | "switch to GTT domain failed: %d\n", ret); |
1589 | return ret; | ||
1570 | } | 1590 | } |
1571 | goto try_again; | 1591 | goto try_again; |
1572 | } | 1592 | } |
@@ -1591,6 +1611,8 @@ try_again: | |||
1591 | i915_write_fence_reg(reg); | 1611 | i915_write_fence_reg(reg); |
1592 | else | 1612 | else |
1593 | i830_write_fence_reg(reg); | 1613 | i830_write_fence_reg(reg); |
1614 | |||
1615 | return 0; | ||
1594 | } | 1616 | } |
1595 | 1617 | ||
1596 | /** | 1618 | /** |
@@ -1631,7 +1653,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
1631 | if (dev_priv->mm.suspended) | 1653 | if (dev_priv->mm.suspended) |
1632 | return -EBUSY; | 1654 | return -EBUSY; |
1633 | if (alignment == 0) | 1655 | if (alignment == 0) |
1634 | alignment = PAGE_SIZE; | 1656 | alignment = i915_gem_get_gtt_alignment(obj); |
1635 | if (alignment & (PAGE_SIZE - 1)) { | 1657 | if (alignment & (PAGE_SIZE - 1)) { |
1636 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); | 1658 | DRM_ERROR("Invalid object alignment requested %u\n", alignment); |
1637 | return -EINVAL; | 1659 | return -EINVAL; |
@@ -2652,6 +2674,14 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
2652 | DRM_ERROR("Failure to bind: %d", ret); | 2674 | DRM_ERROR("Failure to bind: %d", ret); |
2653 | return ret; | 2675 | return ret; |
2654 | } | 2676 | } |
2677 | /* | ||
2678 | * Pre-965 chips need a fence register set up in order to | ||
2679 | * properly handle tiled surfaces. | ||
2680 | */ | ||
2681 | if (!IS_I965G(dev) && | ||
2682 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
2683 | obj_priv->tiling_mode != I915_TILING_NONE) | ||
2684 | i915_gem_object_get_fence_reg(obj, true); | ||
2655 | } | 2685 | } |
2656 | obj_priv->pin_count++; | 2686 | obj_priv->pin_count++; |
2657 | 2687 | ||
@@ -3229,10 +3259,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
3229 | dev_priv->mm.wedged = 0; | 3259 | dev_priv->mm.wedged = 0; |
3230 | } | 3260 | } |
3231 | 3261 | ||
3232 | dev_priv->mm.gtt_mapping = io_mapping_create_wc(dev->agp->base, | ||
3233 | dev->agp->agp_info.aper_size | ||
3234 | * 1024 * 1024); | ||
3235 | |||
3236 | mutex_lock(&dev->struct_mutex); | 3262 | mutex_lock(&dev->struct_mutex); |
3237 | dev_priv->mm.suspended = 0; | 3263 | dev_priv->mm.suspended = 0; |
3238 | 3264 | ||
@@ -3255,7 +3281,6 @@ int | |||
3255 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, | 3281 | i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, |
3256 | struct drm_file *file_priv) | 3282 | struct drm_file *file_priv) |
3257 | { | 3283 | { |
3258 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
3259 | int ret; | 3284 | int ret; |
3260 | 3285 | ||
3261 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | 3286 | if (drm_core_check_feature(dev, DRIVER_MODESET)) |
@@ -3264,7 +3289,6 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, | |||
3264 | ret = i915_gem_idle(dev); | 3289 | ret = i915_gem_idle(dev); |
3265 | drm_irq_uninstall(dev); | 3290 | drm_irq_uninstall(dev); |
3266 | 3291 | ||
3267 | io_mapping_free(dev_priv->mm.gtt_mapping); | ||
3268 | return ret; | 3292 | return ret; |
3269 | } | 3293 | } |
3270 | 3294 | ||
@@ -3273,6 +3297,9 @@ i915_gem_lastclose(struct drm_device *dev) | |||
3273 | { | 3297 | { |
3274 | int ret; | 3298 | int ret; |
3275 | 3299 | ||
3300 | if (drm_core_check_feature(dev, DRIVER_MODESET)) | ||
3301 | return; | ||
3302 | |||
3276 | ret = i915_gem_idle(dev); | 3303 | ret = i915_gem_idle(dev); |
3277 | if (ret) | 3304 | if (ret) |
3278 | DRM_ERROR("failed to idle hardware: %d\n", ret); | 3305 | DRM_ERROR("failed to idle hardware: %d\n", ret); |
@@ -3294,7 +3321,7 @@ i915_gem_load(struct drm_device *dev) | |||
3294 | /* Old X drivers will take 0-2 for front, back, depth buffers */ | 3321 | /* Old X drivers will take 0-2 for front, back, depth buffers */ |
3295 | dev_priv->fence_reg_start = 3; | 3322 | dev_priv->fence_reg_start = 3; |
3296 | 3323 | ||
3297 | if (IS_I965G(dev)) | 3324 | if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
3298 | dev_priv->num_fence_regs = 16; | 3325 | dev_priv->num_fence_regs = 16; |
3299 | else | 3326 | else |
3300 | dev_priv->num_fence_regs = 8; | 3327 | dev_priv->num_fence_regs = 8; |