1304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki#include "drmP.h" 2304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki#include "drm.h" 3304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki#include "nouveau_drv.h" 4304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki#include "nouveau_drm.h" 5304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki 620f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggsstruct nv50_fb_priv { 720f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs struct page *r100c08_page; 820f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs dma_addr_t r100c08; 920f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs}; 1020f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 118f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggsstatic void 128f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggsnv50_fb_destroy(struct drm_device *dev) 138f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs{ 148f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 158f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; 168f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs struct nv50_fb_priv *priv = pfb->priv; 178f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs 188f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs if (drm_mm_initialized(&pfb->tag_heap)) 198f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs drm_mm_takedown(&pfb->tag_heap); 208f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs 218f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs if (priv->r100c08_page) { 228f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE, 238f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs PCI_DMA_BIDIRECTIONAL); 248f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs __free_page(priv->r100c08_page); 258f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs } 268f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs 278f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs kfree(priv); 288f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs pfb->priv = NULL; 298f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs} 308f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs 3120f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggsstatic int 3220f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggsnv50_fb_create(struct drm_device *dev) 3320f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs{ 3420f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 358f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; 3620f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs struct nv50_fb_priv *priv; 378f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs u32 tagmem; 388f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs int ret; 3920f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 4020f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs priv = kzalloc(sizeof(*priv), GFP_KERNEL); 4120f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs if (!priv) 4220f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs return -ENOMEM; 438f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs pfb->priv = priv; 4420f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 4520f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO); 4620f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs if (!priv->r100c08_page) { 478f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs nv50_fb_destroy(dev); 4820f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs return -ENOMEM; 4920f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs } 5020f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 5120f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0, 5220f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); 5320f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) { 548f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs nv50_fb_destroy(dev); 5520f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs return -EFAULT; 5620f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs } 5720f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 588f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs tagmem = nv_rd32(dev, 0x100320); 598f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs NV_DEBUG(dev, "%d tags available\n", tagmem); 608f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs ret = drm_mm_init(&pfb->tag_heap, 0, tagmem); 618f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs if (ret) { 628f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs nv50_fb_destroy(dev); 638f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs return ret; 648f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs } 658f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs 6620f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs return 0; 6720f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs} 6820f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 69304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnickiint 70304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnickinv50_fb_init(struct drm_device *dev) 71304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki{ 72304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki struct drm_nouveau_private *dev_priv = dev->dev_private; 7320f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs struct nv50_fb_priv *priv; 7420f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs int ret; 7520f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs 7620f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs if (!dev_priv->engine.fb.priv) { 7720f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs ret = nv50_fb_create(dev); 7820f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs if (ret) 7920f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs return ret; 8020f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs } 8120f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs priv = dev_priv->engine.fb.priv; 82304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki 834eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs /* Not a clue what this is exactly. Without pointing it at a 844eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs * scratch page, VRAM->GART blits with M2MF (as in DDX DFS) 854eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs * cause IOMMU "read from address 0" errors (rh#561267) 864eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs */ 8720f63afe988a25b0a4d991e87b41f76ee14e2a84Ben Skeggs nv_wr32(dev, 0x100c08, priv->r100c08 >> 8); 884eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs 894eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs /* This is needed to get meaningful information from 100c90 904eb3033c72099fab3536ed8ac54a5dc99f0832d7Ben Skeggs * on traps. No idea what these values mean exactly. */ 91304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki switch (dev_priv->chipset) { 92304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki case 0x50: 939fea1bcbff037cb61f71e0d699180030b1f509a5Ben Skeggs nv_wr32(dev, 0x100c90, 0x000707ff); 94304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki break; 95f9aafdd30ef8356f0a3690bf9bdd9c6e51b7705cBen Skeggs case 0xa3: 96304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki case 0xa5: 97304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki case 0xa8: 989fea1bcbff037cb61f71e0d699180030b1f509a5Ben Skeggs nv_wr32(dev, 0x100c90, 0x000d0fff); 999fea1bcbff037cb61f71e0d699180030b1f509a5Ben Skeggs break; 1009fea1bcbff037cb61f71e0d699180030b1f509a5Ben Skeggs case 0xaf: 1019fea1bcbff037cb61f71e0d699180030b1f509a5Ben Skeggs nv_wr32(dev, 0x100c90, 0x089d1fff); 102304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki break; 103304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki default: 1049fea1bcbff037cb61f71e0d699180030b1f509a5Ben Skeggs nv_wr32(dev, 0x100c90, 0x001d07ff); 105304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki break; 106304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki } 107304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki 108304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki return 0; 109304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki} 110304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki 111304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnickivoid 112304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnickinv50_fb_takedown(struct drm_device *dev) 113304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki{ 1148f7286f8e4e80f7b868ba3d117ae900f0d207cbeBen Skeggs nv50_fb_destroy(dev); 115304424e17dd904cef048ef8966d9f54618a915ccMarcin Kościelnicki} 116d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 117312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_dispatch_subclients[] = { 118312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "GRCTX", NULL }, 119312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "NOTIFY", NULL }, 120312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000002, "QUERY", NULL }, 121312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000003, "COND", NULL }, 122312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000004, "M2M_IN", NULL }, 123312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000005, "M2M_OUT", NULL }, 124312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000006, "M2M_NOTIFY", NULL }, 125312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 126312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 127312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 128312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_ccache_subclients[] = { 129312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "CB", NULL }, 130312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "TIC", NULL }, 131312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000002, "TSC", NULL }, 132312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 133312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 134312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 135312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_prop_subclients[] = { 136312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "RT0", NULL }, 137312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "RT1", NULL }, 138312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000002, "RT2", NULL }, 139312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000003, "RT3", NULL }, 140312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000004, "RT4", NULL }, 141312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000005, "RT5", NULL }, 142312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000006, "RT6", NULL }, 143312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000007, "RT7", NULL }, 144312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000008, "ZETA", NULL }, 145312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000009, "LOCAL", NULL }, 146312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000a, "GLOBAL", NULL }, 147312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000b, "STACK", NULL }, 148312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000c, "DST2D", NULL }, 149312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 150312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 151312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 152312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_pfifo_subclients[] = { 153312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "PUSHBUF", NULL }, 154312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "SEMAPHORE", NULL }, 155312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 156312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 157312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 158312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_bar_subclients[] = { 159312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "FB", NULL }, 160312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "IN", NULL }, 161312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 162312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 163312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 164312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_client[] = { 165312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "STRMOUT", NULL }, 166312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000003, "DISPATCH", vm_dispatch_subclients }, 167312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000004, "PFIFO_WRITE", NULL }, 168312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000005, "CCACHE", vm_ccache_subclients }, 169312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000006, "PPPP", NULL }, 170312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000007, "CLIPID", NULL }, 171312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000008, "PFIFO_READ", NULL }, 172312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000009, "VFETCH", NULL }, 173312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000a, "TEXTURE", NULL }, 174312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000b, "PROP", vm_prop_subclients }, 175312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000c, "PVP", NULL }, 176312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000d, "PBSP", NULL }, 177312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000e, "PCRYPT", NULL }, 178312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000f, "PCOUNTER", NULL }, 179312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000011, "PDAEMON", NULL }, 180312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 181312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 182312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 183312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_engine[] = { 184312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "PGRAPH", NULL }, 185312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "PVP", NULL }, 186312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000004, "PEEPHOLE", NULL }, 187312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000005, "PFIFO", vm_pfifo_subclients }, 188312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000006, "BAR", vm_bar_subclients }, 189312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000008, "PPPP", NULL }, 190312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000009, "PBSP", NULL }, 191312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000a, "PCRYPT", NULL }, 192312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000b, "PCOUNTER", NULL }, 193312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000c, "SEMAPHORE_BG", NULL }, 194312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000d, "PCOPY", NULL }, 195312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000e, "PDAEMON", NULL }, 196312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 197312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 198312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 199312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggsstatic struct nouveau_enum vm_fault[] = { 200312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000000, "PT_NOT_PRESENT", NULL }, 201312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000001, "PT_TOO_SHORT", NULL }, 202312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000002, "PAGE_NOT_PRESENT", NULL }, 203312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000003, "PAGE_SYSTEM_ONLY", NULL }, 204312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000004, "PAGE_READ_ONLY", NULL }, 205312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000006, "NULL_DMAOBJ", NULL }, 206312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x00000007, "WRONG_MEMTYPE", NULL }, 207312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000b, "VRAM_LIMIT", NULL }, 208312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs { 0x0000000f, "DMAOBJ_LIMIT", NULL }, 209312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs {} 210312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs}; 211312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 212d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggsvoid 2136fdb383e81a644a244299d635de5eb30ed401278Ben Skeggsnv50_fb_vm_trap(struct drm_device *dev, int display) 214d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs{ 215d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs struct drm_nouveau_private *dev_priv = dev->dev_private; 216312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs const struct nouveau_enum *en, *cl; 217cff5c1332486ced8ff4180e957e04983cb72a39eBen Skeggs unsigned long flags; 218d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs u32 trap[6], idx, chinst; 219312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs u8 st0, st1, st2, st3; 220d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs int i, ch; 221d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 222d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs idx = nv_rd32(dev, 0x100c90); 223d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs if (!(idx & 0x80000000)) 224d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs return; 225d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs idx &= 0x00ffffff; 226d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 227d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs for (i = 0; i < 6; i++) { 228d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs nv_wr32(dev, 0x100c90, idx | i << 24); 229d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs trap[i] = nv_rd32(dev, 0x100c94); 230d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs } 231d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs nv_wr32(dev, 0x100c90, idx | 0x80000000); 232d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 233d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs if (!display) 234d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs return; 235d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 236312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs /* lookup channel id */ 237d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs chinst = (trap[2] << 16) | trap[1]; 238cff5c1332486ced8ff4180e957e04983cb72a39eBen Skeggs spin_lock_irqsave(&dev_priv->channels.lock, flags); 239d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { 240cff5c1332486ced8ff4180e957e04983cb72a39eBen Skeggs struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; 241d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 242d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs if (!chan || !chan->ramin) 243d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs continue; 244d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 245d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs if (chinst == chan->ramin->vinst >> 12) 246d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs break; 247d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs } 248cff5c1332486ced8ff4180e957e04983cb72a39eBen Skeggs spin_unlock_irqrestore(&dev_priv->channels.lock, flags); 249d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs 250312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs /* decode status bits into something more useful */ 251312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs if (dev_priv->chipset < 0xa3 || 252312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { 253312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st0 = (trap[0] & 0x0000000f) >> 0; 254312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st1 = (trap[0] & 0x000000f0) >> 4; 255312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st2 = (trap[0] & 0x00000f00) >> 8; 256312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st3 = (trap[0] & 0x0000f000) >> 12; 257312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs } else { 258312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st0 = (trap[0] & 0x000000ff) >> 0; 259312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st1 = (trap[0] & 0x0000ff00) >> 8; 260312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st2 = (trap[0] & 0x00ff0000) >> 16; 261312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs st3 = (trap[0] & 0xff000000) >> 24; 262312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs } 263312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 264312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ", 265312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs (trap[5] & 0x00000100) ? "read" : "write", 266312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst); 267312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 268312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs en = nouveau_enum_find(vm_engine, st0); 269312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs if (en) 270312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%s/", en->name); 271312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs else 272312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%02x/", st0); 273312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 274312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs cl = nouveau_enum_find(vm_client, st2); 275312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs if (cl) 276312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%s/", cl->name); 277312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs else 278312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%02x/", st2); 279312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 280312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); 281312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs else if (en && en->data) cl = nouveau_enum_find(en->data, st3); 282312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs else cl = NULL; 283312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs if (cl) 284312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%s", cl->name); 285312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs else 286312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%02x", st3); 287312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs 288312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk(" reason: "); 289312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs en = nouveau_enum_find(vm_fault, st1); 290312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs if (en) 291312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("%s\n", en->name); 292312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs else 293312d1d5fe9b832899b02c620c143bc7eb5a3bdb1Ben Skeggs printk("0x%08x\n", st1); 294d96773e7b61d9976b8227e018a1c94fb7374e641Ben Skeggs} 295