Skip to content

Commit 862450a

Browse files
Ben Skeggsairlied
authored andcommitted
drm/nouveau/gf100-: track chan progress with non-WFI semaphore release
From VOLTA_CHANNEL_GPFIFO_A onwards, HW no longer updates the GET/GP_GET pointers in USERD following channel progress, but instead updates on a timer for compatibility, and SW is expected to implement its own method of tracking channel progress (typically via non-WFI semaphore release). Nouveau has been making use of the compatibility mode up until now, however, from BLACKWELL_CHANNEL_GPFIFO_A HW no longer supports USERD writeback at all. Allocate a per-channel buffer in system memory, and append a non-WFI semaphore release to the end of each push buffer segment to simulate the pointers previously read from USERD. This change is implemented for Fermi (which is the first to support non- WFI semaphore release) onwards, as readback from system memory is likely faster than BAR1 reads. Signed-off-by: Ben Skeggs <[email protected]> Reviewed-by: Dave Airlie <[email protected]> Reviewed-by: Timur Tabi <[email protected]> Tested-by: Timur Tabi <[email protected]> Signed-off-by: Dave Airlie <[email protected]>
1 parent d1fb887 commit 862450a

File tree

12 files changed

+245
-18
lines changed

12 files changed

+245
-18
lines changed

drivers/gpu/drm/nouveau/include/nvif/chan.h

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ struct nvif_chan {
1717
void (*push)(struct nvif_chan *, bool main, u64 addr, u32 size,
1818
bool no_prefetch);
1919
void (*kick)(struct nvif_chan *);
20+
int (*post)(struct nvif_chan *, u32 gpptr, u32 pbptr);
21+
u32 post_size;
2022
} gpfifo;
23+
24+
struct {
25+
int (*release)(struct nvif_chan *, u64 addr, u32 data);
26+
} sem;
2127
} *func;
2228

2329
struct {
@@ -31,6 +37,11 @@ struct nvif_chan {
3137
int free;
3238
} gpfifo;
3339

40+
struct {
41+
struct nvif_map map;
42+
u64 addr;
43+
} sema;
44+
3445
struct nvif_push push;
3546

3647
struct nvif_user *usermode;
@@ -43,14 +54,23 @@ void nvif_chan_gpfifo_ctor(const struct nvif_chan_func *, void *userd, void *gpf
4354
void *push, u64 push_addr, u32 push_size, struct nvif_chan *);
4455
int nvif_chan_gpfifo_wait(struct nvif_chan *, u32 gpfifo_nr, u32 push_nr);
4556
void nvif_chan_gpfifo_push(struct nvif_chan *, u64 addr, u32 size, bool no_prefetch);
57+
int nvif_chan_gpfifo_post(struct nvif_chan *);
4658

47-
int nvif_chan506f_ctor(struct nvif_chan *, void *userd, void *gpfifo, u32 gpfifo_size,
48-
void *push, u64 push_addr, u32 push_size);
49-
u32 nvif_chan506f_read_get(struct nvif_chan *);
50-
u32 nvif_chan506f_gpfifo_read_get(struct nvif_chan *);
5159
void nvif_chan506f_gpfifo_push(struct nvif_chan *, bool main, u64 addr, u32 size, bool no_prefetch);
60+
void nvif_chan506f_gpfifo_kick(struct nvif_chan *);
61+
62+
int nvif_chan906f_ctor_(const struct nvif_chan_func *, void *userd, void *gpfifo, u32 gpfifo_size,
63+
void *push, u64 push_addr, u32 push_size, void *sema, u64 sema_addr,
64+
struct nvif_chan *);
65+
u32 nvif_chan906f_read_get(struct nvif_chan *);
66+
u32 nvif_chan906f_gpfifo_read_get(struct nvif_chan *);
67+
int nvif_chan906f_gpfifo_post(struct nvif_chan *, u32 gpptr, u32 pbptr);
5268

69+
int nvif_chan506f_ctor(struct nvif_chan *, void *userd, void *gpfifo, u32 gpfifo_size,
70+
void *push, u64 push_addr, u32 push_size);
71+
int nvif_chan906f_ctor(struct nvif_chan *, void *userd, void *gpfifo, u32 gpfifo_size,
72+
void *push, u64 push_addr, u32 push_size, void *sema, u64 sema_addr);
5373
int nvif_chanc36f_ctor(struct nvif_chan *, void *userd, void *gpfifo, u32 gpfifo_size,
54-
void *push, u64 push_addr, u32 push_size,
74+
void *push, u64 push_addr, u32 push_size, void *sema, u64 sema_addr,
5575
struct nvif_user *usermode, u32 doorbell_token);
5676
#endif

drivers/gpu/drm/nouveau/nouveau_bo.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,28 @@ nouveau_bo_new_map(struct nouveau_cli *cli, u32 domain, u32 size, struct nouveau
456456
return 0;
457457
}
458458

459+
int
460+
nouveau_bo_new_map_gpu(struct nouveau_cli *cli, u32 domain, u32 size,
461+
struct nouveau_bo **pnvbo, struct nouveau_vma **pvma)
462+
{
463+
struct nouveau_vmm *vmm = nouveau_cli_vmm(cli);
464+
struct nouveau_bo *nvbo;
465+
int ret;
466+
467+
ret = nouveau_bo_new_map(cli, domain, size, &nvbo);
468+
if (ret)
469+
return ret;
470+
471+
ret = nouveau_vma_new(nvbo, vmm, pvma);
472+
if (ret) {
473+
nouveau_bo_unpin_del(&nvbo);
474+
return ret;
475+
}
476+
477+
*pnvbo = nvbo;
478+
return 0;
479+
}
480+
459481
static void
460482
set_placement_range(struct nouveau_bo *nvbo, uint32_t domain)
461483
{

drivers/gpu/drm/nouveau/nouveau_bo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ void nouveau_bo_del_io_reserve_lru(struct ttm_buffer_object *bo);
9292

9393
int nouveau_bo_new_pin(struct nouveau_cli *, u32 domain, u32 size, struct nouveau_bo **);
9494
int nouveau_bo_new_map(struct nouveau_cli *, u32 domain, u32 size, struct nouveau_bo **);
95+
int nouveau_bo_new_map_gpu(struct nouveau_cli *, u32 domain, u32 size,
96+
struct nouveau_bo **, struct nouveau_vma **);
9597
void nouveau_bo_unpin_del(struct nouveau_bo **);
9698

9799
/* TODO: submit equivalent to TTM generic API upstream? */

drivers/gpu/drm/nouveau/nouveau_chan.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ nouveau_channel_del(struct nouveau_channel **pchan)
103103
nvif_event_dtor(&chan->kill);
104104
nvif_object_dtor(&chan->user);
105105
nvif_mem_dtor(&chan->mem_userd);
106+
nouveau_vma_del(&chan->sema.vma);
107+
nouveau_bo_unpin_del(&chan->sema.bo);
106108
nvif_object_dtor(&chan->push.ctxdma);
107109
nouveau_vma_del(&chan->push.vma);
108110
nouveau_bo_unpin_del(&chan->push.buffer);
@@ -189,8 +191,10 @@ nouveau_channel_prep(struct nouveau_cli *cli,
189191

190192
chan->push.addr = chan->push.vma->addr;
191193

192-
if (device->info.family >= NV_DEVICE_INFO_V0_FERMI)
193-
return 0;
194+
if (device->info.family >= NV_DEVICE_INFO_V0_FERMI) {
195+
return nouveau_bo_new_map_gpu(cli, NOUVEAU_GEM_DOMAIN_GART, PAGE_SIZE,
196+
&chan->sema.bo, &chan->sema.vma);
197+
}
194198

195199
args.target = NV_DMA_V0_TARGET_VM;
196200
args.access = NV_DMA_V0_ACCESS_VM;
@@ -429,16 +433,25 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
429433
chan->user_get = 0x44;
430434
chan->dma.max = (0x10000 / 4) - 2;
431435
} else
432-
if (chan->user.oclass < VOLTA_CHANNEL_GPFIFO_A) {
436+
if (chan->user.oclass < FERMI_CHANNEL_GPFIFO) {
433437
ret = nvif_chan506f_ctor(&chan->chan, chan->userd->map.ptr,
434438
(u8*)chan->push.buffer->kmap.virtual + 0x10000, 0x2000,
435439
chan->push.buffer->kmap.virtual, chan->push.addr, 0x10000);
436440
if (ret)
437441
return ret;
442+
} else
443+
if (chan->user.oclass < VOLTA_CHANNEL_GPFIFO_A) {
444+
ret = nvif_chan906f_ctor(&chan->chan, chan->userd->map.ptr,
445+
(u8*)chan->push.buffer->kmap.virtual + 0x10000, 0x2000,
446+
chan->push.buffer->kmap.virtual, chan->push.addr, 0x10000,
447+
chan->sema.bo->kmap.virtual, chan->sema.vma->addr);
448+
if (ret)
449+
return ret;
438450
} else {
439451
ret = nvif_chanc36f_ctor(&chan->chan, chan->userd->map.ptr,
440452
(u8*)chan->push.buffer->kmap.virtual + 0x10000, 0x2000,
441453
chan->push.buffer->kmap.virtual, chan->push.addr, 0x10000,
454+
chan->sema.bo->kmap.virtual, chan->sema.vma->addr,
442455
&drm->client.device.user, chan->token);
443456
if (ret)
444457
return ret;

drivers/gpu/drm/nouveau/nouveau_chan.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ struct nouveau_channel {
4343
u32 user_get;
4444
u32 user_put;
4545

46+
struct {
47+
struct nouveau_bo *bo;
48+
struct nouveau_vma *vma;
49+
} sema;
50+
4651
struct nvif_object user;
4752
struct nvif_object blit;
4853

drivers/gpu/drm/nouveau/nouveau_exec.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ nouveau_exec_job_run(struct nouveau_job *job)
146146
nvif_chan_gpfifo_push(&chan->chan, p->va, p->va_len, no_prefetch);
147147
}
148148

149+
nvif_chan_gpfifo_post(&chan->chan);
150+
149151
ret = nouveau_fence_emit(fence);
150152
if (ret) {
151153
nouveau_fence_unref(&exec_job->fence);

drivers/gpu/drm/nouveau/nouveau_gem.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
866866

867867
nvif_chan_gpfifo_push(&chan->chan, addr, length, no_prefetch);
868868
}
869+
870+
nvif_chan_gpfifo_post(&chan->chan);
869871
} else
870872
if (drm->client.device.info.chipset >= 0x25) {
871873
ret = PUSH_WAIT(&chan->chan.push, req->nr_push * 2);

drivers/gpu/drm/nouveau/nvif/Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ nvif-y += nvif/vmm.o
1717
# Channel classes
1818
nvif-y += nvif/chan.o
1919
nvif-y += nvif/chan506f.o
20+
nvif-y += nvif/chan906f.o
2021
nvif-y += nvif/chanc36f.o
2122

2223
# Usermode classes

drivers/gpu/drm/nouveau/nvif/chan.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ nvif_chan_gpfifo_push_kick(struct nvif_push *push)
99
{
1010
struct nvif_chan *chan = container_of(push, typeof(*chan), push);
1111
u32 put = push->bgn - (u32 *)chan->push.mem.object.map.ptr;
12-
u32 cnt = push->cur - push->bgn;
12+
u32 cnt;
13+
14+
if (chan->func->gpfifo.post) {
15+
if (push->end - push->cur < chan->func->gpfifo.post_size)
16+
push->end = push->cur + chan->func->gpfifo.post_size;
17+
18+
WARN_ON(nvif_chan_gpfifo_post(chan));
19+
}
20+
21+
cnt = push->cur - push->bgn;
1322

1423
chan->func->gpfifo.push(chan, true, chan->push.addr + (put << 2), cnt << 2, false);
1524
chan->func->gpfifo.kick(chan);
@@ -23,6 +32,16 @@ nvif_chan_gpfifo_push_wait(struct nvif_push *push, u32 push_nr)
2332
return nvif_chan_gpfifo_wait(chan, 1, push_nr);
2433
}
2534

35+
int
36+
nvif_chan_gpfifo_post(struct nvif_chan *chan)
37+
{
38+
const u32 *map = chan->push.mem.object.map.ptr;
39+
const u32 pbptr = (chan->push.cur - map) + chan->func->gpfifo.post_size;
40+
const u32 gpptr = (chan->gpfifo.cur + 1) & chan->gpfifo.max;
41+
42+
return chan->func->gpfifo.post(chan, gpptr, pbptr);
43+
}
44+
2645
void
2746
nvif_chan_gpfifo_push(struct nvif_chan *chan, u64 addr, u32 size, bool no_prefetch)
2847
{
@@ -35,6 +54,14 @@ nvif_chan_gpfifo_wait(struct nvif_chan *chan, u32 gpfifo_nr, u32 push_nr)
3554
struct nvif_push *push = &chan->push;
3655
int ret = 0, time = 1000000;
3756

57+
if (gpfifo_nr) {
58+
/* Account for pushbuf space needed by nvif_chan_gpfifo_post(),
59+
* if used after pushing userspace GPFIFO entries.
60+
*/
61+
if (chan->func->gpfifo.post)
62+
push_nr += chan->func->gpfifo.post_size;
63+
}
64+
3865
/* Account for the GPFIFO entry needed to submit pushbuf. */
3966
if (push_nr)
4067
gpfifo_nr++;
@@ -89,6 +116,8 @@ nvif_chan_dma_wait(struct nvif_chan *chan, u32 nr)
89116
u32 cur = push->cur - (u32 *)push->mem.object.map.ptr;
90117
u32 free, time = 1000000;
91118

119+
nr += chan->func->gpfifo.post_size;
120+
92121
do {
93122
u32 get = chan->func->push.read_get(chan);
94123

@@ -122,6 +151,6 @@ nvif_chan_dma_wait(struct nvif_chan *chan, u32 nr)
122151

123152
push->bgn = (u32 *)push->mem.object.map.ptr + cur;
124153
push->cur = push->bgn;
125-
push->end = push->bgn + free;
154+
push->end = push->bgn + free - chan->func->gpfifo.post_size;
126155
return 0;
127156
}

drivers/gpu/drm/nouveau/nvif/chan506f.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55
#include <nvif/chan.h>
66

7-
static void
7+
void
88
nvif_chan506f_gpfifo_kick(struct nvif_chan *chan)
99
{
1010
wmb();
@@ -31,13 +31,13 @@ nvif_chan506f_gpfifo_push(struct nvif_chan *chan, bool main, u64 addr, u32 size,
3131
chan->push.end = chan->push.cur;
3232
}
3333

34-
u32
34+
static u32
3535
nvif_chan506f_gpfifo_read_get(struct nvif_chan *chan)
3636
{
3737
return nvif_rd32(&chan->userd, 0x88);
3838
}
3939

40-
u32
40+
static u32
4141
nvif_chan506f_read_get(struct nvif_chan *chan)
4242
{
4343
u32 tlgetlo = nvif_rd32(&chan->userd, 0x58);

0 commit comments

Comments
 (0)