hc
2024-05-10 61598093bbdd283a7edc367d900f223070ead8d2
kernel/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
....@@ -1,22 +1,17 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2015 Etnaviv Project
3
- *
4
- * This program is free software; you can redistribute it and/or modify it
5
- * under the terms of the GNU General Public License version 2 as published by
6
- * the Free Software Foundation.
7
- *
8
- * This program is distributed in the hope that it will be useful, but WITHOUT
9
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11
- * more details.
12
- *
13
- * You should have received a copy of the GNU General Public License along with
14
- * this program. If not, see <http://www.gnu.org/licenses/>.
154 */
165
6
+#include <drm/drm_file.h>
177 #include <linux/dma-fence-array.h>
18
-#include <linux/reservation.h>
8
+#include <linux/file.h>
9
+#include <linux/pm_runtime.h>
10
+#include <linux/dma-resv.h>
1911 #include <linux/sync_file.h>
12
+#include <linux/uaccess.h>
13
+#include <linux/vmalloc.h>
14
+
2015 #include "etnaviv_cmdbuf.h"
2116 #include "etnaviv_drv.h"
2217 #include "etnaviv_gpu.h"
....@@ -77,6 +72,14 @@
7772 }
7873
7974 submit->bos[i].flags = bo->flags;
75
+ if (submit->flags & ETNA_SUBMIT_SOFTPIN) {
76
+ if (bo->presumed < ETNAVIV_SOFTPIN_START_ADDRESS) {
77
+ DRM_ERROR("invalid softpin address\n");
78
+ ret = -EINVAL;
79
+ goto out_unlock;
80
+ }
81
+ submit->bos[i].va = bo->presumed;
82
+ }
8083
8184 /* normally use drm_gem_object_lookup(), but for bulk lookup
8285 * all under single table_lock just hit object_idr directly:
....@@ -108,9 +111,9 @@
108111 static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i)
109112 {
110113 if (submit->bos[i].flags & BO_LOCKED) {
111
- struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
114
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
112115
113
- ww_mutex_unlock(&etnaviv_obj->resv->lock);
116
+ dma_resv_unlock(obj->resv);
114117 submit->bos[i].flags &= ~BO_LOCKED;
115118 }
116119 }
....@@ -122,7 +125,7 @@
122125
123126 retry:
124127 for (i = 0; i < submit->nr_bos; i++) {
125
- struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
128
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
126129
127130 if (slow_locked == i)
128131 slow_locked = -1;
....@@ -130,8 +133,7 @@
130133 contended = i;
131134
132135 if (!(submit->bos[i].flags & BO_LOCKED)) {
133
- ret = ww_mutex_lock_interruptible(&etnaviv_obj->resv->lock,
134
- ticket);
136
+ ret = dma_resv_lock_interruptible(obj->resv, ticket);
135137 if (ret == -EALREADY)
136138 DRM_ERROR("BO at index %u already on submit list\n",
137139 i);
....@@ -153,13 +155,12 @@
153155 submit_unlock_object(submit, slow_locked);
154156
155157 if (ret == -EDEADLK) {
156
- struct etnaviv_gem_object *etnaviv_obj;
158
+ struct drm_gem_object *obj;
157159
158
- etnaviv_obj = submit->bos[contended].obj;
160
+ obj = &submit->bos[contended].obj->base;
159161
160162 /* we lost out in a seqno race, lock and retry.. */
161
- ret = ww_mutex_lock_slow_interruptible(&etnaviv_obj->resv->lock,
162
- ticket);
163
+ ret = dma_resv_lock_slow_interruptible(obj->resv, ticket);
163164 if (!ret) {
164165 submit->bos[contended].flags |= BO_LOCKED;
165166 slow_locked = contended;
....@@ -176,10 +177,10 @@
176177
177178 for (i = 0; i < submit->nr_bos; i++) {
178179 struct etnaviv_gem_submit_bo *bo = &submit->bos[i];
179
- struct reservation_object *robj = bo->obj->resv;
180
+ struct dma_resv *robj = bo->obj->base.resv;
180181
181182 if (!(bo->flags & ETNA_SUBMIT_BO_WRITE)) {
182
- ret = reservation_object_reserve_shared(robj);
183
+ ret = dma_resv_reserve_shared(robj, 1);
183184 if (ret)
184185 return ret;
185186 }
....@@ -188,13 +189,13 @@
188189 continue;
189190
190191 if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
191
- ret = reservation_object_get_fences_rcu(robj, &bo->excl,
192
+ ret = dma_resv_get_fences_rcu(robj, &bo->excl,
192193 &bo->nr_shared,
193194 &bo->shared);
194195 if (ret)
195196 return ret;
196197 } else {
197
- bo->excl = reservation_object_get_excl_rcu(robj);
198
+ bo->excl = dma_resv_get_excl_rcu(robj);
198199 }
199200
200201 }
....@@ -207,13 +208,13 @@
207208 int i;
208209
209210 for (i = 0; i < submit->nr_bos; i++) {
210
- struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
211
+ struct drm_gem_object *obj = &submit->bos[i].obj->base;
211212
212213 if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE)
213
- reservation_object_add_excl_fence(etnaviv_obj->resv,
214
+ dma_resv_add_excl_fence(obj->resv,
214215 submit->out_fence);
215216 else
216
- reservation_object_add_shared_fence(etnaviv_obj->resv,
217
+ dma_resv_add_shared_fence(obj->resv,
217218 submit->out_fence);
218219
219220 submit_unlock_object(submit, i);
....@@ -229,11 +230,19 @@
229230 struct etnaviv_vram_mapping *mapping;
230231
231232 mapping = etnaviv_gem_mapping_get(&etnaviv_obj->base,
232
- submit->gpu);
233
+ submit->mmu_context,
234
+ submit->bos[i].va);
233235 if (IS_ERR(mapping)) {
234236 ret = PTR_ERR(mapping);
235237 break;
236238 }
239
+
240
+ if ((submit->flags & ETNA_SUBMIT_SOFTPIN) &&
241
+ submit->bos[i].va != mapping->iova) {
242
+ etnaviv_gem_mapping_unreference(mapping);
243
+ return -EINVAL;
244
+ }
245
+
237246 atomic_inc(&etnaviv_obj->gpu_active);
238247
239248 submit->bos[i].flags |= BO_PINNED;
....@@ -265,6 +274,10 @@
265274 u32 i, last_offset = 0;
266275 u32 *ptr = stream;
267276 int ret;
277
+
278
+ /* Submits using softpin don't blend with relocs */
279
+ if ((submit->flags & ETNA_SUBMIT_SOFTPIN) && nr_relocs != 0)
280
+ return -EINVAL;
268281
269282 for (i = 0; i < nr_relocs; i++) {
270283 const struct drm_etnaviv_gem_submit_reloc *r = relocs + i;
....@@ -366,6 +379,12 @@
366379 if (submit->cmdbuf.suballoc)
367380 etnaviv_cmdbuf_free(&submit->cmdbuf);
368381
382
+ if (submit->mmu_context)
383
+ etnaviv_iommu_context_put(submit->mmu_context);
384
+
385
+ if (submit->prev_mmu_context)
386
+ etnaviv_iommu_context_put(submit->prev_mmu_context);
387
+
369388 for (i = 0; i < submit->nr_bos; i++) {
370389 struct etnaviv_gem_object *etnaviv_obj = submit->bos[i].obj;
371390
....@@ -379,7 +398,7 @@
379398
380399 /* if the GPU submit failed, objects might still be locked */
381400 submit_unlock_object(submit, i);
382
- drm_gem_object_put_unlocked(&etnaviv_obj->base);
401
+ drm_gem_object_put(&etnaviv_obj->base);
383402 }
384403
385404 wake_up_all(&submit->gpu->fence_event);
....@@ -441,6 +460,12 @@
441460
442461 if (args->flags & ~ETNA_SUBMIT_FLAGS) {
443462 DRM_ERROR("invalid flags: 0x%x\n", args->flags);
463
+ return -EINVAL;
464
+ }
465
+
466
+ if ((args->flags & ETNA_SUBMIT_SOFTPIN) &&
467
+ priv->mmu_global->version != ETNAVIV_IOMMU_V2) {
468
+ DRM_ERROR("softpin requested on incompatible MMU\n");
444469 return -EINVAL;
445470 }
446471
....@@ -507,12 +532,13 @@
507532 goto err_submit_ww_acquire;
508533 }
509534
510
- ret = etnaviv_cmdbuf_init(gpu->cmdbuf_suballoc, &submit->cmdbuf,
535
+ ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf,
511536 ALIGN(args->stream_size, 8) + 8);
512537 if (ret)
513538 goto err_submit_objects;
514539
515
- submit->cmdbuf.ctx = file->driver_priv;
540
+ submit->ctx = file->driver_priv;
541
+ submit->mmu_context = etnaviv_iommu_context_get(submit->ctx->mmu);
516542 submit->exec_state = args->exec_state;
517543 submit->flags = args->flags;
518544
....@@ -520,7 +546,8 @@
520546 if (ret)
521547 goto err_submit_objects;
522548
523
- if (!etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4,
549
+ if ((priv->mmu_global->version != ETNAVIV_IOMMU_V2) &&
550
+ !etnaviv_cmd_validate_one(gpu, stream, args->stream_size / 4,
524551 relocs, args->nr_relocs)) {
525552 ret = -EINVAL;
526553 goto err_submit_objects;