aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/files/0417-drm-amdgpu-add-invalidate_page-callback-for-userptrs.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/files/0417-drm-amdgpu-add-invalidate_page-callback-for-userptrs.patch')
-rw-r--r--common/recipes-kernel/linux/files/0417-drm-amdgpu-add-invalidate_page-callback-for-userptrs.patch147
1 files changed, 147 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/files/0417-drm-amdgpu-add-invalidate_page-callback-for-userptrs.patch b/common/recipes-kernel/linux/files/0417-drm-amdgpu-add-invalidate_page-callback-for-userptrs.patch
new file mode 100644
index 00000000..c89b9592
--- /dev/null
+++ b/common/recipes-kernel/linux/files/0417-drm-amdgpu-add-invalidate_page-callback-for-userptrs.patch
@@ -0,0 +1,147 @@
+From e3eacee1dc6e60e7197872ccd0dd3d4468c417d6 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 18 Mar 2016 19:29:52 +0100
+Subject: [PATCH 0417/1110] drm/amdgpu: add invalidate_page callback for
+ userptrs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Otherwise we can run into problems with the writeback code.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 98 +++++++++++++++++++++++++---------
+ 1 file changed, 72 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+index c47f222..9f4a45c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+@@ -106,6 +106,76 @@ static void amdgpu_mn_release(struct mmu_notifier *mn,
+ }
+
+ /**
++ * amdgpu_mn_invalidate_node - unmap all BOs of a node
++ *
++ * @node: the node with the BOs to unmap
++ *
++ * We block for all BOs and unmap them by move them
++ * into system domain again.
++ */
++static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node,
++ unsigned long start,
++ unsigned long end)
++{
++ struct amdgpu_bo *bo;
++ long r;
++
++ list_for_each_entry(bo, &node->bos, mn_list) {
++
++ if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end))
++ continue;
++
++ r = amdgpu_bo_reserve(bo, true);
++ if (r) {
++ DRM_ERROR("(%ld) failed to reserve user bo\n", r);
++ continue;
++ }
++
++ r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
++ true, false, MAX_SCHEDULE_TIMEOUT);
++ if (r <= 0)
++ DRM_ERROR("(%ld) failed to wait for user bo\n", r);
++
++ amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
++ r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
++ if (r)
++ DRM_ERROR("(%ld) failed to validate user bo\n", r);
++
++ amdgpu_bo_unreserve(bo);
++ }
++}
++
++/**
++ * amdgpu_mn_invalidate_page - callback to notify about mm change
++ *
++ * @mn: our notifier
++ * @mn: the mm this callback is about
++ * @address: address of invalidate page
++ *
++ * Invalidation of a single page. Blocks for all BOs mapping it
++ * and unmap them by move them into system domain again.
++ */
++static void amdgpu_mn_invalidate_page(struct mmu_notifier *mn,
++ struct mm_struct *mm,
++ unsigned long address)
++{
++ struct amdgpu_mn *rmn = container_of(mn, struct amdgpu_mn, mn);
++ struct interval_tree_node *it;
++
++ mutex_lock(&rmn->lock);
++
++ it = interval_tree_iter_first(&rmn->objects, address, address);
++ if (it) {
++ struct amdgpu_mn_node *node;
++
++ node = container_of(it, struct amdgpu_mn_node, it);
++ amdgpu_mn_invalidate_node(node, address, address);
++ }
++
++ mutex_unlock(&rmn->lock);
++}
++
++/**
+ * amdgpu_mn_invalidate_range_start - callback to notify about mm change
+ *
+ * @mn: our notifier
+@@ -132,36 +202,11 @@ static void amdgpu_mn_invalidate_range_start(struct mmu_notifier *mn,
+ it = interval_tree_iter_first(&rmn->objects, start, end);
+ while (it) {
+ struct amdgpu_mn_node *node;
+- struct amdgpu_bo *bo;
+- long r;
+
+ node = container_of(it, struct amdgpu_mn_node, it);
+ it = interval_tree_iter_next(it, start, end);
+
+- list_for_each_entry(bo, &node->bos, mn_list) {
+-
+- if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start,
+- end))
+- continue;
+-
+- r = amdgpu_bo_reserve(bo, true);
+- if (r) {
+- DRM_ERROR("(%ld) failed to reserve user bo\n", r);
+- continue;
+- }
+-
+- r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
+- true, false, MAX_SCHEDULE_TIMEOUT);
+- if (r <= 0)
+- DRM_ERROR("(%ld) failed to wait for user bo\n", r);
+-
+- amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
+- r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+- if (r)
+- DRM_ERROR("(%ld) failed to validate user bo\n", r);
+-
+- amdgpu_bo_unreserve(bo);
+- }
++ amdgpu_mn_invalidate_node(node, start, end);
+ }
+
+ mutex_unlock(&rmn->lock);
+@@ -169,6 +214,7 @@ static void amdgpu_mn_invalidate_range_start(struct mmu_notifier *mn,
+
+ static const struct mmu_notifier_ops amdgpu_mn_ops = {
+ .release = amdgpu_mn_release,
++ .invalidate_page = amdgpu_mn_invalidate_page,
+ .invalidate_range_start = amdgpu_mn_invalidate_range_start,
+ };
+
+--
+2.7.4
+