aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/2793-drm-amdkfd-Handle-unmapping-of-doorbell-VMAs-correct.patch
blob: fda6d4fcdb6c87dafaf060365973da9219ea7f99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
From 2ac66eb37891b15f0ad0470354669a3e8f0a8396 Mon Sep 17 00:00:00 2001
From: Felix Kuehling <Felix.Kuehling@amd.com>
Date: Wed, 29 May 2019 00:00:35 -0400
Subject: [PATCH 2793/2940] drm/amdkfd: Handle unmapping of doorbell VMAs
 correctly

KFDTest with --gtest_repeat will unmap and map doorbells for each
test. When the doorbells are unmapped, we need to forget the doorbell
VMA. The next time they are mapped, a new VMA is created.

If the process is evicted during unmap, we need to remember that the
doorbells are supposed to be zapped so they can be zapped on the next
map.

Whether or not queues exist shouldn't matter for the purposes of
zapping and remapping doorbells. Only the existence of a VMA matters.

Change-Id: I885f5b386997cfdc5e2f95ae43c9d6f4e13c5d0d
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c | 21 ++++++++++++---------
 drivers/gpu/drm/amd/amdkfd/kfd_process.c  |  9 ++++++++-
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index de5366685535..278bc22edf49 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -128,18 +128,21 @@ void kfd_doorbell_fini(struct kfd_dev *kfd)
 
 static int kfd_doorbell_vm_fault(struct vm_fault *vmf)
 {
-	struct kfd_process *process = vmf->vma->vm_private_data;
-
+	struct kfd_process_device *pdd = vmf->vma->vm_private_data;
 	pr_debug("Process %d doorbell vm page fault\n", process->pasid);
+        if (!pdd)
+                return VM_FAULT_SIGBUS;
 
-	kfd_process_remap_doorbells_locked(process);
-
-	kfd_process_schedule_restore(process);
+        pr_debug("Process %d doorbell vm page fault\n", pdd->process->pasid);
+	kfd_process_remap_doorbells_locked(pdd->process);
 
+	kfd_process_schedule_restore(pdd->process);
 	return VM_FAULT_NOPAGE;
 }
 
 static const struct vm_operations_struct kfd_doorbell_vm_ops = {
+        .open = kfd_doorbell_open,
+        .close = kfd_doorbell_close,
 	.fault = kfd_doorbell_vm_fault,
 };
 
@@ -150,10 +153,10 @@ void kfd_doorbell_unmap_locked(struct kfd_process_device *pdd)
 	size_t size;
 
 	vma = pdd->qpd.doorbell_vma;
-	/* If process is evicted before queue is created
-	 * doorbell is not mapped to user space yet
+	/* Remember if the process was evicted without doorbells
+	 * mapped to user mode.
 	 */
-	if (!vma || !pdd->qpd.queue_count) {
+	if (!vma) {
 		pdd->qpd.doorbell_mapped = -1;
 		return;
 	}
@@ -249,7 +252,7 @@ int kfd_doorbell_mmap(struct kfd_dev *dev, struct kfd_process *process,
 
 	if (!ret && keep_idle_process_evicted) {
 		vma->vm_ops = &kfd_doorbell_vm_ops;
-		vma->vm_private_data = process;
+		vma->vm_private_data = pdd;
 		pdd->qpd.doorbell_vma = vma;
 
 		/* If process is evicted before the first queue is created,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 18fa6c75e97d..6da0f3d8f3e9 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -379,6 +379,7 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
 		kfree(pdd->qpd.doorbell_bitmap);
 		idr_destroy(&pdd->alloc_idr);
 		mutex_destroy(&pdd->qpd.doorbell_lock);
+
 		kfree(pdd);
 	}
 }
@@ -453,11 +454,17 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
 
 	/* Iterate over all process device data structures and if the
 	 * pdd is in debug mode, we should first force unregistration,
-	 * then we will be able to destroy the queues
+	 * then we will be able to destroy the queues. Also invalidate
+	 * doorbell_vma private data because the pdds are about to be
+	 * destroyed, which can race with the kfd_doorbell_close
+	 * vm_ops callback.
 	 */
 	list_for_each_entry(pdd, &p->per_device_data, per_device_list) {
 		struct kfd_dev *dev = pdd->dev;
 
+		if (pdd->qpd.doorbell_vma)
+			pdd->qpd.doorbell_vma->vm_private_data = NULL;
+
 		/* Old (deprecated) debugger for GFXv8 and older */
 		mutex_lock(kfd_get_dbgmgr_mutex());
 		if (dev && dev->dbgmgr && dev->dbgmgr->pasid == p->pasid) {
-- 
2.17.1