drm/nouveau/fifo: allow direct access to channel control registers where possible
authorBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 18:10:25 +0000 (04:10 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Sat, 9 Aug 2014 19:28:05 +0000 (05:28 +1000)
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>
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv10.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv17.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv40.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
drivers/gpu/drm/nouveau/core/include/engine/fifo.h
drivers/gpu/drm/nouveau/nouveau_chan.c

index f825def16ffa8e3b367723beb20707addaa79645..0def249b1b43ff9fd4638015f21bbe1995c979ff 100644 (file)
@@ -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);
 }
 
index 5b4a9a56d63048743a42469bb6fc2c37b847cf5a..347b381e2dcf28d2ff5141e9a522f387028c33ac 100644 (file)
@@ -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,
 };
index 90713fdef662948f9655810251bd3ec26f31c01f..d8dac2fc6a3bc7d9550ec3f9f6f74549d078061c 100644 (file)
@@ -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,
 };
index 07b4b2d33bd2a7d4754819eba3f7fa0a32dfec2f..c424aab0e0413f7d339e97ffb48c37593b98116a 100644 (file)
@@ -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,
 };
index 0aa3a138774256f7eac5cf05869265b071e7b2fb..17d14d9e02ca8f8b2be0a8fac4f35fb762b816dd 100644 (file)
@@ -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,
 };
index ffc74f1ea30f3e2ed3211399ac1178fd1742538e..2db67a207b4a672e099517ad6946bd5ed631d774 100644 (file)
@@ -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,
 };
index bb9017377889abb2782b108f77475df6fcd66d0c..a2acf3f78b568b57dd4413c3c24bb9ad6dc24de2 100644 (file)
@@ -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,
 };
index c4a1e1122c93353c29aeae09f5e1cfabf9db0f11..f76ed10d8db0310fd0f154af5ff3930602ce9de0 100644 (file)
@@ -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,
 };
index 96b14b7873f11f9c016d1d0f516786d1aeb25619..ef730b52ce0d57a162e632fa714da4d2a2bfee8d 100644 (file)
@@ -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,
 };
index 83567124d3b5bffc8f2f23476246868fdc0c05a4..b53f9d8022fed1aa8141441e54a14d10d370946a 100644 (file)
@@ -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);
 
index ab2d9ff45a446987ed08690c30ac6ab5745a2b3c..b4173be38451882b3879f4e4db410a25ae629a10 100644 (file)
@@ -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) {