aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1604-drm-amdkfd-Fixed-a-kfd-driver-and-FW-sync-issue.patch
blob: fc2d887f8cda4cd09b963e5e649d4195953be0dd (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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
From dd94a9a0309ff7824f975eebd2d7ab4c8c6771f1 Mon Sep 17 00:00:00 2001
From: ozeng <oak.zeng@amd.com>
Date: Fri, 17 Feb 2017 16:48:37 -0600
Subject: [PATCH 1604/4131] drm/amdkfd: Fixed a kfd driver and FW sync issue

In update_queue(), previously mqd is updated by kfd driver
while queue is still mapped to hqd. When queue is mapped,
mqd is owned by FW and clobbered during driver update.

Queue is unmapped first and mapped again after mqd update.

Signed-off-by: Oak Zeng <Oak.Zeng@amd.com>

Change-Id: I27d72750ec3419e91945e240f5637fb974db8b9a
---
 .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c  | 95 ++++++++++++++--------
 1 file changed, 63 insertions(+), 32 deletions(-)

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 fc38dca..d1edbfc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -50,6 +50,8 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
 		enum kfd_unmap_queues_filter filter,
 		uint32_t filter_param, bool reset);
 
+static int map_queues_cpsch(struct device_queue_manager *dqm);
+
 static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm,
 					struct queue *q,
 					struct qcm_process_device *qpd);
@@ -404,6 +406,13 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm,
 	return retval;
 }
 
+static  bool is_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q)
+{
+	return (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS &&
+			(q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
+			q->properties.type == KFD_QUEUE_TYPE_SDMA));
+}
+
 static int update_queue(struct device_queue_manager *dqm, struct queue *q)
 {
 	int retval;
@@ -437,33 +446,45 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
 					    q->properties.queue_address != 0);
 
 	/* save previous activity state for counters */
-	if (q->properties.is_active)
-		prev_active = true;
+	prev_active = q->properties.is_active;
 
+	/* HWS mode, unmap first to own mqd */
+	if (dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS) {
+		retval = unmap_queues_cpsch(dqm,
+				KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
+				false);
+		if (retval != 0) {
+			pr_err("unmap queue failed");
+			goto out_unlock;
+		}
+	} else if (is_queue_nocpsch(dqm, q) && prev_active == true) {
+		retval = mqd->destroy_mqd(mqd, q->mqd,
+				KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN,
+				KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
+		if (retval != 0) {
+			pr_err("destroy mqd failed");
+			goto out_unlock;
+		}
+	}
 
 	retval = mqd->update_mqd(mqd, q->mqd, &q->properties);
-	if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS &&
-	    (q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
-	     q->properties.type == KFD_QUEUE_TYPE_SDMA)) {
+
+	if (is_queue_nocpsch(dqm, q)) {
 		if (q->properties.is_active)
 			retval = mqd->load_mqd(mqd, q->mqd, q->pipe, q->queue,
 					       &q->properties, q->process->mm);
-		else if (prev_active)
-			retval = mqd->destroy_mqd(mqd, q->mqd,
-				KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN,
-				KFD_UNMAP_LATENCY_MS, q->pipe, q->queue);
 	}
 	/*
-		 * check active state vs. the previous state
-		 * and modify counter accordingly
-	*/
+	 * check active state vs. the previous state
+	 * and modify counter accordingly
+	 */
 	if ((q->properties.is_active) && (!prev_active))
 		dqm->queue_count++;
 	else if ((!q->properties.is_active) && (prev_active))
 		dqm->queue_count--;
 
 	if (dqm->sched_policy != KFD_SCHED_POLICY_NO_HWS)
-		retval = execute_queues_cpsch(dqm, false);
+		retval = map_queues_cpsch(dqm);
 
 out_unlock:
 	mutex_unlock(&dqm->lock);
@@ -518,9 +539,7 @@ int process_evict_queues(struct device_queue_manager *dqm,
 			q->properties.is_evicted = true;
 
 		retval = mqd->update_mqd(mqd, q->mqd, &q->properties);
-		if (dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS &&
-		    (q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
-		     q->properties.type == KFD_QUEUE_TYPE_SDMA) &&
+		if (is_queue_nocpsch(dqm, q) &&
 		    q->properties.is_evicted)
 			retval = mqd->destroy_mqd(mqd, q->mqd,
 				KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN,
@@ -1128,6 +1147,31 @@ static int unmap_sdma_queues(struct device_queue_manager *dqm,
 }
 
 /* dqm->lock mutex has to be locked before calling this function */
+static int map_queues_cpsch(struct device_queue_manager *dqm)
+{
+	int retval;
+
+	if (dqm->queue_count <= 0 || dqm->processes_count <= 0) {
+		retval = 0;
+		return retval;
+	}
+
+	if (dqm->active_runlist) {
+		retval = 0;
+		return retval;
+	}
+
+	retval = pm_send_runlist(&dqm->packets, &dqm->queues);
+	if (retval != 0) {
+		pr_err("failed to execute runlist");
+		return retval;
+	}
+	dqm->active_runlist = true;
+
+	return retval;
+}
+
+/* dqm->lock mutex has to be locked before calling this function */
 static int unmap_queues_cpsch(struct device_queue_manager *dqm,
 		enum kfd_unmap_queues_filter filter,
 		uint32_t filter_param, bool reset)
@@ -1180,6 +1224,8 @@ static int execute_queues_cpsch(struct device_queue_manager *dqm,
 
 	BUG_ON(!dqm);
 
+	pr_debug("In function %s\n", __func__);
+
 	filter = static_queues_included ?
 			KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES :
 			KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES;
@@ -1190,22 +1236,7 @@ static int execute_queues_cpsch(struct device_queue_manager *dqm,
 		return retval;
 	}
 
-	if (dqm->queue_count <= 0 || dqm->processes_count <= 0) {
-		retval = 0;
-		return retval;
-	}
-
-	if (dqm->active_runlist) {
-		retval = 0;
-		return retval;
-	}
-
-	retval = pm_send_runlist(&dqm->packets, &dqm->queues);
-	if (retval != 0) {
-		pr_err("kfd: failed to execute runlist");
-		return retval;
-	}
-	dqm->active_runlist = true;
+	retval = map_queues_cpsch(dqm);
 
 	return retval;
 }
-- 
2.7.4