From 982722eb88db16f065495556f9e0109059850556 Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Tue, 15 Aug 2023 17:12:01 +0200 Subject: [PATCH] nv50: fix code uploads bigger than 0x10000 bytes The hardware has a max limit on how much data we can upload in one go via the 2D engine. Just split the uploads up. Cc: mesa-stable Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9571 Acked-by: M Henning Signed-off-by: Karol Herbst Part-of: (cherry picked from commit 7f63d2ebdbc4c29a58c768787e0551e8a6bd411b) --- .pick_status.json | 2 +- .../drivers/nouveau/nv50/nv50_transfer.c | 75 +++++++++++-------- 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 847decfa04e..aea5508882d 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -22,7 +22,7 @@ "description": "nv50: fix code uploads bigger than 0x10000 bytes", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c index 4c73695a28d..5a9a5bacaae 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_transfer.c @@ -279,47 +279,56 @@ nv50_sifc_linear_u8(struct nouveau_context *nv, struct nv50_context *nv50 = nv50_context(&nv->pipe); struct nouveau_pushbuf *push = nv50->base.pushbuf; uint32_t *src = (uint32_t *)data; - unsigned count = (size + 3) / 4; - unsigned xcoord = offset & 0xff; + unsigned count = DIV_ROUND_UP(size, 4); + unsigned max_size = 0x10000; nouveau_bufctx_refn(nv50->bufctx, 0, dst, domain | NOUVEAU_BO_WR); nouveau_pushbuf_bufctx(push, nv50->bufctx); + PUSH_VAL(push); - offset &= ~0xff; - - BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); - PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); - PUSH_DATA (push, 1); - BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); - PUSH_DATA (push, 262144); - PUSH_DATA (push, 65536); - PUSH_DATA (push, 1); - PUSH_DATAh(push, dst->offset + offset); - PUSH_DATA (push, dst->offset + offset); - BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); - PUSH_DATA (push, 0); - PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); - BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); - PUSH_DATA (push, size); - PUSH_DATA (push, 1); - PUSH_DATA (push, 0); - PUSH_DATA (push, 1); - PUSH_DATA (push, 0); - PUSH_DATA (push, 1); - PUSH_DATA (push, 0); - PUSH_DATA (push, xcoord); - PUSH_DATA (push, 0); - PUSH_DATA (push, 0); - while (count) { - unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); + unsigned xcoord = offset & 0xff; + offset &= ~0xff; - BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr); - PUSH_DATAp(push, src, nr); + BEGIN_NV04(push, NV50_2D(DST_FORMAT), 2); + PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); + PUSH_DATA (push, 1); + BEGIN_NV04(push, NV50_2D(DST_PITCH), 5); + PUSH_DATA (push, 262144); + PUSH_DATA (push, 65536); + PUSH_DATA (push, 1); + PUSH_DATAh(push, dst->offset + offset); + PUSH_DATA (push, dst->offset + offset); + BEGIN_NV04(push, NV50_2D(SIFC_BITMAP_ENABLE), 2); + PUSH_DATA (push, 0); + PUSH_DATA (push, G80_SURFACE_FORMAT_R8_UNORM); + BEGIN_NV04(push, NV50_2D(SIFC_WIDTH), 10); + PUSH_DATA (push, MIN2(size, max_size)); + PUSH_DATA (push, 1); + PUSH_DATA (push, 0); + PUSH_DATA (push, 1); + PUSH_DATA (push, 0); + PUSH_DATA (push, 1); + PUSH_DATA (push, 0); + PUSH_DATA (push, xcoord); + PUSH_DATA (push, 0); + PUSH_DATA (push, 0); - src += nr; - count -= nr; + unsigned iter_count = MIN2(count, max_size / 4); + count -= iter_count; + offset += max_size; + size -= max_size; + + while (iter_count) { + unsigned nr = MIN2(iter_count, NV04_PFIFO_MAX_PACKET_LEN); + + BEGIN_NI04(push, NV50_2D(SIFC_DATA), nr); + PUSH_DATAp(push, src, nr); + + src += nr; + iter_count -= nr; + } } nouveau_bufctx_reset(nv50->bufctx, 0);