Short summary of fixes pull: * gpuva: Cleanups * kunit: Documentation fixes * nouveau: * UAPI: Avoid implicit NO_PREFETCH flag * Scheduler fixes * Fix remap * ttm: Fix type conversion in tests Signed-off-by: Dave Airlie <airlied@redhat.com>
Unified · Split
| @@ -1076,7 +1076,7 @@ __drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, · 1075 unmodified lines | |||
| 1076 | u64 req_addr, u64 req_range, | 1076 | u64 req_addr, u64 req_range, |
| 1077 | struct drm_gem_object *req_obj, u64 req_offset) | 1077 | struct drm_gem_object *req_obj, u64 req_offset) |
| 1078 | { | 1078 | { |
| 1079 | struct drm_gpuva *va, *next, *prev = NULL; | 1079 | struct drm_gpuva *va, *next; |
| 1080 | u64 req_end = req_addr + req_range; | 1080 | u64 req_end = req_addr + req_range; |
| 1081 | int ret; | 1081 | int ret; |
| 1082 | 1082 | ||
| @@ -1106,7 +1106,7 @@ __drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, · 23 unmodified lines | |||
| 1106 | ret = op_unmap_cb(ops, priv, va, merge); | 1106 | ret = op_unmap_cb(ops, priv, va, merge); |
| 1107 | if (ret) | 1107 | if (ret) |
| 1108 | return ret; | 1108 | return ret; |
| 1109 | goto next; | 1109 | continue; |
| 1110 | } | 1110 | } |
| 1111 | 1111 | ||
| 1112 | if (end > req_end) { | 1112 | if (end > req_end) { |
| @@ -1151,7 +1151,7 @@ __drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, · 38 unmodified lines | |||
| 1151 | ret = op_remap_cb(ops, priv, &p, NULL, &u); | 1151 | ret = op_remap_cb(ops, priv, &p, NULL, &u); |
| 1152 | if (ret) | 1152 | if (ret) |
| 1153 | return ret; | 1153 | return ret; |
| 1154 | goto next; | 1154 | continue; |
| 1155 | } | 1155 | } |
| 1156 | 1156 | ||
| 1157 | if (end > req_end) { | 1157 | if (end > req_end) { |
| @@ -1184,7 +1184,7 @@ __drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, · 26 unmodified lines | |||
| 1184 | ret = op_unmap_cb(ops, priv, va, merge); | 1184 | ret = op_unmap_cb(ops, priv, va, merge); |
| 1185 | if (ret) | 1185 | if (ret) |
| 1186 | return ret; | 1186 | return ret; |
| 1187 | goto next; | 1187 | continue; |
| 1188 | } | 1188 | } |
| 1189 | 1189 | ||
| 1190 | if (end > req_end) { | 1190 | if (end > req_end) { |
| @@ -1205,8 +1205,6 @@ __drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, · 14 unmodified lines | |||
| 1205 | break; | 1205 | break; |
| 1206 | } | 1206 | } |
| 1207 | } | 1207 | } |
| 1208 | next: | ||
| 1209 | prev = va; | ||
| 1210 | } | 1208 | } |
| 1211 | 1209 | ||
| 1212 | return op_map_cb(ops, priv, | 1210 | return op_map_cb(ops, priv, |
| @@ -69,16 +69,19 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) · 68 unmodified lines | |||
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void | 71 | void |
| 72 | nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length) | 72 | nv50_dma_push(struct nouveau_channel *chan, u64 offset, u32 length, |
| 73 | bool no_prefetch) | ||
| 73 | { | 74 | { |
| 74 | struct nvif_user *user = &chan->drm->client.device.user; | 75 | struct nvif_user *user = &chan->drm->client.device.user; |
| 75 | struct nouveau_bo *pb = chan->push.buffer; | 76 | struct nouveau_bo *pb = chan->push.buffer; |
| 76 | int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; | 77 | int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; |
| 77 | 78 | ||
| 78 | BUG_ON(chan->dma.ib_free < 1); | 79 | BUG_ON(chan->dma.ib_free < 1); |
| 80 | WARN_ON(length > NV50_DMA_PUSH_MAX_LENGTH); | ||
| 79 | 81 | ||
| 80 | nouveau_bo_wr32(pb, ip++, lower_32_bits(offset)); | 82 | nouveau_bo_wr32(pb, ip++, lower_32_bits(offset)); |
| 81 | nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8); | 83 | nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8 | |
| 84 | (no_prefetch ? (1 << 31) : 0)); | ||
| 82 | 85 | ||
| 83 | chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max; | 86 | chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max; |
| 84 | 87 | ||
| @@ -31,7 +31,8 @@ · 30 unmodified lines | |||
| 31 | #include "nouveau_chan.h" | 31 | #include "nouveau_chan.h" |
| 32 | 32 | ||
| 33 | int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); | 33 | int nouveau_dma_wait(struct nouveau_channel *, int slots, int size); |
| 34 | void nv50_dma_push(struct nouveau_channel *, u64 addr, int length); | 34 | void nv50_dma_push(struct nouveau_channel *, u64 addr, u32 length, |
| 35 | bool no_prefetch); | ||
| 35 | 36 | ||
| 36 | /* | 37 | /* |
| 37 | * There's a hw race condition where you can't jump to your PUT offset, | 38 | * There's a hw race condition where you can't jump to your PUT offset, |
| @@ -45,6 +46,9 @@ void nv50_dma_push(struct nouveau_channel *, u64 addr, int length); · 7 unmodified lines | |||
| 45 | */ | 46 | */ |
| 46 | #define NOUVEAU_DMA_SKIPS (128 / 4) | 47 | #define NOUVEAU_DMA_SKIPS (128 / 4) |
| 47 | 48 | ||
| 49 | /* Maximum push buffer size. */ | ||
| 50 | #define NV50_DMA_PUSH_MAX_LENGTH 0x7fffff | ||
| 51 | |||
| 48 | /* Object handles - for stuff that's doesn't use handle == oclass. */ | 52 | /* Object handles - for stuff that's doesn't use handle == oclass. */ |
| 49 | enum { | 53 | enum { |
| 50 | NvDmaFB = 0x80000002, | 54 | NvDmaFB = 0x80000002, |
| @@ -89,7 +93,7 @@ FIRE_RING(struct nouveau_channel *chan) · 38 unmodified lines | |||
| 89 | 93 | ||
| 90 | if (chan->dma.ib_max) { | 94 | if (chan->dma.ib_max) { |
| 91 | nv50_dma_push(chan, chan->push.addr + (chan->dma.put << 2), | 95 | nv50_dma_push(chan, chan->push.addr + (chan->dma.put << 2), |
| 92 | (chan->dma.cur - chan->dma.put) << 2); | 96 | (chan->dma.cur - chan->dma.put) << 2, false); |
| 93 | } else { | 97 | } else { |
| 94 | WRITE_PUT(chan->dma.cur); | 98 | WRITE_PUT(chan->dma.cur); |
| 95 | } | 99 | } |
| @@ -164,8 +164,10 @@ nouveau_exec_job_run(struct nouveau_job *job) · 163 unmodified lines | |||
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | for (i = 0; i < exec_job->push.count; i++) { | 166 | for (i = 0; i < exec_job->push.count; i++) { |
| 167 | nv50_dma_push(chan, exec_job->push.s[i].va, | 167 | struct drm_nouveau_exec_push *p = &exec_job->push.s[i]; |
| 168 | exec_job->push.s[i].va_len); | 168 | bool no_prefetch = p->flags & DRM_NOUVEAU_EXEC_PUSH_NO_PREFETCH; |
| 169 | |||
| 170 | nv50_dma_push(chan, p->va, p->va_len, no_prefetch); | ||
| 169 | } | 171 | } |
| 170 | 172 | ||
| 171 | ret = nouveau_fence_emit(fence, chan); | 173 | ret = nouveau_fence_emit(fence, chan); |
| @@ -223,7 +225,18 @@ nouveau_exec_job_init(struct nouveau_exec_job **pjob, · 51 unmodified lines | |||
| 223 | { | 225 | { |
| 224 | struct nouveau_exec_job *job; | 226 | struct nouveau_exec_job *job; |
| 225 | struct nouveau_job_args args = {}; | 227 | struct nouveau_job_args args = {}; |
| 226 | int ret; | 228 | int i, ret; |
| 229 | |||
| 230 | for (i = 0; i < __args->push.count; i++) { | ||
| 231 | struct drm_nouveau_exec_push *p = &__args->push.s[i]; | ||
| 232 | |||
| 233 | if (unlikely(p->va_len > NV50_DMA_PUSH_MAX_LENGTH)) { | ||
| 234 | NV_PRINTK(err, nouveau_cli(__args->file_priv), | ||
| 235 | "pushbuf size exceeds limit: 0x%x max 0x%x\n", | ||
| 236 | p->va_len, NV50_DMA_PUSH_MAX_LENGTH); | ||
| 237 | return -EINVAL; | ||
| 238 | } | ||
| 239 | } | ||
| 227 | 240 | ||
| 228 | job = *pjob = kzalloc(sizeof(*job), GFP_KERNEL); | 241 | job = *pjob = kzalloc(sizeof(*job), GFP_KERNEL); |
| 229 | if (!job) | 242 | if (!job) |
| @@ -856,9 +856,11 @@ revalidate: · 855 unmodified lines | |||
| 856 | for (i = 0; i < req->nr_push; i++) { | 856 | for (i = 0; i < req->nr_push; i++) { |
| 857 | struct nouveau_vma *vma = (void *)(unsigned long) | 857 | struct nouveau_vma *vma = (void *)(unsigned long) |
| 858 | bo[push[i].bo_index].user_priv; | 858 | bo[push[i].bo_index].user_priv; |
| 859 | u64 addr = vma->addr + push[i].offset; | ||
| 860 | u32 length = push[i].length & ~NOUVEAU_GEM_PUSHBUF_NO_PREFETCH; | ||
| 861 | bool no_prefetch = push[i].length & NOUVEAU_GEM_PUSHBUF_NO_PREFETCH; | ||
| 859 | 862 | ||
| 860 | nv50_dma_push(chan, vma->addr + push[i].offset, | 863 | nv50_dma_push(chan, addr, length, no_prefetch); |
| 861 | push[i].length); | ||
| 862 | } | 864 | } |
| 863 | } else | 865 | } else |
| 864 | if (drm->client.device.info.chipset >= 0x25) { | 866 | if (drm->client.device.info.chipset >= 0x25) { |
| @@ -292,6 +292,28 @@ nouveau_job_submit(struct nouveau_job *job) · 291 unmodified lines | |||
| 292 | if (job->sync) | 292 | if (job->sync) |
| 293 | done_fence = dma_fence_get(job->done_fence); | 293 | done_fence = dma_fence_get(job->done_fence); |
| 294 | 294 | ||
| 295 | /* If a sched job depends on a dma-fence from a job from the same GPU | ||
| 296 | * scheduler instance, but a different scheduler entity, the GPU | ||
| 297 | * scheduler does only wait for the particular job to be scheduled, | ||
| 298 | * rather than for the job to fully complete. This is due to the GPU | ||
| 299 | * scheduler assuming that there is a scheduler instance per ring. | ||
| 300 | * However, the current implementation, in order to avoid arbitrary | ||
| 301 | * amounts of kthreads, has a single scheduler instance while scheduler | ||
| 302 | * entities represent rings. | ||
| 303 | * | ||
| 304 | * As a workaround, set the DRM_SCHED_FENCE_DONT_PIPELINE for all | ||
| 305 | * out-fences in order to force the scheduler to wait for full job | ||
| 306 | * completion for dependent jobs from different entities and same | ||
| 307 | * scheduler instance. | ||
| 308 | * | ||
| 309 | * There is some work in progress [1] to address the issues of firmware | ||
| 310 | * schedulers; once it is in-tree the scheduler topology in Nouveau | ||
| 311 | * should be re-worked accordingly. | ||
| 312 | * | ||
| 313 | * [1] https://lore.kernel.org/dri-devel/20230801205103.627779-1-matthew.brost@intel.com/ | ||
| 314 | */ | ||
| 315 | set_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &job->done_fence->flags); | ||
| 316 | |||
| 295 | if (job->ops->armed_submit) | 317 | if (job->ops->armed_submit) |
| 296 | job->ops->armed_submit(job); | 318 | job->ops->armed_submit(job); |
| 297 | 319 | ||
| @@ -639,6 +639,7 @@ nouveau_uvmm_sm_prepare(struct nouveau_uvmm *uvmm, · 638 unmodified lines | |||
| 639 | struct drm_gpuva *va = r->unmap->va; | 639 | struct drm_gpuva *va = r->unmap->va; |
| 640 | struct uvmm_map_args remap_args = { | 640 | struct uvmm_map_args remap_args = { |
| 641 | .kind = uvma_from_va(va)->kind, | 641 | .kind = uvma_from_va(va)->kind, |
| 642 | .region = uvma_from_va(va)->region, | ||
| 642 | }; | 643 | }; |
| 643 | u64 ustart = va->va.addr; | 644 | u64 ustart = va->va.addr; |
| 644 | u64 urange = va->va.range; | 645 | u64 urange = va->va.range; |
| @@ -156,7 +156,7 @@ static void action_drm_release_context(void *ptr) · 155 unmodified lines | |||
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | /** | 158 | /** |
| 159 | * drm_kunit_helper_context_alloc - Allocates an acquire context | 159 | * drm_kunit_helper_acquire_ctx_alloc - Allocates an acquire context |
| 160 | * @test: The test context object | 160 | * @test: The test context object |
| 161 | * | 161 | * |
| 162 | * Allocates and initializes a modeset acquire context. | 162 | * Allocates and initializes a modeset acquire context. |
| @@ -228,8 +228,8 @@ static void ttm_pool_alloc_basic_dma_addr(struct kunit *test) · 227 unmodified lines | |||
| 228 | dma1 = tt->dma_address[0]; | 228 | dma1 = tt->dma_address[0]; |
| 229 | dma2 = tt->dma_address[tt->num_pages - 1]; | 229 | dma2 = tt->dma_address[tt->num_pages - 1]; |
| 230 | 230 | ||
| 231 | KUNIT_ASSERT_NOT_NULL(test, (void *)dma1); | 231 | KUNIT_ASSERT_NOT_NULL(test, (void *)(uintptr_t)dma1); |
| 232 | KUNIT_ASSERT_NOT_NULL(test, (void *)dma2); | 232 | KUNIT_ASSERT_NOT_NULL(test, (void *)(uintptr_t)dma2); |
| 233 | 233 | ||
| 234 | ttm_pool_free(pool, tt); | 234 | ttm_pool_free(pool, tt); |
| 235 | ttm_tt_fini(tt); | 235 | ttm_tt_fini(tt); |
| @@ -138,6 +138,7 @@ struct drm_nouveau_gem_pushbuf_push { · 137 unmodified lines | |||
| 138 | __u32 pad; | 138 | __u32 pad; |
| 139 | __u64 offset; | 139 | __u64 offset; |
| 140 | __u64 length; | 140 | __u64 length; |
| 141 | #define NOUVEAU_GEM_PUSHBUF_NO_PREFETCH (1 << 23) | ||
| 141 | }; | 142 | }; |
| 142 | 143 | ||
| 143 | struct drm_nouveau_gem_pushbuf { | 144 | struct drm_nouveau_gem_pushbuf { |
| @@ -338,7 +339,12 @@ struct drm_nouveau_exec_push { · 194 unmodified lines | |||
| 338 | /** | 339 | /** |
| 339 | * @va_len: the length of the push buffer mapping | 340 | * @va_len: the length of the push buffer mapping |
| 340 | */ | 341 | */ |
| 341 | __u64 va_len; | 342 | __u32 va_len; |
| 343 | /** | ||
| 344 | * @flags: the flags for this push buffer mapping | ||
| 345 | */ | ||
| 346 | __u32 flags; | ||
| 347 | #define DRM_NOUVEAU_EXEC_PUSH_NO_PREFETCH 0x1 | ||
| 342 | }; | 348 | }; |
| 343 | 349 | ||
| 344 | /** | 350 | /** |