drm/i915: Protect WC stash allocation against direct reclaim

"Linux Kernel Mailing List" <[email protected]>
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/124804c4c4b2e84e956cedd17878562e230a907f
Commit:     124804c4c4b2e84e956cedd17878562e230a907f
Parent:     c5bd1fc9a6c843c85a5cea5765cdc997f832df3c
Refname:    refs/heads/master
Author:     Chris Wilson <[email protected]>
AuthorDate: Sun Jan 21 17:31:43 2018 +0000
Committer:  Rodrigo Vivi <[email protected]>
CommitDate: Thu Feb 1 07:32:46 2018 -0800

    drm/i915: Protect WC stash allocation against direct reclaim
    
    As we attempt to allocate pages for use in a new WC stash, direct
    reclaim may run underneath us and fill up the WC stash. We have to be
    careful then not to overflow the pvec.
    
    Fixes: 66df1014efba ("drm/i915: Keep a small stash of preallocated WC pages")
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103109
    Signed-off-by: Chris Wilson <[email protected]>
    Cc: Matthew Auld <[email protected]>
    Cc: Joonas Lahtinen <[email protected]>
    Reviewed-by: Matthew Auld <[email protected]>
    Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
    (cherry picked from commit 073cd7816685ac77c6d8b4d321a5586c9177b76a)
    Signed-off-by: Rodrigo Vivi <[email protected]>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 0de4f3f13fc4..133cb9590003 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -377,6 +377,7 @@ static gen6_pte_t iris_pte_encode(dma_addr_t addr,
 static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp)
 {
 	struct pagevec *pvec = &vm->free_pages;
+	struct pagevec stash;
 
 	if (I915_SELFTEST_ONLY(should_fail(&vm->fault_attr, 1)))
 		i915_gem_shrink_all(vm->i915);
@@ -395,7 +396,15 @@ static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp)
 	if (likely(pvec->nr))
 		return pvec->pages[--pvec->nr];
 
-	/* Otherwise batch allocate pages to amoritize cost of set_pages_wc. */
+	/*
+	 * Otherwise batch allocate pages to amoritize cost of set_pages_wc.
+	 *
+	 * We have to be careful as page allocation may trigger the shrinker
+	 * (via direct reclaim) which will fill up the WC stash underneath us.
+	 * So we add our WB pages into a temporary pvec on the stack and merge
+	 * them into the WC stash after all the allocations are complete.
+	 */
+	pagevec_init(&stash);
 	do {
 		struct page *page;
 
@@ -403,15 +412,24 @@ static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp)
 		if (unlikely(!page))
 			break;
 
-		pvec->pages[pvec->nr++] = page;
-	} while (pagevec_space(pvec));
+		stash.pages[stash.nr++] = page;
+	} while (stash.nr < pagevec_space(pvec));
 
-	if (unlikely(!pvec->nr))
-		return NULL;
+	if (stash.nr) {
+		int nr = min_t(int, stash.nr, pagevec_space(pvec));
+		struct page **pages = stash.pages + stash.nr - nr;
 
-	set_pages_array_wc(pvec->pages, pvec->nr);
+		if (nr && !set_pages_array_wc(pages, nr)) {
+			memcpy(pvec->pages + pvec->nr,
+			       pages, sizeof(pages[0]) * nr);
+			pvec->nr += nr;
+			stash.nr -= nr;
+		}
+
+		pagevec_release(&stash);
+	}
 
-	return pvec->pages[--pvec->nr];
+	return likely(pvec->nr) ? pvec->pages[--pvec->nr] : NULL;
 }
 
 static void vm_free_pages_release(struct i915_address_space *vm,
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.