forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
....@@ -1,14 +1,5 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /* Copyright (c) 2017 The Linux Foundation. All rights reserved.
2
- *
3
- * This program is free software; you can redistribute it and/or modify
4
- * it under the terms of the GNU General Public License version 2 and
5
- * only version 2 as published by the Free Software Foundation.
6
- *
7
- * This program is distributed in the hope that it will be useful,
8
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
- * GNU General Public License for more details.
11
- *
123 */
134
145 #include "msm_gem.h"
....@@ -54,9 +45,9 @@
5445 if (!ring)
5546 return;
5647
57
- spin_lock_irqsave(&ring->lock, flags);
48
+ spin_lock_irqsave(&ring->preempt_lock, flags);
5849 wptr = get_wptr(ring);
59
- spin_unlock_irqrestore(&ring->lock, flags);
50
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
6051
6152 gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr);
6253 }
....@@ -71,9 +62,9 @@
7162 bool empty;
7263 struct msm_ringbuffer *ring = gpu->rb[i];
7364
74
- spin_lock_irqsave(&ring->lock, flags);
75
- empty = (get_wptr(ring) == ring->memptrs->rptr);
76
- spin_unlock_irqrestore(&ring->lock, flags);
65
+ spin_lock_irqsave(&ring->preempt_lock, flags);
66
+ empty = (get_wptr(ring) == gpu->funcs->get_rptr(gpu, ring));
67
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
7768
7869 if (!empty)
7970 return ring;
....@@ -92,7 +83,7 @@
9283 if (!try_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED))
9384 return;
9485
95
- dev_err(dev->dev, "%s: preemption timed out\n", gpu->name);
86
+ DRM_DEV_ERROR(dev->dev, "%s: preemption timed out\n", gpu->name);
9687 queue_work(priv->wq, &gpu->recover_work);
9788 }
9889
....@@ -141,9 +132,9 @@
141132 }
142133
143134 /* Make sure the wptr doesn't update while we're in motion */
144
- spin_lock_irqsave(&ring->lock, flags);
135
+ spin_lock_irqsave(&ring->preempt_lock, flags);
145136 a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring);
146
- spin_unlock_irqrestore(&ring->lock, flags);
137
+ spin_unlock_irqrestore(&ring->preempt_lock, flags);
147138
148139 /* Set the address of the incoming preemption record */
149140 gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO,
....@@ -188,7 +179,7 @@
188179 status = gpu_read(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL);
189180 if (unlikely(status)) {
190181 set_preempt_state(a5xx_gpu, PREEMPT_FAULTED);
191
- dev_err(dev->dev, "%s: Preemption failed to complete\n",
182
+ DRM_DEV_ERROR(dev->dev, "%s: Preemption failed to complete\n",
192183 gpu->name);
193184 queue_work(priv->wq, &gpu->recover_work);
194185 return;
....@@ -208,10 +199,18 @@
208199 struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
209200 int i;
210201
202
+ /* Always come up on rb 0 */
203
+ a5xx_gpu->cur_ring = gpu->rb[0];
204
+
205
+ /* No preemption if we only have one ring */
206
+ if (gpu->nr_rings == 1)
207
+ return;
208
+
211209 for (i = 0; i < gpu->nr_rings; i++) {
212210 a5xx_gpu->preempt[i]->wptr = 0;
213211 a5xx_gpu->preempt[i]->rptr = 0;
214212 a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova;
213
+ a5xx_gpu->preempt[i]->rptr_addr = shadowptr(a5xx_gpu, gpu->rb[i]);
215214 }
216215
217216 /* Write a 0 to signal that we aren't switching pagetables */
....@@ -220,9 +219,6 @@
220219
221220 /* Reset the preemption state */
222221 set_preempt_state(a5xx_gpu, PREEMPT_NONE);
223
-
224
- /* Always come up on rb 0 */
225
- a5xx_gpu->cur_ring = gpu->rb[0];
226222 }
227223
228224 static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
....@@ -231,17 +227,31 @@
231227 struct adreno_gpu *adreno_gpu = &a5xx_gpu->base;
232228 struct msm_gpu *gpu = &adreno_gpu->base;
233229 struct a5xx_preempt_record *ptr;
234
- struct drm_gem_object *bo = NULL;
235
- u64 iova = 0;
230
+ void *counters;
231
+ struct drm_gem_object *bo = NULL, *counters_bo = NULL;
232
+ u64 iova = 0, counters_iova = 0;
236233
237234 ptr = msm_gem_kernel_new(gpu->dev,
238235 A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE,
239
- MSM_BO_UNCACHED, gpu->aspace, &bo, &iova);
236
+ MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova);
240237
241238 if (IS_ERR(ptr))
242239 return PTR_ERR(ptr);
243240
241
+ /* The buffer to store counters needs to be unprivileged */
242
+ counters = msm_gem_kernel_new(gpu->dev,
243
+ A5XX_PREEMPT_COUNTER_SIZE,
244
+ MSM_BO_UNCACHED, gpu->aspace, &counters_bo, &counters_iova);
245
+ if (IS_ERR(counters)) {
246
+ msm_gem_kernel_put(bo, gpu->aspace, true);
247
+ return PTR_ERR(counters);
248
+ }
249
+
250
+ msm_gem_object_set_name(bo, "preempt");
251
+ msm_gem_object_set_name(counters_bo, "preempt_counters");
252
+
244253 a5xx_gpu->preempt_bo[ring->id] = bo;
254
+ a5xx_gpu->preempt_counters_bo[ring->id] = counters_bo;
245255 a5xx_gpu->preempt_iova[ring->id] = iova;
246256 a5xx_gpu->preempt[ring->id] = ptr;
247257
....@@ -250,9 +260,9 @@
250260 ptr->magic = A5XX_PREEMPT_RECORD_MAGIC;
251261 ptr->info = 0;
252262 ptr->data = 0;
253
- ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT;
254
- ptr->rptr_addr = rbmemptr(ring, rptr);
255
- ptr->counter = iova + A5XX_PREEMPT_RECORD_SIZE;
263
+ ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE;
264
+
265
+ ptr->counter = counters_iova;
256266
257267 return 0;
258268 }
....@@ -264,16 +274,9 @@
264274 int i;
265275
266276 for (i = 0; i < gpu->nr_rings; i++) {
267
- if (!a5xx_gpu->preempt_bo[i])
268
- continue;
269
-
270
- msm_gem_put_vaddr(a5xx_gpu->preempt_bo[i]);
271
-
272
- if (a5xx_gpu->preempt_iova[i])
273
- msm_gem_put_iova(a5xx_gpu->preempt_bo[i], gpu->aspace);
274
-
275
- drm_gem_object_unreference(a5xx_gpu->preempt_bo[i]);
276
- a5xx_gpu->preempt_bo[i] = NULL;
277
+ msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace, true);
278
+ msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i],
279
+ gpu->aspace, true);
277280 }
278281 }
279282