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

Commit 6c6ae061 authored by Ben Skeggs's avatar Ben Skeggs
Browse files

drm/nouveau/fifo: allow direct access to channel control registers where possible



The indirect method has been left in-place here as a fallback path, as
it may not be possible to map the non-PAGE_SIZE aligned control areas
across some chipset+interface combinations.

This isn't a problem for the primary use-case where the core and drm
are linked together in kernel-land, but across a VM or (in the case
where it applies now) between the core in the kernel and a userspace
test tool.

Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
parent bbf8906b
Loading
Loading
Loading
Loading
+24 −9
Original line number Diff line number Diff line
@@ -103,15 +103,10 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
		return -ENOSPC;
	}

	/* map fifo control registers */
	chan->user = ioremap(nv_device_resource_start(device, bar) + addr +
			     (chan->chid * size), size);
	if (!chan->user)
		return -EFAULT;

	nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);

	chan->addr = nv_device_resource_start(device, bar) +
		     addr + size * chan->chid;
	chan->size = size;
	nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);
	return 0;
}

@@ -121,6 +116,7 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan)
	struct nouveau_fifo *priv = (void *)nv_object(chan)->engine;
	unsigned long flags;

	if (chan->user)
		iounmap(chan->user);

	spin_lock_irqsave(&priv->lock, flags);
@@ -139,10 +135,24 @@ _nouveau_fifo_channel_dtor(struct nouveau_object *object)
	nouveau_fifo_channel_destroy(chan);
}

int
_nouveau_fifo_channel_map(struct nouveau_object *object, u64 *addr, u32 *size)
{
	struct nouveau_fifo_chan *chan = (void *)object;
	*addr = chan->addr;
	*size = chan->size;
	return 0;
}

u32
_nouveau_fifo_channel_rd32(struct nouveau_object *object, u64 addr)
{
	struct nouveau_fifo_chan *chan = (void *)object;
	if (unlikely(!chan->user)) {
		chan->user = ioremap(chan->addr, chan->size);
		if (WARN_ON_ONCE(chan->user == NULL))
			return 0;
	}
	return ioread32_native(chan->user + addr);
}

@@ -150,6 +160,11 @@ void
_nouveau_fifo_channel_wr32(struct nouveau_object *object, u64 addr, u32 data)
{
	struct nouveau_fifo_chan *chan = (void *)object;
	if (unlikely(!chan->user)) {
		chan->user = ioremap(chan->addr, chan->size);
		if (WARN_ON_ONCE(chan->user == NULL))
			return;
	}
	iowrite32_native(data, chan->user + addr);
}

+1 −0
Original line number Diff line number Diff line
@@ -252,6 +252,7 @@ nv04_fifo_ofuncs = {
	.dtor = nv04_fifo_chan_dtor,
	.init = nv04_fifo_chan_init,
	.fini = nv04_fifo_chan_fini,
	.map  = _nouveau_fifo_channel_map,
	.rd32 = _nouveau_fifo_channel_rd32,
	.wr32 = _nouveau_fifo_channel_wr32,
};
+1 −0
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ nv10_fifo_ofuncs = {
	.dtor = nv04_fifo_chan_dtor,
	.init = nv04_fifo_chan_init,
	.fini = nv04_fifo_chan_fini,
	.map  = _nouveau_fifo_channel_map,
	.rd32 = _nouveau_fifo_channel_rd32,
	.wr32 = _nouveau_fifo_channel_wr32,
};
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ nv17_fifo_ofuncs = {
	.dtor = nv04_fifo_chan_dtor,
	.init = nv04_fifo_chan_init,
	.fini = nv04_fifo_chan_fini,
	.map  = _nouveau_fifo_channel_map,
	.rd32 = _nouveau_fifo_channel_rd32,
	.wr32 = _nouveau_fifo_channel_wr32,
};
+1 −0
Original line number Diff line number Diff line
@@ -236,6 +236,7 @@ nv40_fifo_ofuncs = {
	.dtor = nv04_fifo_chan_dtor,
	.init = nv04_fifo_chan_init,
	.fini = nv04_fifo_chan_fini,
	.map  = _nouveau_fifo_channel_map,
	.rd32 = _nouveau_fifo_channel_rd32,
	.wr32 = _nouveau_fifo_channel_wr32,
};
Loading