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

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
...@@ -103,15 +103,10 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent, ...@@ -103,15 +103,10 @@ nouveau_fifo_channel_create_(struct nouveau_object *parent,
return -ENOSPC; return -ENOSPC;
} }
/* map fifo control registers */ chan->addr = nv_device_resource_start(device, bar) +
chan->user = ioremap(nv_device_resource_start(device, bar) + addr + addr + size * chan->chid;
(chan->chid * size), size);
if (!chan->user)
return -EFAULT;
nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);
chan->size = size; chan->size = size;
nvkm_event_send(&priv->cevent, 1, 0, NULL, 0);
return 0; return 0;
} }
...@@ -121,7 +116,8 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan) ...@@ -121,7 +116,8 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan)
struct nouveau_fifo *priv = (void *)nv_object(chan)->engine; struct nouveau_fifo *priv = (void *)nv_object(chan)->engine;
unsigned long flags; unsigned long flags;
iounmap(chan->user); if (chan->user)
iounmap(chan->user);
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
priv->channel[chan->chid] = NULL; priv->channel[chan->chid] = NULL;
...@@ -139,10 +135,24 @@ _nouveau_fifo_channel_dtor(struct nouveau_object *object) ...@@ -139,10 +135,24 @@ _nouveau_fifo_channel_dtor(struct nouveau_object *object)
nouveau_fifo_channel_destroy(chan); 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 u32
_nouveau_fifo_channel_rd32(struct nouveau_object *object, u64 addr) _nouveau_fifo_channel_rd32(struct nouveau_object *object, u64 addr)
{ {
struct nouveau_fifo_chan *chan = (void *)object; 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); return ioread32_native(chan->user + addr);
} }
...@@ -150,6 +160,11 @@ void ...@@ -150,6 +160,11 @@ void
_nouveau_fifo_channel_wr32(struct nouveau_object *object, u64 addr, u32 data) _nouveau_fifo_channel_wr32(struct nouveau_object *object, u64 addr, u32 data)
{ {
struct nouveau_fifo_chan *chan = (void *)object; 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); iowrite32_native(data, chan->user + addr);
} }
......
...@@ -252,6 +252,7 @@ nv04_fifo_ofuncs = { ...@@ -252,6 +252,7 @@ nv04_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor, .dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init, .init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini, .fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -110,6 +110,7 @@ nv10_fifo_ofuncs = { ...@@ -110,6 +110,7 @@ nv10_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor, .dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init, .init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini, .fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -117,6 +117,7 @@ nv17_fifo_ofuncs = { ...@@ -117,6 +117,7 @@ nv17_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor, .dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init, .init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini, .fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -236,6 +236,7 @@ nv40_fifo_ofuncs = { ...@@ -236,6 +236,7 @@ nv40_fifo_ofuncs = {
.dtor = nv04_fifo_chan_dtor, .dtor = nv04_fifo_chan_dtor,
.init = nv04_fifo_chan_init, .init = nv04_fifo_chan_init,
.fini = nv04_fifo_chan_fini, .fini = nv04_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -363,6 +363,7 @@ nv50_fifo_ofuncs_dma = { ...@@ -363,6 +363,7 @@ nv50_fifo_ofuncs_dma = {
.dtor = nv50_fifo_chan_dtor, .dtor = nv50_fifo_chan_dtor,
.init = nv50_fifo_chan_init, .init = nv50_fifo_chan_init,
.fini = nv50_fifo_chan_fini, .fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
...@@ -373,6 +374,7 @@ nv50_fifo_ofuncs_ind = { ...@@ -373,6 +374,7 @@ nv50_fifo_ofuncs_ind = {
.dtor = nv50_fifo_chan_dtor, .dtor = nv50_fifo_chan_dtor,
.init = nv50_fifo_chan_init, .init = nv50_fifo_chan_init,
.fini = nv50_fifo_chan_fini, .fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -324,6 +324,7 @@ nv84_fifo_ofuncs_dma = { ...@@ -324,6 +324,7 @@ nv84_fifo_ofuncs_dma = {
.dtor = nv50_fifo_chan_dtor, .dtor = nv50_fifo_chan_dtor,
.init = nv84_fifo_chan_init, .init = nv84_fifo_chan_init,
.fini = nv50_fifo_chan_fini, .fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
...@@ -334,6 +335,7 @@ nv84_fifo_ofuncs_ind = { ...@@ -334,6 +335,7 @@ nv84_fifo_ofuncs_ind = {
.dtor = nv50_fifo_chan_dtor, .dtor = nv50_fifo_chan_dtor,
.init = nv84_fifo_chan_init, .init = nv84_fifo_chan_init,
.fini = nv50_fifo_chan_fini, .fini = nv50_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -302,6 +302,7 @@ nvc0_fifo_ofuncs = { ...@@ -302,6 +302,7 @@ nvc0_fifo_ofuncs = {
.dtor = _nouveau_fifo_channel_dtor, .dtor = _nouveau_fifo_channel_dtor,
.init = nvc0_fifo_chan_init, .init = nvc0_fifo_chan_init,
.fini = nvc0_fifo_chan_fini, .fini = nvc0_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -336,6 +336,7 @@ nve0_fifo_ofuncs = { ...@@ -336,6 +336,7 @@ nve0_fifo_ofuncs = {
.dtor = _nouveau_fifo_channel_dtor, .dtor = _nouveau_fifo_channel_dtor,
.init = nve0_fifo_chan_init, .init = nve0_fifo_chan_init,
.fini = nve0_fifo_chan_fini, .fini = nve0_fifo_chan_fini,
.map = _nouveau_fifo_channel_map,
.rd32 = _nouveau_fifo_channel_rd32, .rd32 = _nouveau_fifo_channel_rd32,
.wr32 = _nouveau_fifo_channel_wr32, .wr32 = _nouveau_fifo_channel_wr32,
}; };
......
...@@ -10,6 +10,7 @@ struct nouveau_fifo_chan { ...@@ -10,6 +10,7 @@ struct nouveau_fifo_chan {
struct nouveau_dmaobj *pushdma; struct nouveau_dmaobj *pushdma;
struct nouveau_gpuobj *pushgpu; struct nouveau_gpuobj *pushgpu;
void __iomem *user; void __iomem *user;
u64 addr;
u32 size; u32 size;
u16 chid; u16 chid;
atomic_t refcnt; /* NV04_NVSW_SET_REF */ atomic_t refcnt; /* NV04_NVSW_SET_REF */
...@@ -40,6 +41,7 @@ void nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *); ...@@ -40,6 +41,7 @@ void nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *);
#define _nouveau_fifo_channel_fini _nouveau_namedb_fini #define _nouveau_fifo_channel_fini _nouveau_namedb_fini
void _nouveau_fifo_channel_dtor(struct nouveau_object *); void _nouveau_fifo_channel_dtor(struct nouveau_object *);
int _nouveau_fifo_channel_map(struct nouveau_object *, u64 *, u32 *);
u32 _nouveau_fifo_channel_rd32(struct nouveau_object *, u64); u32 _nouveau_fifo_channel_rd32(struct nouveau_object *, u64);
void _nouveau_fifo_channel_wr32(struct nouveau_object *, u64, u32); void _nouveau_fifo_channel_wr32(struct nouveau_object *, u64, u32);
......
...@@ -291,6 +291,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) ...@@ -291,6 +291,8 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
struct nv_dma_v0 args = {}; struct nv_dma_v0 args = {};
int ret, i; int ret, i;
nvif_object_map(chan->object);
/* allocate dma objects to cover all allowed vram, and gart */ /* allocate dma objects to cover all allowed vram, and gart */
if (device->info.family < NV_DEVICE_INFO_V0_FERMI) { if (device->info.family < NV_DEVICE_INFO_V0_FERMI) {
if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment