aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorThomas Daniel <thomas.daniel@intel.com>2014-11-13 05:28:56 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-11-19 13:56:44 -0500
commit7ba717cf365d79f2b284e508205ec3d4a05fc41b (patch)
tree99d5b23a67d1a5381b50356d9c1135687e0e997f /drivers/gpu/drm/i915/intel_ringbuffer.c
parentdcb4c12a687710ab745c2cdee8298c3e97f6f707 (diff)
drm/i915/bdw: Pin the ringbuffer backing object to GGTT on-demand
Same as with the context, pinning to GGTT regardless is harmful (it badly fragments the GGTT and can even exhaust it). Unfortunately, this case is also more complex than the previous one because we need to map and access the ringbuffer in several places along the execbuffer path (and we cannot make do by leaving the default ringbuffer pinned, as before). Also, the context object itself contains a pointer to the ringbuffer address that we have to keep updated if we are going to allow the ringbuffer to move around. v2: Same as with the context pinning, we cannot really do it during an interrupt. Also, pin the default ringbuffers objects regardless (makes error capture a lot easier). v3: Rebased. Take a pin reference of the ringbuffer for each item in the execlist request queue because the hardware may still be using the ringbuffer after the MI_USER_INTERRUPT to notify the seqno update is executed. The ringbuffer must remain pinned until the context save is complete. No longer pin and unpin ringbuffer in populate_lr_context() - this transient address is meaningless and the pinning can cause a sleep while atomic. v4: Moved ringbuffer pin and unpin into the lr_context_pin functions. Downgraded pinning check BUG_ONs to WARN_ONs. v5: Reinstated WARN_ONs for unexpected execlist states. Removed unused variable. Issue: VIZ-4277 Signed-off-by: Oscar Mateo <oscar.mateo@intel.com> Signed-off-by: Thomas Daniel <thomas.daniel@intel.com> Reviewed-by: Akash Goel <akash.goels@gmail.com> Reviewed-by: Deepak S<deepak.s@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c85
1 files changed, 50 insertions, 35 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index ae092589ea0c..0a4f35e735c3 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1722,13 +1722,42 @@ static int init_phys_status_page(struct intel_engine_cs *ring)
1722 return 0; 1722 return 0;
1723} 1723}
1724 1724
1725void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) 1725void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
1726{ 1726{
1727 if (!ringbuf->obj)
1728 return;
1729
1730 iounmap(ringbuf->virtual_start); 1727 iounmap(ringbuf->virtual_start);
1728 ringbuf->virtual_start = NULL;
1731 i915_gem_object_ggtt_unpin(ringbuf->obj); 1729 i915_gem_object_ggtt_unpin(ringbuf->obj);
1730}
1731
1732int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
1733 struct intel_ringbuffer *ringbuf)
1734{
1735 struct drm_i915_private *dev_priv = to_i915(dev);
1736 struct drm_i915_gem_object *obj = ringbuf->obj;
1737 int ret;
1738
1739 ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
1740 if (ret)
1741 return ret;
1742
1743 ret = i915_gem_object_set_to_gtt_domain(obj, true);
1744 if (ret) {
1745 i915_gem_object_ggtt_unpin(obj);
1746 return ret;
1747 }
1748
1749 ringbuf->virtual_start = ioremap_wc(dev_priv->gtt.mappable_base +
1750 i915_gem_obj_ggtt_offset(obj), ringbuf->size);
1751 if (ringbuf->virtual_start == NULL) {
1752 i915_gem_object_ggtt_unpin(obj);
1753 return -EINVAL;
1754 }
1755
1756 return 0;
1757}
1758
1759void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
1760{
1732 drm_gem_object_unreference(&ringbuf->obj->base); 1761 drm_gem_object_unreference(&ringbuf->obj->base);
1733 ringbuf->obj = NULL; 1762 ringbuf->obj = NULL;
1734} 1763}
@@ -1736,12 +1765,7 @@ void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
1736int intel_alloc_ringbuffer_obj(struct drm_device *dev, 1765int intel_alloc_ringbuffer_obj(struct drm_device *dev,
1737 struct intel_ringbuffer *ringbuf) 1766 struct intel_ringbuffer *ringbuf)
1738{ 1767{
1739 struct drm_i915_private *dev_priv = to_i915(dev);
1740 struct drm_i915_gem_object *obj; 1768 struct drm_i915_gem_object *obj;
1741 int ret;
1742
1743 if (ringbuf->obj)
1744 return 0;
1745 1769
1746 obj = NULL; 1770 obj = NULL;
1747 if (!HAS_LLC(dev)) 1771 if (!HAS_LLC(dev))
@@ -1754,30 +1778,9 @@ int intel_alloc_ringbuffer_obj(struct drm_device *dev,
1754 /* mark ring buffers as read-only from GPU side by default */ 1778 /* mark ring buffers as read-only from GPU side by default */
1755 obj->gt_ro = 1; 1779 obj->gt_ro = 1;
1756 1780
1757 ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
1758 if (ret)
1759 goto err_unref;
1760
1761 ret = i915_gem_object_set_to_gtt_domain(obj, true);
1762 if (ret)
1763 goto err_unpin;
1764
1765 ringbuf->virtual_start =
1766 ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
1767 ringbuf->size);
1768 if (ringbuf->virtual_start == NULL) {
1769 ret = -EINVAL;
1770 goto err_unpin;
1771 }
1772
1773 ringbuf->obj = obj; 1781 ringbuf->obj = obj;
1774 return 0;
1775 1782
1776err_unpin: 1783 return 0;
1777 i915_gem_object_ggtt_unpin(obj);
1778err_unref:
1779 drm_gem_object_unreference(&obj->base);
1780 return ret;
1781} 1784}
1782 1785
1783static int intel_init_ring_buffer(struct drm_device *dev, 1786static int intel_init_ring_buffer(struct drm_device *dev,
@@ -1814,10 +1817,21 @@ static int intel_init_ring_buffer(struct drm_device *dev,
1814 goto error; 1817 goto error;
1815 } 1818 }
1816 1819
1817 ret = intel_alloc_ringbuffer_obj(dev, ringbuf); 1820 if (ringbuf->obj == NULL) {
1818 if (ret) { 1821 ret = intel_alloc_ringbuffer_obj(dev, ringbuf);
1819 DRM_ERROR("Failed to allocate ringbuffer %s: %d\n", ring->name, ret); 1822 if (ret) {
1820 goto error; 1823 DRM_ERROR("Failed to allocate ringbuffer %s: %d\n",
1824 ring->name, ret);
1825 goto error;
1826 }
1827
1828 ret = intel_pin_and_map_ringbuffer_obj(dev, ringbuf);
1829 if (ret) {
1830 DRM_ERROR("Failed to pin and map ringbuffer %s: %d\n",
1831 ring->name, ret);
1832 intel_destroy_ringbuffer_obj(ringbuf);
1833 goto error;
1834 }
1821 } 1835 }
1822 1836
1823 /* Workaround an erratum on the i830 which causes a hang if 1837 /* Workaround an erratum on the i830 which causes a hang if
@@ -1858,6 +1872,7 @@ void intel_cleanup_ring_buffer(struct intel_engine_cs *ring)
1858 intel_stop_ring_buffer(ring); 1872 intel_stop_ring_buffer(ring);
1859 WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0); 1873 WARN_ON(!IS_GEN2(ring->dev) && (I915_READ_MODE(ring) & MODE_IDLE) == 0);
1860 1874
1875 intel_unpin_ringbuffer_obj(ringbuf);
1861 intel_destroy_ringbuffer_obj(ringbuf); 1876 intel_destroy_ringbuffer_obj(ringbuf);
1862 ring->preallocated_lazy_request = NULL; 1877 ring->preallocated_lazy_request = NULL;
1863 ring->outstanding_lazy_seqno = 0; 1878 ring->outstanding_lazy_seqno = 0;