From 6c6ae061b61c1fd0d1823765299bcc009ddc21c8 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sun, 10 Aug 2014 04:10:25 +1000 Subject: [PATCH] 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 --- .../gpu/drm/nouveau/core/engine/fifo/base.c | 33 ++++++++++++++----- .../gpu/drm/nouveau/core/engine/fifo/nv04.c | 1 + .../gpu/drm/nouveau/core/engine/fifo/nv10.c | 1 + .../gpu/drm/nouveau/core/engine/fifo/nv17.c | 1 + .../gpu/drm/nouveau/core/engine/fifo/nv40.c | 1 + .../gpu/drm/nouveau/core/engine/fifo/nv50.c | 2 ++ .../gpu/drm/nouveau/core/engine/fifo/nv84.c | 2 ++ .../gpu/drm/nouveau/core/engine/fifo/nvc0.c | 1 + .../gpu/drm/nouveau/core/engine/fifo/nve0.c | 1 + .../drm/nouveau/core/include/engine/fifo.h | 2 ++ drivers/gpu/drm/nouveau/nouveau_chan.c | 2 ++ 11 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index f825def16ffa..0def249b1b43 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -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,7 +116,8 @@ nouveau_fifo_channel_destroy(struct nouveau_fifo_chan *chan) struct nouveau_fifo *priv = (void *)nv_object(chan)->engine; unsigned long flags; - iounmap(chan->user); + if (chan->user) + iounmap(chan->user); spin_lock_irqsave(&priv->lock, flags); priv->channel[chan->chid] = NULL; @@ -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); } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index 5b4a9a56d630..347b381e2dcf 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c index 90713fdef662..d8dac2fc6a3b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c index 07b4b2d33bd2..c424aab0e041 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c index 0aa3a1387742..17d14d9e02ca 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index ffc74f1ea30f..2db67a207b4a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index bb9017377889..a2acf3f78b56 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index c4a1e1122c93..f76ed10d8db0 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 96b14b7873f1..ef730b52ce0d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -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, }; diff --git a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index 83567124d3b5..b53f9d8022fe 100644 --- a/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -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); diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index ab2d9ff45a44..b4173be38451 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -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) { -- 2.20.1