3 #include "nouveau_drv.h"
4 #include "nouveau_drm.h"
7 struct page
*r100c08_page
;
12 nv50_fb_destroy(struct drm_device
*dev
)
14 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
15 struct nouveau_fb_engine
*pfb
= &dev_priv
->engine
.fb
;
16 struct nv50_fb_priv
*priv
= pfb
->priv
;
18 if (drm_mm_initialized(&pfb
->tag_heap
))
19 drm_mm_takedown(&pfb
->tag_heap
);
21 if (priv
->r100c08_page
) {
22 pci_unmap_page(dev
->pdev
, priv
->r100c08
, PAGE_SIZE
,
23 PCI_DMA_BIDIRECTIONAL
);
24 __free_page(priv
->r100c08_page
);
32 nv50_fb_create(struct drm_device
*dev
)
34 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
35 struct nouveau_fb_engine
*pfb
= &dev_priv
->engine
.fb
;
36 struct nv50_fb_priv
*priv
;
40 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
45 priv
->r100c08_page
= alloc_page(GFP_KERNEL
| __GFP_ZERO
);
46 if (!priv
->r100c08_page
) {
51 priv
->r100c08
= pci_map_page(dev
->pdev
, priv
->r100c08_page
, 0,
52 PAGE_SIZE
, PCI_DMA_BIDIRECTIONAL
);
53 if (pci_dma_mapping_error(dev
->pdev
, priv
->r100c08
)) {
58 tagmem
= nv_rd32(dev
, 0x100320);
59 NV_DEBUG(dev
, "%d tags available\n", tagmem
);
60 ret
= drm_mm_init(&pfb
->tag_heap
, 0, tagmem
);
70 nv50_fb_init(struct drm_device
*dev
)
72 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
73 struct nv50_fb_priv
*priv
;
76 if (!dev_priv
->engine
.fb
.priv
) {
77 ret
= nv50_fb_create(dev
);
81 priv
= dev_priv
->engine
.fb
.priv
;
83 /* Not a clue what this is exactly. Without pointing it at a
84 * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
85 * cause IOMMU "read from address 0" errors (rh#561267)
87 nv_wr32(dev
, 0x100c08, priv
->r100c08
>> 8);
89 /* This is needed to get meaningful information from 100c90
90 * on traps. No idea what these values mean exactly. */
91 switch (dev_priv
->chipset
) {
93 nv_wr32(dev
, 0x100c90, 0x000707ff);
98 nv_wr32(dev
, 0x100c90, 0x000d0fff);
101 nv_wr32(dev
, 0x100c90, 0x089d1fff);
104 nv_wr32(dev
, 0x100c90, 0x001d07ff);
112 nv50_fb_takedown(struct drm_device
*dev
)
114 nv50_fb_destroy(dev
);
117 static struct nouveau_enum vm_dispatch_subclients
[] = {
118 { 0x00000000, "GRCTX", NULL
},
119 { 0x00000001, "NOTIFY", NULL
},
120 { 0x00000002, "QUERY", NULL
},
121 { 0x00000003, "COND", NULL
},
122 { 0x00000004, "M2M_IN", NULL
},
123 { 0x00000005, "M2M_OUT", NULL
},
124 { 0x00000006, "M2M_NOTIFY", NULL
},
128 static struct nouveau_enum vm_ccache_subclients
[] = {
129 { 0x00000000, "CB", NULL
},
130 { 0x00000001, "TIC", NULL
},
131 { 0x00000002, "TSC", NULL
},
135 static struct nouveau_enum vm_prop_subclients
[] = {
136 { 0x00000000, "RT0", NULL
},
137 { 0x00000001, "RT1", NULL
},
138 { 0x00000002, "RT2", NULL
},
139 { 0x00000003, "RT3", NULL
},
140 { 0x00000004, "RT4", NULL
},
141 { 0x00000005, "RT5", NULL
},
142 { 0x00000006, "RT6", NULL
},
143 { 0x00000007, "RT7", NULL
},
144 { 0x00000008, "ZETA", NULL
},
145 { 0x00000009, "LOCAL", NULL
},
146 { 0x0000000a, "GLOBAL", NULL
},
147 { 0x0000000b, "STACK", NULL
},
148 { 0x0000000c, "DST2D", NULL
},
152 static struct nouveau_enum vm_pfifo_subclients
[] = {
153 { 0x00000000, "PUSHBUF", NULL
},
154 { 0x00000001, "SEMAPHORE", NULL
},
158 static struct nouveau_enum vm_bar_subclients
[] = {
159 { 0x00000000, "FB", NULL
},
160 { 0x00000001, "IN", NULL
},
164 static struct nouveau_enum vm_client
[] = {
165 { 0x00000000, "STRMOUT", NULL
},
166 { 0x00000003, "DISPATCH", vm_dispatch_subclients
},
167 { 0x00000004, "PFIFO_WRITE", NULL
},
168 { 0x00000005, "CCACHE", vm_ccache_subclients
},
169 { 0x00000006, "PPPP", NULL
},
170 { 0x00000007, "CLIPID", NULL
},
171 { 0x00000008, "PFIFO_READ", NULL
},
172 { 0x00000009, "VFETCH", NULL
},
173 { 0x0000000a, "TEXTURE", NULL
},
174 { 0x0000000b, "PROP", vm_prop_subclients
},
175 { 0x0000000c, "PVP", NULL
},
176 { 0x0000000d, "PBSP", NULL
},
177 { 0x0000000e, "PCRYPT", NULL
},
178 { 0x0000000f, "PCOUNTER", NULL
},
179 { 0x00000011, "PDAEMON", NULL
},
183 static struct nouveau_enum vm_engine
[] = {
184 { 0x00000000, "PGRAPH", NULL
},
185 { 0x00000001, "PVP", NULL
},
186 { 0x00000004, "PEEPHOLE", NULL
},
187 { 0x00000005, "PFIFO", vm_pfifo_subclients
},
188 { 0x00000006, "BAR", vm_bar_subclients
},
189 { 0x00000008, "PPPP", NULL
},
190 { 0x00000009, "PBSP", NULL
},
191 { 0x0000000a, "PCRYPT", NULL
},
192 { 0x0000000b, "PCOUNTER", NULL
},
193 { 0x0000000c, "SEMAPHORE_BG", NULL
},
194 { 0x0000000d, "PCOPY", NULL
},
195 { 0x0000000e, "PDAEMON", NULL
},
199 static struct nouveau_enum vm_fault
[] = {
200 { 0x00000000, "PT_NOT_PRESENT", NULL
},
201 { 0x00000001, "PT_TOO_SHORT", NULL
},
202 { 0x00000002, "PAGE_NOT_PRESENT", NULL
},
203 { 0x00000003, "PAGE_SYSTEM_ONLY", NULL
},
204 { 0x00000004, "PAGE_READ_ONLY", NULL
},
205 { 0x00000006, "NULL_DMAOBJ", NULL
},
206 { 0x00000007, "WRONG_MEMTYPE", NULL
},
207 { 0x0000000b, "VRAM_LIMIT", NULL
},
208 { 0x0000000f, "DMAOBJ_LIMIT", NULL
},
213 nv50_fb_vm_trap(struct drm_device
*dev
, int display
)
215 struct drm_nouveau_private
*dev_priv
= dev
->dev_private
;
216 const struct nouveau_enum
*en
, *cl
;
218 u32 trap
[6], idx
, chinst
;
219 u8 st0
, st1
, st2
, st3
;
222 idx
= nv_rd32(dev
, 0x100c90);
223 if (!(idx
& 0x80000000))
227 for (i
= 0; i
< 6; i
++) {
228 nv_wr32(dev
, 0x100c90, idx
| i
<< 24);
229 trap
[i
] = nv_rd32(dev
, 0x100c94);
231 nv_wr32(dev
, 0x100c90, idx
| 0x80000000);
236 /* lookup channel id */
237 chinst
= (trap
[2] << 16) | trap
[1];
238 spin_lock_irqsave(&dev_priv
->channels
.lock
, flags
);
239 for (ch
= 0; ch
< dev_priv
->engine
.fifo
.channels
; ch
++) {
240 struct nouveau_channel
*chan
= dev_priv
->channels
.ptr
[ch
];
242 if (!chan
|| !chan
->ramin
)
245 if (chinst
== chan
->ramin
->vinst
>> 12)
248 spin_unlock_irqrestore(&dev_priv
->channels
.lock
, flags
);
250 /* decode status bits into something more useful */
251 if (dev_priv
->chipset
< 0xa3 ||
252 dev_priv
->chipset
== 0xaa || dev_priv
->chipset
== 0xac) {
253 st0
= (trap
[0] & 0x0000000f) >> 0;
254 st1
= (trap
[0] & 0x000000f0) >> 4;
255 st2
= (trap
[0] & 0x00000f00) >> 8;
256 st3
= (trap
[0] & 0x0000f000) >> 12;
258 st0
= (trap
[0] & 0x000000ff) >> 0;
259 st1
= (trap
[0] & 0x0000ff00) >> 8;
260 st2
= (trap
[0] & 0x00ff0000) >> 16;
261 st3
= (trap
[0] & 0xff000000) >> 24;
264 NV_INFO(dev
, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ",
265 (trap
[5] & 0x00000100) ? "read" : "write",
266 trap
[5] & 0xff, trap
[4] & 0xffff, trap
[3] & 0xffff, ch
, chinst
);
268 en
= nouveau_enum_find(vm_engine
, st0
);
270 printk("%s/", en
->name
);
272 printk("%02x/", st0
);
274 cl
= nouveau_enum_find(vm_client
, st2
);
276 printk("%s/", cl
->name
);
278 printk("%02x/", st2
);
280 if (cl
&& cl
->data
) cl
= nouveau_enum_find(cl
->data
, st3
);
281 else if (en
&& en
->data
) cl
= nouveau_enum_find(en
->data
, st3
);
284 printk("%s", cl
->name
);
289 en
= nouveau_enum_find(vm_fault
, st1
);
291 printk("%s\n", en
->name
);
293 printk("0x%08x\n", st1
);