From 874309a5b77f40915369af01cebd18db695d68ae Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 22 Nov 2012 12:57:32 +1000 Subject: [PATCH] drm/nv50/fb: implement trap handler as subdev interrupt handler 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 --- drivers/gpu/drm/nouveau/core/engine/copy/nva3.c | 1 - drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c | 1 - drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c | 1 - drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c | 1 - drivers/gpu/drm/nouveau/core/engine/graph/nv50.c | 1 - drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c | 1 - drivers/gpu/drm/nouveau/core/include/subdev/fb.h | 1 - drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | 206 +++++++++++------------ drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c | 1 + drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | 1 + 10 files changed, 104 insertions(+), 111 deletions(-) diff --git a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index 1df010c..c28e6fb 100644 --- a/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 10d12ad..2e04b96 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index 0912b79..e7f6bb6 100644 --- a/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index ea76e3e..1147aec 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index 0d67e86a8..07ca12f 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -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)) diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c index 8678a99..bc7d12b3 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv50.c @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h index 4cdd52a..da470e6 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h @@ -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 diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 2c1ee3f..487cb8c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -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, + }, +}; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index cedf33b..8d759f83 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c @@ -39,6 +39,7 @@ nv50_mc_intr[] = { { 0x00200000, NVDEV_SUBDEV_GPIO }, { 0x04000000, NVDEV_ENGINE_DISP }, { 0x80000000, NVDEV_ENGINE_SW }, + { 0x0000d101, NVDEV_SUBDEV_FB }, {}, }; diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index a001e4c4..ceb5c83 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c @@ -40,6 +40,7 @@ nv98_mc_intr[] = { { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */ { 0x04000000, NVDEV_ENGINE_DISP }, { 0x80000000, NVDEV_ENGINE_SW }, + { 0x0040d101, NVDEV_SUBDEV_FB }, {}, }; -- 2.7.4