Skip to content

Commit bfe91af

Browse files
author
Ben Skeggs
committed
drm/nouveau: prepare for enabling svm with existing userspace interfaces
For a channel to make use of SVM features, it requires a different GPU MMU configuration than we would normally use, which is not desirable to switch to unless a client is actively going to use SVM. In order to supporting SVM without more extensive changes to the userspace interfaces, the SVM_INIT ioctl needs to replace the previous configuration safely. The only way we can currently do this safely, accounting for some unlikely failure conditions, is to allocate the new VMM without destroying the last one, and prioritising the SVM-enabled configuration in the code that cares. This will get cleaned up again further down the track. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
1 parent a261a20 commit bfe91af

File tree

9 files changed

+42
-37
lines changed

9 files changed

+42
-37
lines changed

drivers/gpu/drm/nouveau/nouveau_abi16.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
339339
goto done;
340340

341341
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
342-
ret = nouveau_vma_new(chan->ntfy, &cli->vmm, &chan->ntfy_vma);
342+
ret = nouveau_vma_new(chan->ntfy, chan->chan->vmm,
343+
&chan->ntfy_vma);
343344
if (ret)
344345
goto done;
345346
}

drivers/gpu/drm/nouveau/nouveau_bo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
194194
struct nouveau_drm *drm = cli->drm;
195195
struct nouveau_bo *nvbo;
196196
struct nvif_mmu *mmu = &cli->mmu;
197-
struct nvif_vmm *vmm = &cli->vmm.vmm;
197+
struct nvif_vmm *vmm = cli->svm.cli ? &cli->svm.vmm : &cli->vmm.vmm;
198198
size_t acc_size;
199199
int type = ttm_bo_type_device;
200200
int ret, i, pi = -1;

drivers/gpu/drm/nouveau/nouveau_chan.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
130130

131131
chan->device = device;
132132
chan->drm = drm;
133+
chan->vmm = cli->svm.cli ? &cli->svm : &cli->vmm;
133134
atomic_set(&chan->killed, 0);
134135

135136
/* allocate memory for dma push buffer */
@@ -157,7 +158,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
157158
chan->push.addr = chan->push.buffer->bo.offset;
158159

159160
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
160-
ret = nouveau_vma_new(chan->push.buffer, &cli->vmm,
161+
ret = nouveau_vma_new(chan->push.buffer, chan->vmm,
161162
&chan->push.vma);
162163
if (ret) {
163164
nouveau_channel_del(pchan);
@@ -172,7 +173,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
172173
args.target = NV_DMA_V0_TARGET_VM;
173174
args.access = NV_DMA_V0_ACCESS_VM;
174175
args.start = 0;
175-
args.limit = cli->vmm.vmm.limit - 1;
176+
args.limit = chan->vmm->vmm.limit - 1;
176177
} else
177178
if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
178179
if (device->info.family == NV_DEVICE_INFO_V0_TNT) {
@@ -202,7 +203,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
202203
args.target = NV_DMA_V0_TARGET_VM;
203204
args.access = NV_DMA_V0_ACCESS_RDWR;
204205
args.start = 0;
205-
args.limit = cli->vmm.vmm.limit - 1;
206+
args.limit = chan->vmm->vmm.limit - 1;
206207
}
207208
}
208209

@@ -220,7 +221,6 @@ static int
220221
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
221222
u64 runlist, bool priv, struct nouveau_channel **pchan)
222223
{
223-
struct nouveau_cli *cli = (void *)device->object.client;
224224
static const u16 oclasses[] = { TURING_CHANNEL_GPFIFO_A,
225225
VOLTA_CHANNEL_GPFIFO_A,
226226
PASCAL_CHANNEL_GPFIFO_A,
@@ -255,7 +255,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
255255
args.volta.ilength = 0x02000;
256256
args.volta.ioffset = 0x10000 + chan->push.addr;
257257
args.volta.runlist = runlist;
258-
args.volta.vmm = nvif_handle(&cli->vmm.vmm.object);
258+
args.volta.vmm = nvif_handle(&chan->vmm->vmm.object);
259259
args.volta.priv = priv;
260260
size = sizeof(args.volta);
261261
} else
@@ -264,22 +264,22 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
264264
args.kepler.ilength = 0x02000;
265265
args.kepler.ioffset = 0x10000 + chan->push.addr;
266266
args.kepler.runlist = runlist;
267-
args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
267+
args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object);
268268
args.kepler.priv = priv;
269269
size = sizeof(args.kepler);
270270
} else
271271
if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
272272
args.fermi.version = 0;
273273
args.fermi.ilength = 0x02000;
274274
args.fermi.ioffset = 0x10000 + chan->push.addr;
275-
args.fermi.vmm = nvif_handle(&cli->vmm.vmm.object);
275+
args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object);
276276
size = sizeof(args.fermi);
277277
} else {
278278
args.nv50.version = 0;
279279
args.nv50.ilength = 0x02000;
280280
args.nv50.ioffset = 0x10000 + chan->push.addr;
281281
args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
282-
args.nv50.vmm = nvif_handle(&cli->vmm.vmm.object);
282+
args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object);
283283
size = sizeof(args.nv50);
284284
}
285285

@@ -350,7 +350,6 @@ static int
350350
nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
351351
{
352352
struct nvif_device *device = chan->device;
353-
struct nouveau_cli *cli = (void *)chan->user.client;
354353
struct nouveau_drm *drm = chan->drm;
355354
struct nv_dma_v0 args = {};
356355
int ret, i;
@@ -376,7 +375,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
376375
args.target = NV_DMA_V0_TARGET_VM;
377376
args.access = NV_DMA_V0_ACCESS_VM;
378377
args.start = 0;
379-
args.limit = cli->vmm.vmm.limit - 1;
378+
args.limit = chan->vmm->vmm.limit - 1;
380379
} else {
381380
args.target = NV_DMA_V0_TARGET_VRAM;
382381
args.access = NV_DMA_V0_ACCESS_RDWR;
@@ -393,7 +392,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
393392
args.target = NV_DMA_V0_TARGET_VM;
394393
args.access = NV_DMA_V0_ACCESS_VM;
395394
args.start = 0;
396-
args.limit = cli->vmm.vmm.limit - 1;
395+
args.limit = chan->vmm->vmm.limit - 1;
397396
} else
398397
if (chan->drm->agp.bridge) {
399398
args.target = NV_DMA_V0_TARGET_AGP;
@@ -405,7 +404,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
405404
args.target = NV_DMA_V0_TARGET_VM;
406405
args.access = NV_DMA_V0_ACCESS_RDWR;
407406
args.start = 0;
408-
args.limit = cli->vmm.vmm.limit - 1;
407+
args.limit = chan->vmm->vmm.limit - 1;
409408
}
410409

411410
ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY,

drivers/gpu/drm/nouveau/nouveau_chan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ struct nvif_device;
88
struct nouveau_channel {
99
struct nvif_device *device;
1010
struct nouveau_drm *drm;
11+
struct nouveau_vmm *vmm;
1112

1213
int chid;
1314
u64 inst;

drivers/gpu/drm/nouveau/nouveau_drm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ nouveau_cli_fini(struct nouveau_cli *cli)
172172
WARN_ON(!list_empty(&cli->worker));
173173

174174
usif_client_fini(cli);
175+
nouveau_vmm_fini(&cli->svm);
175176
nouveau_vmm_fini(&cli->vmm);
176177
nvif_mmu_fini(&cli->mmu);
177178
nvif_device_fini(&cli->device);

drivers/gpu/drm/nouveau/nouveau_drv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct nouveau_cli {
9696
struct nvif_device device;
9797
struct nvif_mmu mmu;
9898
struct nouveau_vmm vmm;
99+
struct nouveau_vmm svm;
99100
const struct nvif_mclass *mem;
100101

101102
struct list_head head;

drivers/gpu/drm/nouveau/nouveau_fbcon.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
353353

354354
chan = nouveau_nofbaccel ? NULL : drm->channel;
355355
if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
356-
ret = nouveau_vma_new(nvbo, &drm->client.vmm, &fb->vma);
356+
ret = nouveau_vma_new(nvbo, chan->vmm, &fb->vma);
357357
if (ret) {
358358
NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
359359
chan = NULL;

drivers/gpu/drm/nouveau/nouveau_gem.c

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
6868
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
6969
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
7070
struct device *dev = drm->dev->dev;
71+
struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm;
7172
struct nouveau_vma *vma;
7273
int ret;
7374

74-
if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50)
75+
if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50)
7576
return 0;
7677

7778
ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
@@ -82,7 +83,7 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv)
8283
if (ret < 0 && ret != -EACCES)
8384
goto out;
8485

85-
ret = nouveau_vma_new(nvbo, &cli->vmm, &vma);
86+
ret = nouveau_vma_new(nvbo, vmm, &vma);
8687
pm_runtime_mark_last_busy(dev);
8788
pm_runtime_put_autosuspend(dev);
8889
out:
@@ -142,17 +143,18 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv)
142143
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
143144
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
144145
struct device *dev = drm->dev->dev;
146+
struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : & cli->vmm;
145147
struct nouveau_vma *vma;
146148
int ret;
147149

148-
if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50)
150+
if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50)
149151
return;
150152

151153
ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
152154
if (ret)
153155
return;
154156

155-
vma = nouveau_vma_find(nvbo, &cli->vmm);
157+
vma = nouveau_vma_find(nvbo, vmm);
156158
if (vma) {
157159
if (--vma->refs == 0) {
158160
ret = pm_runtime_get_sync(dev);
@@ -219,6 +221,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
219221
{
220222
struct nouveau_cli *cli = nouveau_cli(file_priv);
221223
struct nouveau_bo *nvbo = nouveau_gem_object(gem);
224+
struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm;
222225
struct nouveau_vma *vma;
223226

224227
if (is_power_of_2(nvbo->valid_domains))
@@ -228,8 +231,8 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem,
228231
else
229232
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
230233
rep->offset = nvbo->bo.offset;
231-
if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
232-
vma = nouveau_vma_find(nvbo, &cli->vmm);
234+
if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
235+
vma = nouveau_vma_find(nvbo, vmm);
233236
if (!vma)
234237
return -EINVAL;
235238

@@ -321,7 +324,8 @@ struct validate_op {
321324
};
322325

323326
static void
324-
validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence,
327+
validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan,
328+
struct nouveau_fence *fence,
325329
struct drm_nouveau_gem_pushbuf_bo *pbbo)
326330
{
327331
struct nouveau_bo *nvbo;
@@ -332,13 +336,11 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence,
332336
b = &pbbo[nvbo->pbbo_index];
333337

334338
if (likely(fence)) {
335-
struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
336-
struct nouveau_vma *vma;
337-
338339
nouveau_bo_fence(nvbo, fence, !!b->write_domains);
339340

340-
if (drm->client.vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
341-
vma = (void *)(unsigned long)b->user_priv;
341+
if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
342+
struct nouveau_vma *vma =
343+
(void *)(unsigned long)b->user_priv;
342344
nouveau_fence_unref(&vma->fence);
343345
dma_fence_get(&fence->base);
344346
vma->fence = fence;
@@ -358,10 +360,11 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_fence *fence,
358360
}
359361

360362
static void
361-
validate_fini(struct validate_op *op, struct nouveau_fence *fence,
363+
validate_fini(struct validate_op *op, struct nouveau_channel *chan,
364+
struct nouveau_fence *fence,
362365
struct drm_nouveau_gem_pushbuf_bo *pbbo)
363366
{
364-
validate_fini_no_ticket(op, fence, pbbo);
367+
validate_fini_no_ticket(op, chan, fence, pbbo);
365368
ww_acquire_fini(&op->ticket);
366369
}
367370

@@ -416,7 +419,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
416419
list_splice_tail_init(&vram_list, &op->list);
417420
list_splice_tail_init(&gart_list, &op->list);
418421
list_splice_tail_init(&both_list, &op->list);
419-
validate_fini_no_ticket(op, NULL, NULL);
422+
validate_fini_no_ticket(op, chan, NULL, NULL);
420423
if (unlikely(ret == -EDEADLK)) {
421424
ret = ttm_bo_reserve_slowpath(&nvbo->bo, true,
422425
&op->ticket);
@@ -430,8 +433,8 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
430433
}
431434
}
432435

433-
if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
434-
struct nouveau_vmm *vmm = &cli->vmm;
436+
if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) {
437+
struct nouveau_vmm *vmm = chan->vmm;
435438
struct nouveau_vma *vma = nouveau_vma_find(nvbo, vmm);
436439
if (!vma) {
437440
NV_PRINTK(err, cli, "vma not found!\n");
@@ -471,7 +474,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
471474
list_splice_tail(&gart_list, &op->list);
472475
list_splice_tail(&both_list, &op->list);
473476
if (ret)
474-
validate_fini(op, NULL, NULL);
477+
validate_fini(op, chan, NULL, NULL);
475478
return ret;
476479

477480
}
@@ -563,7 +566,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
563566
if (unlikely(ret < 0)) {
564567
if (ret != -ERESTARTSYS)
565568
NV_PRINTK(err, cli, "validating bo list\n");
566-
validate_fini(op, NULL, NULL);
569+
validate_fini(op, chan, NULL, NULL);
567570
return ret;
568571
}
569572
*apply_relocs = ret;
@@ -842,7 +845,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
842845
}
843846

844847
out:
845-
validate_fini(&op, fence, bo);
848+
validate_fini(&op, chan, fence, bo);
846849
nouveau_fence_unref(&fence);
847850

848851
out_prevalid:

drivers/gpu/drm/nouveau/nv84_fence.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@ nv84_fence_context_del(struct nouveau_channel *chan)
109109
int
110110
nv84_fence_context_new(struct nouveau_channel *chan)
111111
{
112-
struct nouveau_cli *cli = (void *)chan->user.client;
113112
struct nv84_fence_priv *priv = chan->drm->fence;
114113
struct nv84_fence_chan *fctx;
115114
int ret;
@@ -127,7 +126,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
127126
fctx->base.sequence = nv84_fence_read(chan);
128127

129128
mutex_lock(&priv->mutex);
130-
ret = nouveau_vma_new(priv->bo, &cli->vmm, &fctx->vma);
129+
ret = nouveau_vma_new(priv->bo, chan->vmm, &fctx->vma);
131130
mutex_unlock(&priv->mutex);
132131

133132
if (ret)

0 commit comments

Comments
 (0)