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: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
Родитель
bbf8906b2c
Коммит
6c6ae061b6
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -363,6 +363,7 @@ nv50_fifo_ofuncs_dma = {
|
|||
.dtor = nv50_fifo_chan_dtor,
|
||||
.init = nv50_fifo_chan_init,
|
||||
.fini = nv50_fifo_chan_fini,
|
||||
.map = _nouveau_fifo_channel_map,
|
||||
.rd32 = _nouveau_fifo_channel_rd32,
|
||||
.wr32 = _nouveau_fifo_channel_wr32,
|
||||
};
|
||||
|
@ -373,6 +374,7 @@ nv50_fifo_ofuncs_ind = {
|
|||
.dtor = nv50_fifo_chan_dtor,
|
||||
.init = nv50_fifo_chan_init,
|
||||
.fini = nv50_fifo_chan_fini,
|
||||
.map = _nouveau_fifo_channel_map,
|
||||
.rd32 = _nouveau_fifo_channel_rd32,
|
||||
.wr32 = _nouveau_fifo_channel_wr32,
|
||||
};
|
||||
|
|
|
@ -324,6 +324,7 @@ nv84_fifo_ofuncs_dma = {
|
|||
.dtor = nv50_fifo_chan_dtor,
|
||||
.init = nv84_fifo_chan_init,
|
||||
.fini = nv50_fifo_chan_fini,
|
||||
.map = _nouveau_fifo_channel_map,
|
||||
.rd32 = _nouveau_fifo_channel_rd32,
|
||||
.wr32 = _nouveau_fifo_channel_wr32,
|
||||
};
|
||||
|
@ -334,6 +335,7 @@ nv84_fifo_ofuncs_ind = {
|
|||
.dtor = nv50_fifo_chan_dtor,
|
||||
.init = nv84_fifo_chan_init,
|
||||
.fini = nv50_fifo_chan_fini,
|
||||
.map = _nouveau_fifo_channel_map,
|
||||
.rd32 = _nouveau_fifo_channel_rd32,
|
||||
.wr32 = _nouveau_fifo_channel_wr32,
|
||||
};
|
||||
|
|
|
@ -302,6 +302,7 @@ nvc0_fifo_ofuncs = {
|
|||
.dtor = _nouveau_fifo_channel_dtor,
|
||||
.init = nvc0_fifo_chan_init,
|
||||
.fini = nvc0_fifo_chan_fini,
|
||||
.map = _nouveau_fifo_channel_map,
|
||||
.rd32 = _nouveau_fifo_channel_rd32,
|
||||
.wr32 = _nouveau_fifo_channel_wr32,
|
||||
};
|
||||
|
|
|
@ -336,6 +336,7 @@ nve0_fifo_ofuncs = {
|
|||
.dtor = _nouveau_fifo_channel_dtor,
|
||||
.init = nve0_fifo_chan_init,
|
||||
.fini = nve0_fifo_chan_fini,
|
||||
.map = _nouveau_fifo_channel_map,
|
||||
.rd32 = _nouveau_fifo_channel_rd32,
|
||||
.wr32 = _nouveau_fifo_channel_wr32,
|
||||
};
|
||||
|
|
|
@ -10,6 +10,7 @@ struct nouveau_fifo_chan {
|
|||
struct nouveau_dmaobj *pushdma;
|
||||
struct nouveau_gpuobj *pushgpu;
|
||||
void __iomem *user;
|
||||
u64 addr;
|
||||
u32 size;
|
||||
u16 chid;
|
||||
atomic_t refcnt; /* NV04_NVSW_SET_REF */
|
||||
|
@ -40,6 +41,7 @@ void nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *);
|
|||
#define _nouveau_fifo_channel_fini _nouveau_namedb_fini
|
||||
|
||||
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);
|
||||
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)
|
|||
struct nv_dma_v0 args = {};
|
||||
int ret, i;
|
||||
|
||||
nvif_object_map(chan->object);
|
||||
|
||||
/* 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_TESLA) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче