Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfe91afa authored by Ben Skeggs's avatar Ben Skeggs
Browse files

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: default avatarBen Skeggs <bskeggs@redhat.com>
parent a261a20c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -339,7 +339,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
		goto done;

	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
		ret = nouveau_vma_new(chan->ntfy, &cli->vmm, &chan->ntfy_vma);
		ret = nouveau_vma_new(chan->ntfy, chan->chan->vmm,
				      &chan->ntfy_vma);
		if (ret)
			goto done;
	}
+1 −1
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
	struct nouveau_drm *drm = cli->drm;
	struct nouveau_bo *nvbo;
	struct nvif_mmu *mmu = &cli->mmu;
	struct nvif_vmm *vmm = &cli->vmm.vmm;
	struct nvif_vmm *vmm = cli->svm.cli ? &cli->svm.vmm : &cli->vmm.vmm;
	size_t acc_size;
	int type = ttm_bo_type_device;
	int ret, i, pi = -1;
+11 −12
Original line number Diff line number Diff line
@@ -130,6 +130,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,

	chan->device = device;
	chan->drm = drm;
	chan->vmm = cli->svm.cli ? &cli->svm : &cli->vmm;
	atomic_set(&chan->killed, 0);

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

	if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
		ret = nouveau_vma_new(chan->push.buffer, &cli->vmm,
		ret = nouveau_vma_new(chan->push.buffer, chan->vmm,
				      &chan->push.vma);
		if (ret) {
			nouveau_channel_del(pchan);
@@ -172,7 +173,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
		args.target = NV_DMA_V0_TARGET_VM;
		args.access = NV_DMA_V0_ACCESS_VM;
		args.start = 0;
		args.limit = cli->vmm.vmm.limit - 1;
		args.limit = chan->vmm->vmm.limit - 1;
	} else
	if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) {
		if (device->info.family == NV_DEVICE_INFO_V0_TNT) {
@@ -202,7 +203,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
			args.target = NV_DMA_V0_TARGET_VM;
			args.access = NV_DMA_V0_ACCESS_RDWR;
			args.start = 0;
			args.limit = cli->vmm.vmm.limit - 1;
			args.limit = chan->vmm->vmm.limit - 1;
		}
	}

@@ -220,7 +221,6 @@ static int
nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
		    u64 runlist, bool priv, struct nouveau_channel **pchan)
{
	struct nouveau_cli *cli = (void *)device->object.client;
	static const u16 oclasses[] = { TURING_CHANNEL_GPFIFO_A,
					VOLTA_CHANNEL_GPFIFO_A,
					PASCAL_CHANNEL_GPFIFO_A,
@@ -255,7 +255,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
			args.volta.ilength = 0x02000;
			args.volta.ioffset = 0x10000 + chan->push.addr;
			args.volta.runlist = runlist;
			args.volta.vmm = nvif_handle(&cli->vmm.vmm.object);
			args.volta.vmm = nvif_handle(&chan->vmm->vmm.object);
			args.volta.priv = priv;
			size = sizeof(args.volta);
		} else
@@ -264,7 +264,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
			args.kepler.ilength = 0x02000;
			args.kepler.ioffset = 0x10000 + chan->push.addr;
			args.kepler.runlist = runlist;
			args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object);
			args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object);
			args.kepler.priv = priv;
			size = sizeof(args.kepler);
		} else
@@ -272,14 +272,14 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
			args.fermi.version = 0;
			args.fermi.ilength = 0x02000;
			args.fermi.ioffset = 0x10000 + chan->push.addr;
			args.fermi.vmm = nvif_handle(&cli->vmm.vmm.object);
			args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object);
			size = sizeof(args.fermi);
		} else {
			args.nv50.version = 0;
			args.nv50.ilength = 0x02000;
			args.nv50.ioffset = 0x10000 + chan->push.addr;
			args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
			args.nv50.vmm = nvif_handle(&cli->vmm.vmm.object);
			args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object);
			size = sizeof(args.nv50);
		}

@@ -350,7 +350,6 @@ static int
nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
{
	struct nvif_device *device = chan->device;
	struct nouveau_cli *cli = (void *)chan->user.client;
	struct nouveau_drm *drm = chan->drm;
	struct nv_dma_v0 args = {};
	int ret, i;
@@ -376,7 +375,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
			args.target = NV_DMA_V0_TARGET_VM;
			args.access = NV_DMA_V0_ACCESS_VM;
			args.start = 0;
			args.limit = cli->vmm.vmm.limit - 1;
			args.limit = chan->vmm->vmm.limit - 1;
		} else {
			args.target = NV_DMA_V0_TARGET_VRAM;
			args.access = NV_DMA_V0_ACCESS_RDWR;
@@ -393,7 +392,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
			args.target = NV_DMA_V0_TARGET_VM;
			args.access = NV_DMA_V0_ACCESS_VM;
			args.start = 0;
			args.limit = cli->vmm.vmm.limit - 1;
			args.limit = chan->vmm->vmm.limit - 1;
		} else
		if (chan->drm->agp.bridge) {
			args.target = NV_DMA_V0_TARGET_AGP;
@@ -405,7 +404,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
			args.target = NV_DMA_V0_TARGET_VM;
			args.access = NV_DMA_V0_ACCESS_RDWR;
			args.start = 0;
			args.limit = cli->vmm.vmm.limit - 1;
			args.limit = chan->vmm->vmm.limit - 1;
		}

		ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY,
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ struct nvif_device;
struct nouveau_channel {
	struct nvif_device *device;
	struct nouveau_drm *drm;
	struct nouveau_vmm *vmm;

	int chid;
	u64 inst;
+1 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ nouveau_cli_fini(struct nouveau_cli *cli)
	WARN_ON(!list_empty(&cli->worker));

	usif_client_fini(cli);
	nouveau_vmm_fini(&cli->svm);
	nouveau_vmm_fini(&cli->vmm);
	nvif_mmu_fini(&cli->mmu);
	nvif_device_fini(&cli->device);
Loading