diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 7 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 115 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_suspend.c | 11 |
5 files changed, 99 insertions, 37 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 6dab63bdc4c1..6d21b9e48b89 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -1105,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
| 1105 | 1024 * 1024, | 1105 | 1024 * 1024, |
| 1106 | MTRR_TYPE_WRCOMB, 1); | 1106 | MTRR_TYPE_WRCOMB, 1); |
| 1107 | if (dev_priv->mm.gtt_mtrr < 0) { | 1107 | if (dev_priv->mm.gtt_mtrr < 0) { |
| 1108 | DRM_INFO("MTRR allocation failed\n. Graphics " | 1108 | DRM_INFO("MTRR allocation failed. Graphics " |
| 1109 | "performance may suffer.\n"); | 1109 | "performance may suffer.\n"); |
| 1110 | } | 1110 | } |
| 1111 | 1111 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17fa40858d26..d6cc9861e0a1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -279,7 +279,6 @@ typedef struct drm_i915_private { | |||
| 279 | u8 saveAR_INDEX; | 279 | u8 saveAR_INDEX; |
| 280 | u8 saveAR[21]; | 280 | u8 saveAR[21]; |
| 281 | u8 saveDACMASK; | 281 | u8 saveDACMASK; |
| 282 | u8 saveDACDATA[256*3]; /* 256 3-byte colors */ | ||
| 283 | u8 saveCR[37]; | 282 | u8 saveCR[37]; |
| 284 | 283 | ||
| 285 | struct { | 284 | struct { |
| @@ -457,6 +456,12 @@ struct drm_i915_gem_object { | |||
| 457 | 456 | ||
| 458 | /** for phy allocated objects */ | 457 | /** for phy allocated objects */ |
| 459 | struct drm_i915_gem_phys_object *phys_obj; | 458 | struct drm_i915_gem_phys_object *phys_obj; |
| 459 | |||
| 460 | /** | ||
| 461 | * Used for checking the object doesn't appear more than once | ||
| 462 | * in an execbuffer object list. | ||
| 463 | */ | ||
| 464 | int in_execbuffer; | ||
| 460 | }; | 465 | }; |
| 461 | 466 | ||
| 462 | /** | 467 | /** |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 85685bfd12da..37427e4016cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1476,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1476 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1476 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1477 | int regnum = obj_priv->fence_reg; | 1477 | int regnum = obj_priv->fence_reg; |
| 1478 | int tile_width; | 1478 | int tile_width; |
| 1479 | uint32_t val; | 1479 | uint32_t fence_reg, val; |
| 1480 | uint32_t pitch_val; | 1480 | uint32_t pitch_val; |
| 1481 | 1481 | ||
| 1482 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || | 1482 | if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || |
| @@ -1503,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 1503 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; | 1503 | val |= pitch_val << I830_FENCE_PITCH_SHIFT; |
| 1504 | val |= I830_FENCE_REG_VALID; | 1504 | val |= I830_FENCE_REG_VALID; |
| 1505 | 1505 | ||
| 1506 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); | 1506 | if (regnum < 8) |
| 1507 | fence_reg = FENCE_REG_830_0 + (regnum * 4); | ||
| 1508 | else | ||
| 1509 | fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); | ||
| 1510 | I915_WRITE(fence_reg, val); | ||
| 1507 | } | 1511 | } |
| 1508 | 1512 | ||
| 1509 | static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | 1513 | static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) |
| @@ -1557,7 +1561,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) | |||
| 1557 | struct drm_i915_private *dev_priv = dev->dev_private; | 1561 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 1558 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1562 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
| 1559 | struct drm_i915_fence_reg *reg = NULL; | 1563 | struct drm_i915_fence_reg *reg = NULL; |
| 1560 | int i, ret; | 1564 | struct drm_i915_gem_object *old_obj_priv = NULL; |
| 1565 | int i, ret, avail; | ||
| 1561 | 1566 | ||
| 1562 | switch (obj_priv->tiling_mode) { | 1567 | switch (obj_priv->tiling_mode) { |
| 1563 | case I915_TILING_NONE: | 1568 | case I915_TILING_NONE: |
| @@ -1580,25 +1585,46 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) | |||
| 1580 | } | 1585 | } |
| 1581 | 1586 | ||
| 1582 | /* First try to find a free reg */ | 1587 | /* First try to find a free reg */ |
| 1588 | try_again: | ||
| 1589 | avail = 0; | ||
| 1583 | for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { | 1590 | for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { |
| 1584 | reg = &dev_priv->fence_regs[i]; | 1591 | reg = &dev_priv->fence_regs[i]; |
| 1585 | if (!reg->obj) | 1592 | if (!reg->obj) |
| 1586 | break; | 1593 | break; |
| 1594 | |||
| 1595 | old_obj_priv = reg->obj->driver_private; | ||
| 1596 | if (!old_obj_priv->pin_count) | ||
| 1597 | avail++; | ||
| 1587 | } | 1598 | } |
| 1588 | 1599 | ||
| 1589 | /* None available, try to steal one or wait for a user to finish */ | 1600 | /* None available, try to steal one or wait for a user to finish */ |
| 1590 | if (i == dev_priv->num_fence_regs) { | 1601 | if (i == dev_priv->num_fence_regs) { |
| 1591 | struct drm_i915_gem_object *old_obj_priv = NULL; | 1602 | uint32_t seqno = dev_priv->mm.next_gem_seqno; |
| 1592 | loff_t offset; | 1603 | loff_t offset; |
| 1593 | 1604 | ||
| 1594 | try_again: | 1605 | if (avail == 0) |
| 1595 | /* Could try to use LRU here instead... */ | 1606 | return -ENOMEM; |
| 1607 | |||
| 1596 | for (i = dev_priv->fence_reg_start; | 1608 | for (i = dev_priv->fence_reg_start; |
| 1597 | i < dev_priv->num_fence_regs; i++) { | 1609 | i < dev_priv->num_fence_regs; i++) { |
| 1610 | uint32_t this_seqno; | ||
| 1611 | |||
| 1598 | reg = &dev_priv->fence_regs[i]; | 1612 | reg = &dev_priv->fence_regs[i]; |
| 1599 | old_obj_priv = reg->obj->driver_private; | 1613 | old_obj_priv = reg->obj->driver_private; |
| 1600 | if (!old_obj_priv->pin_count) | 1614 | |
| 1615 | if (old_obj_priv->pin_count) | ||
| 1616 | continue; | ||
| 1617 | |||
| 1618 | /* i915 uses fences for GPU access to tiled buffers */ | ||
| 1619 | if (IS_I965G(dev) || !old_obj_priv->active) | ||
| 1601 | break; | 1620 | break; |
| 1621 | |||
| 1622 | /* find the seqno of the first available fence */ | ||
| 1623 | this_seqno = old_obj_priv->last_rendering_seqno; | ||
| 1624 | if (this_seqno != 0 && | ||
| 1625 | reg->obj->write_domain == 0 && | ||
| 1626 | i915_seqno_passed(seqno, this_seqno)) | ||
| 1627 | seqno = this_seqno; | ||
| 1602 | } | 1628 | } |
| 1603 | 1629 | ||
| 1604 | /* | 1630 | /* |
| @@ -1606,15 +1632,25 @@ try_again: | |||
| 1606 | * objects to finish before trying again. | 1632 | * objects to finish before trying again. |
| 1607 | */ | 1633 | */ |
| 1608 | if (i == dev_priv->num_fence_regs) { | 1634 | if (i == dev_priv->num_fence_regs) { |
| 1609 | ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); | 1635 | if (seqno == dev_priv->mm.next_gem_seqno) { |
| 1610 | if (ret) { | 1636 | i915_gem_flush(dev, |
| 1611 | WARN(ret != -ERESTARTSYS, | 1637 | I915_GEM_GPU_DOMAINS, |
| 1612 | "switch to GTT domain failed: %d\n", ret); | 1638 | I915_GEM_GPU_DOMAINS); |
| 1613 | return ret; | 1639 | seqno = i915_add_request(dev, |
| 1640 | I915_GEM_GPU_DOMAINS); | ||
| 1641 | if (seqno == 0) | ||
| 1642 | return -ENOMEM; | ||
| 1614 | } | 1643 | } |
| 1644 | |||
| 1645 | ret = i915_wait_request(dev, seqno); | ||
| 1646 | if (ret) | ||
| 1647 | return ret; | ||
| 1615 | goto try_again; | 1648 | goto try_again; |
| 1616 | } | 1649 | } |
| 1617 | 1650 | ||
| 1651 | BUG_ON(old_obj_priv->active || | ||
| 1652 | (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); | ||
| 1653 | |||
| 1618 | /* | 1654 | /* |
| 1619 | * Zap this virtual mapping so we can set up a fence again | 1655 | * Zap this virtual mapping so we can set up a fence again |
| 1620 | * for this object next time we need it. | 1656 | * for this object next time we need it. |
| @@ -1655,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) | |||
| 1655 | 1691 | ||
| 1656 | if (IS_I965G(dev)) | 1692 | if (IS_I965G(dev)) |
| 1657 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); | 1693 | I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); |
| 1658 | else | 1694 | else { |
| 1659 | I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); | 1695 | uint32_t fence_reg; |
| 1696 | |||
| 1697 | if (obj_priv->fence_reg < 8) | ||
| 1698 | fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; | ||
| 1699 | else | ||
| 1700 | fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - | ||
| 1701 | 8) * 4; | ||
| 1702 | |||
| 1703 | I915_WRITE(fence_reg, 0); | ||
| 1704 | } | ||
| 1660 | 1705 | ||
| 1661 | dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; | 1706 | dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; |
| 1662 | obj_priv->fence_reg = I915_FENCE_REG_NONE; | 1707 | obj_priv->fence_reg = I915_FENCE_REG_NONE; |
| @@ -2469,6 +2514,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2469 | struct drm_i915_gem_exec_object *exec_list = NULL; | 2514 | struct drm_i915_gem_exec_object *exec_list = NULL; |
| 2470 | struct drm_gem_object **object_list = NULL; | 2515 | struct drm_gem_object **object_list = NULL; |
| 2471 | struct drm_gem_object *batch_obj; | 2516 | struct drm_gem_object *batch_obj; |
| 2517 | struct drm_i915_gem_object *obj_priv; | ||
| 2472 | int ret, i, pinned = 0; | 2518 | int ret, i, pinned = 0; |
| 2473 | uint64_t exec_offset; | 2519 | uint64_t exec_offset; |
| 2474 | uint32_t seqno, flush_domains; | 2520 | uint32_t seqno, flush_domains; |
| @@ -2533,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
| 2533 | ret = -EBADF; | 2579 | ret = -EBADF; |
| 2534 | goto err; | 2580 | goto err; |
| 2535 | } | 2581 | } |
| 2582 | |||
| 2583 | obj_priv = object_list[i]->driver_private; | ||
| 2584 | if (obj_priv->in_execbuffer) { | ||
| 2585 | DRM_ERROR("Object %p appears more than once in object list\n", | ||
| 2586 | object_list[i]); | ||
| 2587 | ret = -EBADF; | ||
| 2588 | goto err; | ||
| 2589 | } | ||
| 2590 | obj_priv->in_execbuffer = true; | ||
| 2536 | } | 2591 | } |
| 2537 | 2592 | ||
| 2538 | /* Pin and relocate */ | 2593 | /* Pin and relocate */ |
| @@ -2674,8 +2729,13 @@ err: | |||
| 2674 | for (i = 0; i < pinned; i++) | 2729 | for (i = 0; i < pinned; i++) |
| 2675 | i915_gem_object_unpin(object_list[i]); | 2730 | i915_gem_object_unpin(object_list[i]); |
| 2676 | 2731 | ||
| 2677 | for (i = 0; i < args->buffer_count; i++) | 2732 | for (i = 0; i < args->buffer_count; i++) { |
| 2733 | if (object_list[i]) { | ||
| 2734 | obj_priv = object_list[i]->driver_private; | ||
| 2735 | obj_priv->in_execbuffer = false; | ||
| 2736 | } | ||
| 2678 | drm_gem_object_unreference(object_list[i]); | 2737 | drm_gem_object_unreference(object_list[i]); |
| 2738 | } | ||
| 2679 | 2739 | ||
| 2680 | mutex_unlock(&dev->struct_mutex); | 2740 | mutex_unlock(&dev->struct_mutex); |
| 2681 | 2741 | ||
| @@ -2712,17 +2772,24 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
| 2712 | ret = i915_gem_object_bind_to_gtt(obj, alignment); | 2772 | ret = i915_gem_object_bind_to_gtt(obj, alignment); |
| 2713 | if (ret != 0) { | 2773 | if (ret != 0) { |
| 2714 | if (ret != -EBUSY && ret != -ERESTARTSYS) | 2774 | if (ret != -EBUSY && ret != -ERESTARTSYS) |
| 2715 | DRM_ERROR("Failure to bind: %d", ret); | 2775 | DRM_ERROR("Failure to bind: %d\n", ret); |
| 2776 | return ret; | ||
| 2777 | } | ||
| 2778 | } | ||
| 2779 | /* | ||
| 2780 | * Pre-965 chips need a fence register set up in order to | ||
| 2781 | * properly handle tiled surfaces. | ||
| 2782 | */ | ||
| 2783 | if (!IS_I965G(dev) && | ||
| 2784 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
| 2785 | obj_priv->tiling_mode != I915_TILING_NONE) { | ||
| 2786 | ret = i915_gem_object_get_fence_reg(obj, true); | ||
| 2787 | if (ret != 0) { | ||
| 2788 | if (ret != -EBUSY && ret != -ERESTARTSYS) | ||
| 2789 | DRM_ERROR("Failure to install fence: %d\n", | ||
| 2790 | ret); | ||
| 2716 | return ret; | 2791 | return ret; |
| 2717 | } | 2792 | } |
| 2718 | /* | ||
| 2719 | * Pre-965 chips need a fence register set up in order to | ||
| 2720 | * properly handle tiled surfaces. | ||
| 2721 | */ | ||
| 2722 | if (!IS_I965G(dev) && | ||
| 2723 | obj_priv->fence_reg == I915_FENCE_REG_NONE && | ||
| 2724 | obj_priv->tiling_mode != I915_TILING_NONE) | ||
| 2725 | i915_gem_object_get_fence_reg(obj, true); | ||
| 2726 | } | 2793 | } |
| 2727 | obj_priv->pin_count++; | 2794 | obj_priv->pin_count++; |
| 2728 | 2795 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d6539a868b3..90600d899413 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -184,6 +184,7 @@ | |||
| 184 | * Fence registers | 184 | * Fence registers |
| 185 | */ | 185 | */ |
| 186 | #define FENCE_REG_830_0 0x2000 | 186 | #define FENCE_REG_830_0 0x2000 |
| 187 | #define FENCE_REG_945_8 0x3000 | ||
| 187 | #define I830_FENCE_START_MASK 0x07f80000 | 188 | #define I830_FENCE_START_MASK 0x07f80000 |
| 188 | #define I830_FENCE_TILING_Y_SHIFT 12 | 189 | #define I830_FENCE_TILING_Y_SHIFT 12 |
| 189 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) | 190 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5d84027ee8f3..d669cc2b42c0 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev) | |||
| 119 | 119 | ||
| 120 | /* VGA color palette registers */ | 120 | /* VGA color palette registers */ |
| 121 | dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); | 121 | dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); |
| 122 | /* DACCRX automatically increments during read */ | ||
| 123 | I915_WRITE8(VGA_DACRX, 0); | ||
| 124 | /* Read 3 bytes of color data from each index */ | ||
| 125 | for (i = 0; i < 256 * 3; i++) | ||
| 126 | dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA); | ||
| 127 | 122 | ||
| 128 | /* MSR bits */ | 123 | /* MSR bits */ |
| 129 | dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); | 124 | dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); |
| @@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev) | |||
| 225 | 220 | ||
| 226 | /* VGA color palette registers */ | 221 | /* VGA color palette registers */ |
| 227 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); | 222 | I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); |
| 228 | /* DACCRX automatically increments during read */ | ||
| 229 | I915_WRITE8(VGA_DACWX, 0); | ||
| 230 | /* Read 3 bytes of color data from each index */ | ||
| 231 | for (i = 0; i < 256 * 3; i++) | ||
| 232 | I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]); | ||
| 233 | |||
| 234 | } | 223 | } |
| 235 | 224 | ||
| 236 | int i915_save_state(struct drm_device *dev) | 225 | int i915_save_state(struct drm_device *dev) |
