aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1499-drm-amd-Simplify-SDMA-HQD-loading-in-kernel-threads.patch
blob: 8671234c366b72e644b7ff7e18436afc28786495 (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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
From 9c8870b8587c2de80f8d4981e65dd4cc67c3500f Mon Sep 17 00:00:00 2001
From: Felix Kuehling <Felix.Kuehling@amd.com>
Date: Thu, 1 Sep 2016 21:11:39 -0400
Subject: [PATCH 1499/4131] drm/amd: Simplify SDMA HQD loading in kernel
 threads

Use the use_mm function to temporarily access a user process context
while running in a kernel thread. This avoids the need to lock the
mmap_sem, which fixes a circular locking problem observed with user
pointers while running without the HW scheduler.

Change-Id: I4e74f3b021277e09df55dddf81ae5e070032b599
Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c  | 26 ++++++++++++----------
 drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c  | 24 +++++++++++---------
 drivers/gpu/drm/amd/amdkfd/kfd_device.c            |  9 +-------
 .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c  |  4 ----
 4 files changed, 28 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
index 9948b37..22c4b7a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
@@ -23,6 +23,7 @@
 #include <linux/fdtable.h>
 #include <linux/uaccess.h>
 #include <linux/firmware.h>
+#include <linux/mmu_context.h>
 #include <drm/drmP.h>
 #include "amdgpu.h"
 #include "amdgpu_amdkfd.h"
@@ -528,18 +529,19 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
         WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, m->sdma_rlc_doorbell);
         WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdma_rlc_rb_rptr);
 
-        if (mm && mm == current->mm)
-                wptr_valid = !get_user(data, wptr);
-        else if (mm) {
-                struct vm_area_struct *vma;
-
-                vma = find_vma(mm, (unsigned long)wptr);
-                if (vma && vma->vm_start <= (unsigned long)wptr &&
-                    vma->vm_ops && vma->vm_ops->access)
-                        wptr_valid = (sizeof(data) == vma->vm_ops->access(
-                                              vma, (unsigned long)wptr,
-                                              &data, sizeof(data), 0));
-        }
+        if (mm) {
+                if (mm == current->mm) {
+                        /* Running in the correct user process context */
+                        wptr_valid = !get_user(data, wptr);
+                } else if (current->mm == NULL) {
+                        /* A kernel thread can temporarily use a user
+                         * process context for AIO
+                         */
+                        use_mm(mm);
+                        wptr_valid = !get_user(data, wptr);
+                        unuse_mm(mm);
+                }
+
         if (wptr_valid)
                 WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, data);
         else
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
index 56a88ef..7be32f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
@@ -24,6 +24,7 @@
 #include <linux/fdtable.h>
 #include <linux/uaccess.h>
 #include <linux/firmware.h>
+#include <linux/mmu_context.h>
 #include <drm/drmP.h>
 #include "amdgpu.h"
 #include "amdgpu_amdkfd.h"
@@ -524,17 +525,18 @@ static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd,
 	WREG32(sdma_base_addr + mmSDMA0_RLC0_DOORBELL, m->sdmax_rlcx_doorbell);
 	WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_RPTR, m->sdmax_rlcx_rb_rptr);
 
-	if (mm && mm == current->mm)
-		wptr_valid = !get_user(data, wptr);
-	else if (mm) {
-		struct vm_area_struct *vma;
-
-		vma = find_vma(mm, (unsigned long)wptr);
-		if (vma && vma->vm_start <= (unsigned long)wptr &&
-		    vma->vm_ops && vma->vm_ops->access)
-			wptr_valid = (sizeof(data) == vma->vm_ops->access(
-					      vma, (unsigned long)wptr,
-					      &data, sizeof(data), 0));
+	if (mm) {
+		if (mm == current->mm) {
+			/* Running in the correct user process context */
+			wptr_valid = !get_user(data, wptr);
+		} else if (current->mm == NULL) {
+			/* A kernel thread can temporarily use a user
+			 * process context for AIO
+			 */
+			use_mm(mm);
+			wptr_valid = !get_user(data, wptr);
+			unuse_mm(mm);
+		}
 	}
 	if (wptr_valid)
 		WREG32(sdma_base_addr + mmSDMA0_RLC0_RB_WPTR, data);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 69b08a9..a47d7f1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -738,16 +738,9 @@ int kgd2kfd_resume_mm(struct kfd_dev *kfd, struct mm_struct *mm)
 
 	r = -ENODEV;
 	pdd = kfd_get_process_device_data(kfd, p);
-	if (pdd) {
-		if (kfd->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
-			down_read(&mm->mmap_sem);
-
+	if (pdd)
 		r = process_restore_queues(kfd->dqm, &pdd->qpd);
 
-		if (kfd->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
-			up_read(&mm->mmap_sem);
-	}
-
 	kfd_unref_process(p);
 	return r;
 }
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index 53fef02..d77c1ad 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -408,8 +408,6 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
 
 	BUG_ON(!dqm || !q || !q->mqd);
 
-	if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
-		down_read(&current->mm->mmap_sem);
 	mutex_lock(&dqm->lock);
 
 	pdd = kfd_get_process_device_data(q->device, q->process);
@@ -465,8 +463,6 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
 
 out_unlock:
 	mutex_unlock(&dqm->lock);
-	if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS)
-		up_read(&current->mm->mmap_sem);
 
 	return retval;
 }
-- 
2.7.4