diff options
author | Dave Airlie <airlied@redhat.com> | 2011-03-14 19:59:31 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-03-14 19:59:31 -0400 |
commit | 235b87afbcadf46e5ca042b2e7a977a41ebce9dd (patch) | |
tree | 3dd7102ae63435e3ed30357609710ac45780766f /drivers/gpu | |
parent | bcd5023c961a44c7149936553b6929b2b233dd27 (diff) | |
parent | bd35fe5a7930bf83ed56422ea4e4b6471ee6f739 (diff) |
Merge remote branch 'nouveau/drm-nouveau-next' of ../drm-nouveau-next into drm-core-next
* 'nouveau/drm-nouveau-next' of ../drm-nouveau-next:
drm/nouveau: fix __nouveau_fence_wait performance
drm/nv40: attempt to reserve just enough vram for all 32 channels
drm/nv50: check for vm traps on every gr irq
drm/nv50: decode vm faults some more
drm/nouveau: add nouveau_enum_find() util function
drm/nouveau: properly handle pushbuffer check failures
drm/nvc0: remove vm hack forcing large/small pages to not share a PDE
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mem.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_sgdma.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_util.c | 23 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_util.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_vm.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_fifo.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_fb.c | 150 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_graph.c | 95 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_crypt.c | 2 |
12 files changed, 257 insertions, 92 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 00aff226397d..8efefed58c15 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -1076,7 +1076,7 @@ extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); | |||
1076 | /* nv50_fb.c */ | 1076 | /* nv50_fb.c */ |
1077 | extern int nv50_fb_init(struct drm_device *); | 1077 | extern int nv50_fb_init(struct drm_device *); |
1078 | extern void nv50_fb_takedown(struct drm_device *); | 1078 | extern void nv50_fb_takedown(struct drm_device *); |
1079 | extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *); | 1079 | extern void nv50_fb_vm_trap(struct drm_device *, int display); |
1080 | 1080 | ||
1081 | /* nvc0_fb.c */ | 1081 | /* nvc0_fb.c */ |
1082 | extern int nvc0_fb_init(struct drm_device *); | 1082 | extern int nvc0_fb_init(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index a244702bb227..4b9f4493c9f9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include "drmP.h" | 27 | #include "drmP.h" |
28 | #include "drm.h" | 28 | #include "drm.h" |
29 | 29 | ||
30 | #include <linux/ktime.h> | ||
31 | #include <linux/hrtimer.h> | ||
32 | |||
30 | #include "nouveau_drv.h" | 33 | #include "nouveau_drv.h" |
31 | #include "nouveau_ramht.h" | 34 | #include "nouveau_ramht.h" |
32 | #include "nouveau_dma.h" | 35 | #include "nouveau_dma.h" |
@@ -229,7 +232,8 @@ int | |||
229 | __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | 232 | __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) |
230 | { | 233 | { |
231 | unsigned long timeout = jiffies + (3 * DRM_HZ); | 234 | unsigned long timeout = jiffies + (3 * DRM_HZ); |
232 | unsigned long sleep_time = jiffies + 1; | 235 | unsigned long sleep_time = NSEC_PER_MSEC / 1000; |
236 | ktime_t t; | ||
233 | int ret = 0; | 237 | int ret = 0; |
234 | 238 | ||
235 | while (1) { | 239 | while (1) { |
@@ -243,8 +247,13 @@ __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr) | |||
243 | 247 | ||
244 | __set_current_state(intr ? TASK_INTERRUPTIBLE | 248 | __set_current_state(intr ? TASK_INTERRUPTIBLE |
245 | : TASK_UNINTERRUPTIBLE); | 249 | : TASK_UNINTERRUPTIBLE); |
246 | if (lazy && time_after_eq(jiffies, sleep_time)) | 250 | if (lazy) { |
247 | schedule_timeout(1); | 251 | t = ktime_set(0, sleep_time); |
252 | schedule_hrtimeout(&t, HRTIMER_MODE_REL); | ||
253 | sleep_time *= 2; | ||
254 | if (sleep_time > NSEC_PER_MSEC) | ||
255 | sleep_time = NSEC_PER_MSEC; | ||
256 | } | ||
248 | 257 | ||
249 | if (intr && signal_pending(current)) { | 258 | if (intr && signal_pending(current)) { |
250 | ret = -ERESTARTSYS; | 259 | ret = -ERESTARTSYS; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 3ce58d2222cb..e8b04f4aed7e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -600,7 +600,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
600 | if (push[i].bo_index >= req->nr_buffers) { | 600 | if (push[i].bo_index >= req->nr_buffers) { |
601 | NV_ERROR(dev, "push %d buffer not in list\n", i); | 601 | NV_ERROR(dev, "push %d buffer not in list\n", i); |
602 | ret = -EINVAL; | 602 | ret = -EINVAL; |
603 | goto out; | 603 | goto out_prevalid; |
604 | } | 604 | } |
605 | 605 | ||
606 | bo[push[i].bo_index].read_domains |= (1 << 31); | 606 | bo[push[i].bo_index].read_domains |= (1 << 31); |
@@ -612,7 +612,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
612 | if (ret) { | 612 | if (ret) { |
613 | if (ret != -ERESTARTSYS) | 613 | if (ret != -ERESTARTSYS) |
614 | NV_ERROR(dev, "validate: %d\n", ret); | 614 | NV_ERROR(dev, "validate: %d\n", ret); |
615 | goto out; | 615 | goto out_prevalid; |
616 | } | 616 | } |
617 | 617 | ||
618 | /* Apply any relocations that are required */ | 618 | /* Apply any relocations that are required */ |
@@ -705,6 +705,8 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
705 | out: | 705 | out: |
706 | validate_fini(&op, fence); | 706 | validate_fini(&op, fence); |
707 | nouveau_fence_unref(&fence); | 707 | nouveau_fence_unref(&fence); |
708 | |||
709 | out_prevalid: | ||
708 | kfree(bo); | 710 | kfree(bo); |
709 | kfree(push); | 711 | kfree(push); |
710 | 712 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 63b9040b5f30..02b48d183f4a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -424,14 +424,32 @@ nouveau_mem_vram_init(struct drm_device *dev) | |||
424 | } | 424 | } |
425 | 425 | ||
426 | /* reserve space at end of VRAM for PRAMIN */ | 426 | /* reserve space at end of VRAM for PRAMIN */ |
427 | if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 || | 427 | if (dev_priv->card_type >= NV_50) { |
428 | dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) | 428 | dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; |
429 | dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024); | 429 | } else |
430 | else | 430 | if (dev_priv->card_type >= NV_40) { |
431 | if (dev_priv->card_type >= NV_40) | 431 | u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); |
432 | dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024); | 432 | u32 rsvd; |
433 | else | 433 | |
434 | dev_priv->ramin_rsvd_vram = (512 * 1024); | 434 | /* estimate grctx size, the magics come from nv40_grctx.c */ |
435 | if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; | ||
436 | else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; | ||
437 | else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; | ||
438 | else rsvd = 0x4a40 * vs; | ||
439 | rsvd += 16 * 1024; | ||
440 | rsvd *= dev_priv->engine.fifo.channels; | ||
441 | |||
442 | /* pciegart table */ | ||
443 | if (drm_pci_device_is_pcie(dev)) | ||
444 | rsvd += 512 * 1024; | ||
445 | |||
446 | /* object storage */ | ||
447 | rsvd += 512 * 1024; | ||
448 | |||
449 | dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); | ||
450 | } else { | ||
451 | dev_priv->ramin_rsvd_vram = 512 * 1024; | ||
452 | } | ||
435 | 453 | ||
436 | ret = dev_priv->engine.vram.init(dev); | 454 | ret = dev_priv->engine.vram.init(dev); |
437 | if (ret) | 455 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 1205f0f345b9..a33fe4019286 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c | |||
@@ -427,8 +427,7 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
427 | u32 aper_size, align; | 427 | u32 aper_size, align; |
428 | int ret; | 428 | int ret; |
429 | 429 | ||
430 | if (dev_priv->card_type >= NV_50 || | 430 | if (dev_priv->card_type >= NV_50 || drm_pci_device_is_pcie(dev)) |
431 | dev_priv->ramin_rsvd_vram >= 2 * 1024 * 1024) | ||
432 | aper_size = 512 * 1024 * 1024; | 431 | aper_size = 512 * 1024 * 1024; |
433 | else | 432 | else |
434 | aper_size = 64 * 1024 * 1024; | 433 | aper_size = 64 * 1024 * 1024; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.c b/drivers/gpu/drm/nouveau/nouveau_util.c index fbe0fb13bc1e..e51b51503baa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.c +++ b/drivers/gpu/drm/nouveau/nouveau_util.c | |||
@@ -47,18 +47,27 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) | |||
47 | printk(" (unknown bits 0x%08x)", value); | 47 | printk(" (unknown bits 0x%08x)", value); |
48 | } | 48 | } |
49 | 49 | ||
50 | void | 50 | const struct nouveau_enum * |
51 | nouveau_enum_print(const struct nouveau_enum *en, u32 value) | 51 | nouveau_enum_find(const struct nouveau_enum *en, u32 value) |
52 | { | 52 | { |
53 | while (en->name) { | 53 | while (en->name) { |
54 | if (value == en->value) { | 54 | if (en->value == value) |
55 | printk("%s", en->name); | 55 | return en; |
56 | return; | ||
57 | } | ||
58 | |||
59 | en++; | 56 | en++; |
60 | } | 57 | } |
61 | 58 | ||
59 | return NULL; | ||
60 | } | ||
61 | |||
62 | void | ||
63 | nouveau_enum_print(const struct nouveau_enum *en, u32 value) | ||
64 | { | ||
65 | en = nouveau_enum_find(en, value); | ||
66 | if (en) { | ||
67 | printk("%s", en->name); | ||
68 | return; | ||
69 | } | ||
70 | |||
62 | printk("(unknown enum 0x%08x)", value); | 71 | printk("(unknown enum 0x%08x)", value); |
63 | } | 72 | } |
64 | 73 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_util.h b/drivers/gpu/drm/nouveau/nouveau_util.h index d9ceaea26f4b..b97719fbb739 100644 --- a/drivers/gpu/drm/nouveau/nouveau_util.h +++ b/drivers/gpu/drm/nouveau/nouveau_util.h | |||
@@ -36,10 +36,14 @@ struct nouveau_bitfield { | |||
36 | struct nouveau_enum { | 36 | struct nouveau_enum { |
37 | u32 value; | 37 | u32 value; |
38 | const char *name; | 38 | const char *name; |
39 | void *data; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); | 42 | void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value); |
42 | void nouveau_enum_print(const struct nouveau_enum *, u32 value); | 43 | void nouveau_enum_print(const struct nouveau_enum *, u32 value); |
44 | const struct nouveau_enum * | ||
45 | nouveau_enum_find(const struct nouveau_enum *, u32 value); | ||
46 | |||
43 | int nouveau_ratelimit(void); | 47 | int nouveau_ratelimit(void); |
44 | 48 | ||
45 | #endif | 49 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c index 62824c80bcb8..0059e6f58a8b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vm.c | |||
@@ -314,18 +314,7 @@ nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, u64 mm_offset, | |||
314 | vm->spg_shift = 12; | 314 | vm->spg_shift = 12; |
315 | vm->lpg_shift = 17; | 315 | vm->lpg_shift = 17; |
316 | pgt_bits = 27; | 316 | pgt_bits = 27; |
317 | 317 | block = 4096; | |
318 | /* Should be 4096 everywhere, this is a hack that's | ||
319 | * currently necessary to avoid an elusive bug that | ||
320 | * causes corruption when mixing small/large pages | ||
321 | */ | ||
322 | if (length < (1ULL << 40)) | ||
323 | block = 4096; | ||
324 | else { | ||
325 | block = (1 << pgt_bits); | ||
326 | if (length < block) | ||
327 | block = length; | ||
328 | } | ||
329 | } else { | 318 | } else { |
330 | kfree(vm); | 319 | kfree(vm); |
331 | return -ENOSYS; | 320 | return -ENOSYS; |
diff --git a/drivers/gpu/drm/nouveau/nv04_fifo.c b/drivers/gpu/drm/nouveau/nv04_fifo.c index dfa600c46186..db465a3ee1b2 100644 --- a/drivers/gpu/drm/nouveau/nv04_fifo.c +++ b/drivers/gpu/drm/nouveau/nv04_fifo.c | |||
@@ -516,7 +516,7 @@ nv04_fifo_isr(struct drm_device *dev) | |||
516 | 516 | ||
517 | if (dev_priv->card_type == NV_50) { | 517 | if (dev_priv->card_type == NV_50) { |
518 | if (status & 0x00000010) { | 518 | if (status & 0x00000010) { |
519 | nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT"); | 519 | nv50_fb_vm_trap(dev, nouveau_ratelimit()); |
520 | status &= ~0x00000010; | 520 | status &= ~0x00000010; |
521 | nv_wr32(dev, 0x002100, 0x00000010); | 521 | nv_wr32(dev, 0x002100, 0x00000010); |
522 | } | 522 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c index ed411d88451d..bdd2afe29205 100644 --- a/drivers/gpu/drm/nouveau/nv50_fb.c +++ b/drivers/gpu/drm/nouveau/nv50_fb.c | |||
@@ -114,12 +114,109 @@ nv50_fb_takedown(struct drm_device *dev) | |||
114 | nv50_fb_destroy(dev); | 114 | nv50_fb_destroy(dev); |
115 | } | 115 | } |
116 | 116 | ||
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 }, | ||
125 | {} | ||
126 | }; | ||
127 | |||
128 | static struct nouveau_enum vm_ccache_subclients[] = { | ||
129 | { 0x00000000, "CB", NULL }, | ||
130 | { 0x00000001, "TIC", NULL }, | ||
131 | { 0x00000002, "TSC", NULL }, | ||
132 | {} | ||
133 | }; | ||
134 | |||
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 }, | ||
149 | {} | ||
150 | }; | ||
151 | |||
152 | static struct nouveau_enum vm_pfifo_subclients[] = { | ||
153 | { 0x00000000, "PUSHBUF", NULL }, | ||
154 | { 0x00000001, "SEMAPHORE", NULL }, | ||
155 | {} | ||
156 | }; | ||
157 | |||
158 | static struct nouveau_enum vm_bar_subclients[] = { | ||
159 | { 0x00000000, "FB", NULL }, | ||
160 | { 0x00000001, "IN", NULL }, | ||
161 | {} | ||
162 | }; | ||
163 | |||
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 }, | ||
180 | {} | ||
181 | }; | ||
182 | |||
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 }, | ||
196 | {} | ||
197 | }; | ||
198 | |||
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 }, | ||
209 | {} | ||
210 | }; | ||
211 | |||
117 | void | 212 | void |
118 | nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | 213 | nv50_fb_vm_trap(struct drm_device *dev, int display) |
119 | { | 214 | { |
120 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 215 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
216 | const struct nouveau_enum *en, *cl; | ||
121 | unsigned long flags; | 217 | unsigned long flags; |
122 | u32 trap[6], idx, chinst; | 218 | u32 trap[6], idx, chinst; |
219 | u8 st0, st1, st2, st3; | ||
123 | int i, ch; | 220 | int i, ch; |
124 | 221 | ||
125 | idx = nv_rd32(dev, 0x100c90); | 222 | idx = nv_rd32(dev, 0x100c90); |
@@ -136,8 +233,8 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | |||
136 | if (!display) | 233 | if (!display) |
137 | return; | 234 | return; |
138 | 235 | ||
236 | /* lookup channel id */ | ||
139 | chinst = (trap[2] << 16) | trap[1]; | 237 | chinst = (trap[2] << 16) | trap[1]; |
140 | |||
141 | spin_lock_irqsave(&dev_priv->channels.lock, flags); | 238 | spin_lock_irqsave(&dev_priv->channels.lock, flags); |
142 | for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { | 239 | for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { |
143 | struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; | 240 | struct nouveau_channel *chan = dev_priv->channels.ptr[ch]; |
@@ -150,9 +247,48 @@ nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) | |||
150 | } | 247 | } |
151 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | 248 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); |
152 | 249 | ||
153 | NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " | 250 | /* decode status bits into something more useful */ |
154 | "channel %d (0x%08x)\n", | 251 | if (dev_priv->chipset < 0xa3 || |
155 | name, (trap[5] & 0x100 ? "read" : "write"), | 252 | dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) { |
156 | trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, | 253 | st0 = (trap[0] & 0x0000000f) >> 0; |
157 | trap[0], ch, chinst); | 254 | st1 = (trap[0] & 0x000000f0) >> 4; |
255 | st2 = (trap[0] & 0x00000f00) >> 8; | ||
256 | st3 = (trap[0] & 0x0000f000) >> 12; | ||
257 | } else { | ||
258 | st0 = (trap[0] & 0x000000ff) >> 0; | ||
259 | st1 = (trap[0] & 0x0000ff00) >> 8; | ||
260 | st2 = (trap[0] & 0x00ff0000) >> 16; | ||
261 | st3 = (trap[0] & 0xff000000) >> 24; | ||
262 | } | ||
263 | |||
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); | ||
267 | |||
268 | en = nouveau_enum_find(vm_engine, st0); | ||
269 | if (en) | ||
270 | printk("%s/", en->name); | ||
271 | else | ||
272 | printk("%02x/", st0); | ||
273 | |||
274 | cl = nouveau_enum_find(vm_client, st2); | ||
275 | if (cl) | ||
276 | printk("%s/", cl->name); | ||
277 | else | ||
278 | printk("%02x/", st2); | ||
279 | |||
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); | ||
282 | else cl = NULL; | ||
283 | if (cl) | ||
284 | printk("%s", cl->name); | ||
285 | else | ||
286 | printk("%02x", st3); | ||
287 | |||
288 | printk(" reason: "); | ||
289 | en = nouveau_enum_find(vm_fault, st1); | ||
290 | if (en) | ||
291 | printk("%s\n", en->name); | ||
292 | else | ||
293 | printk("0x%08x\n", st1); | ||
158 | } | 294 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index e1267a1f6d10..8675b00caf18 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -550,11 +550,11 @@ nv86_graph_tlb_flush(struct drm_device *dev) | |||
550 | 550 | ||
551 | static struct nouveau_enum nv50_mp_exec_error_names[] = | 551 | static struct nouveau_enum nv50_mp_exec_error_names[] = |
552 | { | 552 | { |
553 | { 3, "STACK_UNDERFLOW" }, | 553 | { 3, "STACK_UNDERFLOW", NULL }, |
554 | { 4, "QUADON_ACTIVE" }, | 554 | { 4, "QUADON_ACTIVE", NULL }, |
555 | { 8, "TIMEOUT" }, | 555 | { 8, "TIMEOUT", NULL }, |
556 | { 0x10, "INVALID_OPCODE" }, | 556 | { 0x10, "INVALID_OPCODE", NULL }, |
557 | { 0x40, "BREAKPOINT" }, | 557 | { 0x40, "BREAKPOINT", NULL }, |
558 | {} | 558 | {} |
559 | }; | 559 | }; |
560 | 560 | ||
@@ -582,47 +582,47 @@ static struct nouveau_bitfield nv50_graph_trap_ccache[] = { | |||
582 | 582 | ||
583 | /* There must be a *lot* of these. Will take some time to gather them up. */ | 583 | /* There must be a *lot* of these. Will take some time to gather them up. */ |
584 | struct nouveau_enum nv50_data_error_names[] = { | 584 | struct nouveau_enum nv50_data_error_names[] = { |
585 | { 0x00000003, "INVALID_QUERY_OR_TEXTURE" }, | 585 | { 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL }, |
586 | { 0x00000004, "INVALID_VALUE" }, | 586 | { 0x00000004, "INVALID_VALUE", NULL }, |
587 | { 0x00000005, "INVALID_ENUM" }, | 587 | { 0x00000005, "INVALID_ENUM", NULL }, |
588 | { 0x00000008, "INVALID_OBJECT" }, | 588 | { 0x00000008, "INVALID_OBJECT", NULL }, |
589 | { 0x00000009, "READ_ONLY_OBJECT" }, | 589 | { 0x00000009, "READ_ONLY_OBJECT", NULL }, |
590 | { 0x0000000a, "SUPERVISOR_OBJECT" }, | 590 | { 0x0000000a, "SUPERVISOR_OBJECT", NULL }, |
591 | { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" }, | 591 | { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL }, |
592 | { 0x0000000c, "INVALID_BITFIELD" }, | 592 | { 0x0000000c, "INVALID_BITFIELD", NULL }, |
593 | { 0x0000000d, "BEGIN_END_ACTIVE" }, | 593 | { 0x0000000d, "BEGIN_END_ACTIVE", NULL }, |
594 | { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" }, | 594 | { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL }, |
595 | { 0x0000000f, "VIEWPORT_ID_NEEDS_GP" }, | 595 | { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL }, |
596 | { 0x00000010, "RT_DOUBLE_BIND" }, | 596 | { 0x00000010, "RT_DOUBLE_BIND", NULL }, |
597 | { 0x00000011, "RT_TYPES_MISMATCH" }, | 597 | { 0x00000011, "RT_TYPES_MISMATCH", NULL }, |
598 | { 0x00000012, "RT_LINEAR_WITH_ZETA" }, | 598 | { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL }, |
599 | { 0x00000015, "FP_TOO_FEW_REGS" }, | 599 | { 0x00000015, "FP_TOO_FEW_REGS", NULL }, |
600 | { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" }, | 600 | { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL }, |
601 | { 0x00000017, "RT_LINEAR_WITH_MSAA" }, | 601 | { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL }, |
602 | { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" }, | 602 | { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL }, |
603 | { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" }, | 603 | { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL }, |
604 | { 0x0000001a, "RT_INVALID_ALIGNMENT" }, | 604 | { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL }, |
605 | { 0x0000001b, "SAMPLER_OVER_LIMIT" }, | 605 | { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL }, |
606 | { 0x0000001c, "TEXTURE_OVER_LIMIT" }, | 606 | { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL }, |
607 | { 0x0000001e, "GP_TOO_MANY_OUTPUTS" }, | 607 | { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL }, |
608 | { 0x0000001f, "RT_BPP128_WITH_MS8" }, | 608 | { 0x0000001f, "RT_BPP128_WITH_MS8", NULL }, |
609 | { 0x00000021, "Z_OUT_OF_BOUNDS" }, | 609 | { 0x00000021, "Z_OUT_OF_BOUNDS", NULL }, |
610 | { 0x00000023, "XY_OUT_OF_BOUNDS" }, | 610 | { 0x00000023, "XY_OUT_OF_BOUNDS", NULL }, |
611 | { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" }, | 611 | { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL }, |
612 | { 0x00000028, "CP_NO_REG_SPACE_STRIPED" }, | 612 | { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL }, |
613 | { 0x00000029, "CP_NO_REG_SPACE_PACKED" }, | 613 | { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL }, |
614 | { 0x0000002a, "CP_NOT_ENOUGH_WARPS" }, | 614 | { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL }, |
615 | { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" }, | 615 | { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL }, |
616 | { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" }, | 616 | { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL }, |
617 | { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" }, | 617 | { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL }, |
618 | { 0x0000002e, "CP_NO_BLOCKDIM_LATCH" }, | 618 | { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL }, |
619 | { 0x00000031, "ENG2D_FORMAT_MISMATCH" }, | 619 | { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL }, |
620 | { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" }, | 620 | { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL }, |
621 | { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" }, | 621 | { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL }, |
622 | { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" }, | 622 | { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL }, |
623 | { 0x00000046, "LAYER_ID_NEEDS_GP" }, | 623 | { 0x00000046, "LAYER_ID_NEEDS_GP", NULL }, |
624 | { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" }, | 624 | { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL }, |
625 | { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" }, | 625 | { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL }, |
626 | {} | 626 | {} |
627 | }; | 627 | }; |
628 | 628 | ||
@@ -702,7 +702,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, | |||
702 | tps++; | 702 | tps++; |
703 | switch (type) { | 703 | switch (type) { |
704 | case 6: /* texture error... unknown for now */ | 704 | case 6: /* texture error... unknown for now */ |
705 | nv50_fb_vm_trap(dev, display, name); | ||
706 | if (display) { | 705 | if (display) { |
707 | NV_ERROR(dev, "magic set %d:\n", i); | 706 | NV_ERROR(dev, "magic set %d:\n", i); |
708 | for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) | 707 | for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4) |
@@ -725,7 +724,6 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, | |||
725 | uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); | 724 | uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14); |
726 | uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); | 725 | uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18); |
727 | uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); | 726 | uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c); |
728 | nv50_fb_vm_trap(dev, display, name); | ||
729 | /* 2d engine destination */ | 727 | /* 2d engine destination */ |
730 | if (ustatus & 0x00000010) { | 728 | if (ustatus & 0x00000010) { |
731 | if (display) { | 729 | if (display) { |
@@ -1068,6 +1066,7 @@ nv50_graph_isr(struct drm_device *dev) | |||
1068 | NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " | 1066 | NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d " |
1069 | "class 0x%04x mthd 0x%04x data 0x%08x\n", | 1067 | "class 0x%04x mthd 0x%04x data 0x%08x\n", |
1070 | chid, inst, subc, class, mthd, data); | 1068 | chid, inst, subc, class, mthd, data); |
1069 | nv50_fb_vm_trap(dev, 1); | ||
1071 | } | 1070 | } |
1072 | } | 1071 | } |
1073 | 1072 | ||
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index ec18ae1c3886..fabc7fd30b1d 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c +++ b/drivers/gpu/drm/nouveau/nv84_crypt.c | |||
@@ -136,5 +136,5 @@ nv84_crypt_isr(struct drm_device *dev) | |||
136 | nv_wr32(dev, 0x102130, stat); | 136 | nv_wr32(dev, 0x102130, stat); |
137 | nv_wr32(dev, 0x10200c, 0x10); | 137 | nv_wr32(dev, 0x10200c, 0x10); |
138 | 138 | ||
139 | nv50_fb_vm_trap(dev, show, "PCRYPT"); | 139 | nv50_fb_vm_trap(dev, show); |
140 | } | 140 | } |