aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c151
1 files changed, 139 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3471dece13e7..666d75570502 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1588,6 +1588,13 @@ i915_gem_process_flushing_list(struct drm_device *dev,
1588 } 1588 }
1589} 1589}
1590 1590
1591#define PIPE_CONTROL_FLUSH(addr) \
1592 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE | \
1593 PIPE_CONTROL_DEPTH_STALL); \
1594 OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT); \
1595 OUT_RING(0); \
1596 OUT_RING(0); \
1597
1591/** 1598/**
1592 * Creates a new sequence number, emitting a write of it to the status page 1599 * Creates a new sequence number, emitting a write of it to the status page
1593 * plus an interrupt, which will trigger i915_user_interrupt_handler. 1600 * plus an interrupt, which will trigger i915_user_interrupt_handler.
@@ -1622,13 +1629,47 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
1622 if (dev_priv->mm.next_gem_seqno == 0) 1629 if (dev_priv->mm.next_gem_seqno == 0)
1623 dev_priv->mm.next_gem_seqno++; 1630 dev_priv->mm.next_gem_seqno++;
1624 1631
1625 BEGIN_LP_RING(4); 1632 if (HAS_PIPE_CONTROL(dev)) {
1626 OUT_RING(MI_STORE_DWORD_INDEX); 1633 u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
1627 OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
1628 OUT_RING(seqno);
1629 1634
1630 OUT_RING(MI_USER_INTERRUPT); 1635 /*
1631 ADVANCE_LP_RING(); 1636 * Workaround qword write incoherence by flushing the
1637 * PIPE_NOTIFY buffers out to memory before requesting
1638 * an interrupt.
1639 */
1640 BEGIN_LP_RING(32);
1641 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
1642 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
1643 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
1644 OUT_RING(seqno);
1645 OUT_RING(0);
1646 PIPE_CONTROL_FLUSH(scratch_addr);
1647 scratch_addr += 128; /* write to separate cachelines */
1648 PIPE_CONTROL_FLUSH(scratch_addr);
1649 scratch_addr += 128;
1650 PIPE_CONTROL_FLUSH(scratch_addr);
1651 scratch_addr += 128;
1652 PIPE_CONTROL_FLUSH(scratch_addr);
1653 scratch_addr += 128;
1654 PIPE_CONTROL_FLUSH(scratch_addr);
1655 scratch_addr += 128;
1656 PIPE_CONTROL_FLUSH(scratch_addr);
1657 OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
1658 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
1659 PIPE_CONTROL_NOTIFY);
1660 OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
1661 OUT_RING(seqno);
1662 OUT_RING(0);
1663 ADVANCE_LP_RING();
1664 } else {
1665 BEGIN_LP_RING(4);
1666 OUT_RING(MI_STORE_DWORD_INDEX);
1667 OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
1668 OUT_RING(seqno);
1669
1670 OUT_RING(MI_USER_INTERRUPT);
1671 ADVANCE_LP_RING();
1672 }
1632 1673
1633 DRM_DEBUG_DRIVER("%d\n", seqno); 1674 DRM_DEBUG_DRIVER("%d\n", seqno);
1634 1675
@@ -1752,7 +1793,10 @@ i915_get_gem_seqno(struct drm_device *dev)
1752{ 1793{
1753 drm_i915_private_t *dev_priv = dev->dev_private; 1794 drm_i915_private_t *dev_priv = dev->dev_private;
1754 1795
1755 return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX); 1796 if (HAS_PIPE_CONTROL(dev))
1797 return ((volatile u32 *)(dev_priv->seqno_page))[0];
1798 else
1799 return READ_HWSP(dev_priv, I915_GEM_HWS_INDEX);
1756} 1800}
1757 1801
1758/** 1802/**
@@ -2362,6 +2406,12 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
2362 pitch_val = obj_priv->stride / tile_width; 2406 pitch_val = obj_priv->stride / tile_width;
2363 pitch_val = ffs(pitch_val) - 1; 2407 pitch_val = ffs(pitch_val) - 1;
2364 2408
2409 if (obj_priv->tiling_mode == I915_TILING_Y &&
2410 HAS_128_BYTE_Y_TILING(dev))
2411 WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL);
2412 else
2413 WARN_ON(pitch_val > I915_FENCE_MAX_PITCH_VAL);
2414
2365 val = obj_priv->gtt_offset; 2415 val = obj_priv->gtt_offset;
2366 if (obj_priv->tiling_mode == I915_TILING_Y) 2416 if (obj_priv->tiling_mode == I915_TILING_Y)
2367 val |= 1 << I830_FENCE_TILING_Y_SHIFT; 2417 val |= 1 << I830_FENCE_TILING_Y_SHIFT;
@@ -4554,6 +4604,49 @@ i915_gem_idle(struct drm_device *dev)
4554 return 0; 4604 return 0;
4555} 4605}
4556 4606
4607/*
4608 * 965+ support PIPE_CONTROL commands, which provide finer grained control
4609 * over cache flushing.
4610 */
4611static int
4612i915_gem_init_pipe_control(struct drm_device *dev)
4613{
4614 drm_i915_private_t *dev_priv = dev->dev_private;
4615 struct drm_gem_object *obj;
4616 struct drm_i915_gem_object *obj_priv;
4617 int ret;
4618
4619 obj = i915_gem_alloc_object(dev, 4096);
4620 if (obj == NULL) {
4621 DRM_ERROR("Failed to allocate seqno page\n");
4622 ret = -ENOMEM;
4623 goto err;
4624 }
4625 obj_priv = to_intel_bo(obj);
4626 obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
4627
4628 ret = i915_gem_object_pin(obj, 4096);
4629 if (ret)
4630 goto err_unref;
4631
4632 dev_priv->seqno_gfx_addr = obj_priv->gtt_offset;
4633 dev_priv->seqno_page = kmap(obj_priv->pages[0]);
4634 if (dev_priv->seqno_page == NULL)
4635 goto err_unpin;
4636
4637 dev_priv->seqno_obj = obj;
4638 memset(dev_priv->seqno_page, 0, PAGE_SIZE);
4639
4640 return 0;
4641
4642err_unpin:
4643 i915_gem_object_unpin(obj);
4644err_unref:
4645 drm_gem_object_unreference(obj);
4646err:
4647 return ret;
4648}
4649
4557static int 4650static int
4558i915_gem_init_hws(struct drm_device *dev) 4651i915_gem_init_hws(struct drm_device *dev)
4559{ 4652{
@@ -4571,7 +4664,8 @@ i915_gem_init_hws(struct drm_device *dev)
4571 obj = i915_gem_alloc_object(dev, 4096); 4664 obj = i915_gem_alloc_object(dev, 4096);
4572 if (obj == NULL) { 4665 if (obj == NULL) {
4573 DRM_ERROR("Failed to allocate status page\n"); 4666 DRM_ERROR("Failed to allocate status page\n");
4574 return -ENOMEM; 4667 ret = -ENOMEM;
4668 goto err;
4575 } 4669 }
4576 obj_priv = to_intel_bo(obj); 4670 obj_priv = to_intel_bo(obj);
4577 obj_priv->agp_type = AGP_USER_CACHED_MEMORY; 4671 obj_priv->agp_type = AGP_USER_CACHED_MEMORY;
@@ -4579,7 +4673,7 @@ i915_gem_init_hws(struct drm_device *dev)
4579 ret = i915_gem_object_pin(obj, 4096); 4673 ret = i915_gem_object_pin(obj, 4096);
4580 if (ret != 0) { 4674 if (ret != 0) {
4581 drm_gem_object_unreference(obj); 4675 drm_gem_object_unreference(obj);
4582 return ret; 4676 goto err_unref;
4583 } 4677 }
4584 4678
4585 dev_priv->status_gfx_addr = obj_priv->gtt_offset; 4679 dev_priv->status_gfx_addr = obj_priv->gtt_offset;
@@ -4588,10 +4682,16 @@ i915_gem_init_hws(struct drm_device *dev)
4588 if (dev_priv->hw_status_page == NULL) { 4682 if (dev_priv->hw_status_page == NULL) {
4589 DRM_ERROR("Failed to map status page.\n"); 4683 DRM_ERROR("Failed to map status page.\n");
4590 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); 4684 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
4591 i915_gem_object_unpin(obj); 4685 ret = -EINVAL;
4592 drm_gem_object_unreference(obj); 4686 goto err_unpin;
4593 return -EINVAL;
4594 } 4687 }
4688
4689 if (HAS_PIPE_CONTROL(dev)) {
4690 ret = i915_gem_init_pipe_control(dev);
4691 if (ret)
4692 goto err_unpin;
4693 }
4694
4595 dev_priv->hws_obj = obj; 4695 dev_priv->hws_obj = obj;
4596 memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 4696 memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
4597 if (IS_GEN6(dev)) { 4697 if (IS_GEN6(dev)) {
@@ -4604,6 +4704,30 @@ i915_gem_init_hws(struct drm_device *dev)
4604 DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr); 4704 DRM_DEBUG_DRIVER("hws offset: 0x%08x\n", dev_priv->status_gfx_addr);
4605 4705
4606 return 0; 4706 return 0;
4707
4708err_unpin:
4709 i915_gem_object_unpin(obj);
4710err_unref:
4711 drm_gem_object_unreference(obj);
4712err:
4713 return 0;
4714}
4715
4716static void
4717i915_gem_cleanup_pipe_control(struct drm_device *dev)
4718{
4719 drm_i915_private_t *dev_priv = dev->dev_private;
4720 struct drm_gem_object *obj;
4721 struct drm_i915_gem_object *obj_priv;
4722
4723 obj = dev_priv->seqno_obj;
4724 obj_priv = to_intel_bo(obj);
4725 kunmap(obj_priv->pages[0]);
4726 i915_gem_object_unpin(obj);
4727 drm_gem_object_unreference(obj);
4728 dev_priv->seqno_obj = NULL;
4729
4730 dev_priv->seqno_page = NULL;
4607} 4731}
4608 4732
4609static void 4733static void
@@ -4627,6 +4751,9 @@ i915_gem_cleanup_hws(struct drm_device *dev)
4627 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map)); 4751 memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
4628 dev_priv->hw_status_page = NULL; 4752 dev_priv->hw_status_page = NULL;
4629 4753
4754 if (HAS_PIPE_CONTROL(dev))
4755 i915_gem_cleanup_pipe_control(dev);
4756
4630 /* Write high address into HWS_PGA when disabling. */ 4757 /* Write high address into HWS_PGA when disabling. */
4631 I915_WRITE(HWS_PGA, 0x1ffff000); 4758 I915_WRITE(HWS_PGA, 0x1ffff000);
4632} 4759}