diff options
author | Imre Deak <imre.deak@intel.com> | 2013-02-18 12:28:03 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-03-23 07:17:09 -0400 |
commit | 90797e6d1ec0dfde6ba62a48b9ee3803887d6ed4 (patch) | |
tree | 3308e54aca521e530872f80fbb27ca8a7bccfe76 | |
parent | 67d5a50c0480d5d41e0423e6fa55984f9fd3381e (diff) |
drm/i915: create compact dma scatter lists for gem objects
So far we created a sparse dma scatter list for gem objects, where each
scatter list entry represented only a single page. In the future we'll
have to handle compact scatter lists too where each entry can consist of
multiple pages, for example for objects imported through PRIME.
The previous patches have already fixed up all other places where the
i915 driver _walked_ these lists. Here we have the corresponding fix to
_create_ compact lists. It's not a performance or memory footprint
improvement, but it helps to better exercise the new logic.
Reference: http://www.spinics.net/lists/dri-devel/msg33917.html
Signed-off-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 5cf6140354db..8a2cbee491a2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1625,9 +1625,8 @@ i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj) | |||
1625 | static void | 1625 | static void |
1626 | i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) | 1626 | i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) |
1627 | { | 1627 | { |
1628 | int page_count = obj->base.size / PAGE_SIZE; | 1628 | struct sg_page_iter sg_iter; |
1629 | struct scatterlist *sg; | 1629 | int ret; |
1630 | int ret, i; | ||
1631 | 1630 | ||
1632 | BUG_ON(obj->madv == __I915_MADV_PURGED); | 1631 | BUG_ON(obj->madv == __I915_MADV_PURGED); |
1633 | 1632 | ||
@@ -1647,8 +1646,8 @@ i915_gem_object_put_pages_gtt(struct drm_i915_gem_object *obj) | |||
1647 | if (obj->madv == I915_MADV_DONTNEED) | 1646 | if (obj->madv == I915_MADV_DONTNEED) |
1648 | obj->dirty = 0; | 1647 | obj->dirty = 0; |
1649 | 1648 | ||
1650 | for_each_sg(obj->pages->sgl, sg, page_count, i) { | 1649 | for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0) { |
1651 | struct page *page = sg_page(sg); | 1650 | struct page *page = sg_iter.page; |
1652 | 1651 | ||
1653 | if (obj->dirty) | 1652 | if (obj->dirty) |
1654 | set_page_dirty(page); | 1653 | set_page_dirty(page); |
@@ -1749,7 +1748,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
1749 | struct address_space *mapping; | 1748 | struct address_space *mapping; |
1750 | struct sg_table *st; | 1749 | struct sg_table *st; |
1751 | struct scatterlist *sg; | 1750 | struct scatterlist *sg; |
1751 | struct sg_page_iter sg_iter; | ||
1752 | struct page *page; | 1752 | struct page *page; |
1753 | unsigned long last_pfn = 0; /* suppress gcc warning */ | ||
1753 | gfp_t gfp; | 1754 | gfp_t gfp; |
1754 | 1755 | ||
1755 | /* Assert that the object is not currently in any GPU domain. As it | 1756 | /* Assert that the object is not currently in any GPU domain. As it |
@@ -1779,7 +1780,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
1779 | gfp = mapping_gfp_mask(mapping); | 1780 | gfp = mapping_gfp_mask(mapping); |
1780 | gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD; | 1781 | gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD; |
1781 | gfp &= ~(__GFP_IO | __GFP_WAIT); | 1782 | gfp &= ~(__GFP_IO | __GFP_WAIT); |
1782 | for_each_sg(st->sgl, sg, page_count, i) { | 1783 | sg = st->sgl; |
1784 | st->nents = 0; | ||
1785 | for (i = 0; i < page_count; i++) { | ||
1783 | page = shmem_read_mapping_page_gfp(mapping, i, gfp); | 1786 | page = shmem_read_mapping_page_gfp(mapping, i, gfp); |
1784 | if (IS_ERR(page)) { | 1787 | if (IS_ERR(page)) { |
1785 | i915_gem_purge(dev_priv, page_count); | 1788 | i915_gem_purge(dev_priv, page_count); |
@@ -1802,9 +1805,18 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
1802 | gfp &= ~(__GFP_IO | __GFP_WAIT); | 1805 | gfp &= ~(__GFP_IO | __GFP_WAIT); |
1803 | } | 1806 | } |
1804 | 1807 | ||
1805 | sg_set_page(sg, page, PAGE_SIZE, 0); | 1808 | if (!i || page_to_pfn(page) != last_pfn + 1) { |
1809 | if (i) | ||
1810 | sg = sg_next(sg); | ||
1811 | st->nents++; | ||
1812 | sg_set_page(sg, page, PAGE_SIZE, 0); | ||
1813 | } else { | ||
1814 | sg->length += PAGE_SIZE; | ||
1815 | } | ||
1816 | last_pfn = page_to_pfn(page); | ||
1806 | } | 1817 | } |
1807 | 1818 | ||
1819 | sg_mark_end(sg); | ||
1808 | obj->pages = st; | 1820 | obj->pages = st; |
1809 | 1821 | ||
1810 | if (i915_gem_object_needs_bit17_swizzle(obj)) | 1822 | if (i915_gem_object_needs_bit17_swizzle(obj)) |
@@ -1813,8 +1825,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
1813 | return 0; | 1825 | return 0; |
1814 | 1826 | ||
1815 | err_pages: | 1827 | err_pages: |
1816 | for_each_sg(st->sgl, sg, i, page_count) | 1828 | sg_mark_end(sg); |
1817 | page_cache_release(sg_page(sg)); | 1829 | for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) |
1830 | page_cache_release(sg_iter.page); | ||
1818 | sg_free_table(st); | 1831 | sg_free_table(st); |
1819 | kfree(st); | 1832 | kfree(st); |
1820 | return PTR_ERR(page); | 1833 | return PTR_ERR(page); |