drm/nv50/fb: implement trap handler as subdev interrupt handler
authorBen Skeggs <bskeggs@redhat.com>
Thu, 22 Nov 2012 02:57:32 +0000 (12:57 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 28 Nov 2012 23:58:03 +0000 (09:58 +1000)
nv50_fb_trap() will now be called automagically by the mc intr handler,
rather than each engine's handler having to check for traps manually.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/fb.h
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c

index 1df010c..c28e6fb 100644 (file)
@@ -133,7 +133,6 @@ nva3_copy_intr(struct nouveau_subdev *subdev)
                nv_wr32(priv, 0x104004, stat);
        }
 
-       nv50_fb_trap(nouveau_fb(priv), 1);
        nouveau_engctx_put(engctx);
 }
 
index 10d12ad..2e04b96 100644 (file)
@@ -157,7 +157,6 @@ nv84_crypt_intr(struct nouveau_subdev *subdev)
        nv_wr32(priv, 0x102130, stat);
        nv_wr32(priv, 0x10200c, 0x10);
 
-       nv50_fb_trap(nouveau_fb(priv), 1);
        nouveau_engctx_put(engctx);
 }
 
index 0912b79..e7f6bb6 100644 (file)
@@ -135,7 +135,6 @@ nv98_crypt_intr(struct nouveau_subdev *subdev)
                nv_wr32(priv, 0x087004, stat);
        }
 
-       nv50_fb_trap(nouveau_fb(priv), 1);
        nouveau_engctx_put(engctx);
 }
 
index ea76e3e..1147aec 100644 (file)
@@ -525,7 +525,6 @@ nv04_fifo_intr(struct nouveau_subdev *subdev)
 
                if (device->card_type == NV_50) {
                        if (status & 0x00000010) {
-                               nv50_fb_trap(nouveau_fb(priv), 1);
                                status &= ~0x00000010;
                                nv_wr32(priv, 0x002100, 0x00000010);
                        }
index 0d67e86..07ca12f 100644 (file)
@@ -792,7 +792,6 @@ nv50_graph_intr(struct nouveau_subdev *subdev)
                nv_error(priv, "ch %d [0x%010llx] subc %d class 0x%04x "
                               "mthd 0x%04x data 0x%08x\n",
                         chid, (u64)inst << 12, subc, class, mthd, data);
-               nv50_fb_trap(nouveau_fb(priv), 1);
        }
 
        if (nv_rd32(priv, 0x400824) & (1 << 31))
index 8678a99..bc7d12b 100644 (file)
@@ -157,7 +157,6 @@ nv50_mpeg_intr(struct nouveau_subdev *subdev)
 
        nv_wr32(priv, 0x00b100, stat);
        nv_wr32(priv, 0x00b230, 0x00000001);
-       nv50_fb_trap(nouveau_fb(priv), 1);
 }
 
 static void
index 4cdd52a..da470e6 100644 (file)
@@ -167,6 +167,5 @@ void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
                       u32 pitch, u32 flags, struct nouveau_fb_tile *);
 
 void nv50_fb_vram_del(struct nouveau_fb *, struct nouveau_mem **);
-void nv50_fb_trap(struct nouveau_fb *, int display);
 
 #endif
index 2c1ee3f..487cb8c 100644 (file)
@@ -235,103 +235,6 @@ nv50_fb_vram_del(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
        kfree(mem);
 }
 
-static int
-nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
-            struct nouveau_oclass *oclass, void *data, u32 size,
-            struct nouveau_object **pobject)
-{
-       struct nouveau_device *device = nv_device(parent);
-       struct nv50_fb_priv *priv;
-       int ret;
-
-       ret = nouveau_fb_create(parent, engine, oclass, &priv);
-       *pobject = nv_object(priv);
-       if (ret)
-               return ret;
-
-       priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
-       if (priv->r100c08_page) {
-               priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
-                                            0, PAGE_SIZE,
-                                            PCI_DMA_BIDIRECTIONAL);
-               if (pci_dma_mapping_error(device->pdev, priv->r100c08))
-                       nv_warn(priv, "failed 0x100c08 page map\n");
-       } else {
-               nv_warn(priv, "failed 0x100c08 page alloc\n");
-       }
-
-       priv->base.memtype_valid = nv50_fb_memtype_valid;
-       priv->base.ram.init = nv50_fb_vram_init;
-       priv->base.ram.get = nv50_fb_vram_new;
-       priv->base.ram.put = nv50_fb_vram_del;
-       return nouveau_fb_preinit(&priv->base);
-}
-
-static void
-nv50_fb_dtor(struct nouveau_object *object)
-{
-       struct nouveau_device *device = nv_device(object);
-       struct nv50_fb_priv *priv = (void *)object;
-
-       if (priv->r100c08_page) {
-               pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE,
-                              PCI_DMA_BIDIRECTIONAL);
-               __free_page(priv->r100c08_page);
-       }
-
-       nouveau_fb_destroy(&priv->base);
-}
-
-static int
-nv50_fb_init(struct nouveau_object *object)
-{
-       struct nouveau_device *device = nv_device(object);
-       struct nv50_fb_priv *priv = (void *)object;
-       int ret;
-
-       ret = nouveau_fb_init(&priv->base);
-       if (ret)
-               return ret;
-
-       /* Not a clue what this is exactly.  Without pointing it at a
-        * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
-        * cause IOMMU "read from address 0" errors (rh#561267)
-        */
-       nv_wr32(priv, 0x100c08, priv->r100c08 >> 8);
-
-       /* This is needed to get meaningful information from 100c90
-        * on traps. No idea what these values mean exactly. */
-       switch (device->chipset) {
-       case 0x50:
-               nv_wr32(priv, 0x100c90, 0x000707ff);
-               break;
-       case 0xa3:
-       case 0xa5:
-       case 0xa8:
-               nv_wr32(priv, 0x100c90, 0x000d0fff);
-               break;
-       case 0xaf:
-               nv_wr32(priv, 0x100c90, 0x089d1fff);
-               break;
-       default:
-               nv_wr32(priv, 0x100c90, 0x001d07ff);
-               break;
-       }
-
-       return 0;
-}
-
-struct nouveau_oclass
-nv50_fb_oclass = {
-       .handle = NV_SUBDEV(FB, 0x50),
-       .ofuncs = &(struct nouveau_ofuncs) {
-               .ctor = nv50_fb_ctor,
-               .dtor = nv50_fb_dtor,
-               .init = nv50_fb_init,
-               .fini = _nouveau_fb_fini,
-       },
-};
-
 static const struct nouveau_enum vm_dispatch_subclients[] = {
        { 0x00000000, "GRCTX", NULL },
        { 0x00000001, "NOTIFY", NULL },
@@ -427,11 +330,11 @@ static const struct nouveau_enum vm_fault[] = {
        {}
 };
 
-void
-nv50_fb_trap(struct nouveau_fb *pfb, int display)
+static void
+nv50_fb_intr(struct nouveau_subdev *subdev)
 {
-       struct nouveau_device *device = nv_device(pfb);
-       struct nv50_fb_priv *priv = (void *)pfb;
+       struct nouveau_device *device = nv_device(subdev);
+       struct nv50_fb_priv *priv = (void *)subdev;
        const struct nouveau_enum *en, *cl;
        u32 trap[6], idx, chan;
        u8 st0, st1, st2, st3;
@@ -448,9 +351,6 @@ nv50_fb_trap(struct nouveau_fb *pfb, int display)
        }
        nv_wr32(priv, 0x100c90, idx | 0x80000000);
 
-       if (!display)
-               return;
-
        /* decode status bits into something more useful */
        if (device->chipset  < 0xa3 ||
            device->chipset == 0xaa || device->chipset == 0xac) {
@@ -497,3 +397,101 @@ nv50_fb_trap(struct nouveau_fb *pfb, int display)
        else
                printk("0x%08x\n", st1);
 }
+
+static int
+nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
+            struct nouveau_oclass *oclass, void *data, u32 size,
+            struct nouveau_object **pobject)
+{
+       struct nouveau_device *device = nv_device(parent);
+       struct nv50_fb_priv *priv;
+       int ret;
+
+       ret = nouveau_fb_create(parent, engine, oclass, &priv);
+       *pobject = nv_object(priv);
+       if (ret)
+               return ret;
+
+       priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+       if (priv->r100c08_page) {
+               priv->r100c08 = pci_map_page(device->pdev, priv->r100c08_page,
+                                            0, PAGE_SIZE,
+                                            PCI_DMA_BIDIRECTIONAL);
+               if (pci_dma_mapping_error(device->pdev, priv->r100c08))
+                       nv_warn(priv, "failed 0x100c08 page map\n");
+       } else {
+               nv_warn(priv, "failed 0x100c08 page alloc\n");
+       }
+
+       priv->base.memtype_valid = nv50_fb_memtype_valid;
+       priv->base.ram.init = nv50_fb_vram_init;
+       priv->base.ram.get = nv50_fb_vram_new;
+       priv->base.ram.put = nv50_fb_vram_del;
+       nv_subdev(priv)->intr = nv50_fb_intr;
+       return nouveau_fb_preinit(&priv->base);
+}
+
+static void
+nv50_fb_dtor(struct nouveau_object *object)
+{
+       struct nouveau_device *device = nv_device(object);
+       struct nv50_fb_priv *priv = (void *)object;
+
+       if (priv->r100c08_page) {
+               pci_unmap_page(device->pdev, priv->r100c08, PAGE_SIZE,
+                              PCI_DMA_BIDIRECTIONAL);
+               __free_page(priv->r100c08_page);
+       }
+
+       nouveau_fb_destroy(&priv->base);
+}
+
+static int
+nv50_fb_init(struct nouveau_object *object)
+{
+       struct nouveau_device *device = nv_device(object);
+       struct nv50_fb_priv *priv = (void *)object;
+       int ret;
+
+       ret = nouveau_fb_init(&priv->base);
+       if (ret)
+               return ret;
+
+       /* Not a clue what this is exactly.  Without pointing it at a
+        * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
+        * cause IOMMU "read from address 0" errors (rh#561267)
+        */
+       nv_wr32(priv, 0x100c08, priv->r100c08 >> 8);
+
+       /* This is needed to get meaningful information from 100c90
+        * on traps. No idea what these values mean exactly. */
+       switch (device->chipset) {
+       case 0x50:
+               nv_wr32(priv, 0x100c90, 0x000707ff);
+               break;
+       case 0xa3:
+       case 0xa5:
+       case 0xa8:
+               nv_wr32(priv, 0x100c90, 0x000d0fff);
+               break;
+       case 0xaf:
+               nv_wr32(priv, 0x100c90, 0x089d1fff);
+               break;
+       default:
+               nv_wr32(priv, 0x100c90, 0x001d07ff);
+               break;
+       }
+
+       return 0;
+}
+
+struct nouveau_oclass
+nv50_fb_oclass = {
+       .handle = NV_SUBDEV(FB, 0x50),
+       .ofuncs = &(struct nouveau_ofuncs) {
+               .ctor = nv50_fb_ctor,
+               .dtor = nv50_fb_dtor,
+               .init = nv50_fb_init,
+               .fini = _nouveau_fb_fini,
+       },
+};
index cedf33b..8d759f8 100644 (file)
@@ -39,6 +39,7 @@ nv50_mc_intr[] = {
        { 0x00200000, NVDEV_SUBDEV_GPIO },
        { 0x04000000, NVDEV_ENGINE_DISP },
        { 0x80000000, NVDEV_ENGINE_SW },
+       { 0x0000d101, NVDEV_SUBDEV_FB },
        {},
 };
 
index a001e4c..ceb5c83 100644 (file)
@@ -40,6 +40,7 @@ nv98_mc_intr[] = {
        { 0x00400000, NVDEV_ENGINE_COPY0 },     /* NVA3-     */
        { 0x04000000, NVDEV_ENGINE_DISP },
        { 0x80000000, NVDEV_ENGINE_SW },
+       { 0x0040d101, NVDEV_SUBDEV_FB },
        {},
 };