aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-07-30 02:49:57 -0400
committerDave Airlie <airlied@redhat.com>2013-07-30 02:49:57 -0400
commite9e3c8a20b2ac89a5770a6bb0a1d0dafc7f0edb0 (patch)
tree160b7db4ee3b4aaa232f6bd788eef82ce609fdc3
parentca089b7266337c144a17a890c5168f4db205ba85 (diff)
parent7a7da592cbb22a1d360638dbecc393470c5effe3 (diff)
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6
nouveau fixes a number of regressions and a few user triggerable oops since -rc1. Along with a few mpeg engine fixes. * 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: drm/nouveau: fix semaphore dmabuf obj drm/nouveau/vm: make vm refcount into a kref drm/nv31/mpeg: don't recognize nv3x cards as having nv44 graph class drm/nv40/mpeg: write magic value to channel object to make it work drm/nouveau: fix size check for cards without vm drm/nv50-/disp: remove dcb_outp_match call, and related variables drm/nva3-/disp: fix hda eld writing, needs to be padded drm/nv31/mpeg: fix mpeg engine initialization drm/nv50/mc: include vp in the fb error reporting mask drm/nouveau: fix null pointer dereference in poll_changed drm/nv50/gpio: post-nv92 cards have 32 interrupt lines drm/nvc0/fb: take lock in nvc0_ram_put() drm/nouveau/core: xtensa firmware size needs to be 0x40000 no matter what
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c9
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c1
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/xtensa.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/vm.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c22
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c14
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/base.c27
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c3
-rw-r--r--drivers/gpu/drm/nouveau/nv17_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fence.c14
17 files changed, 79 insertions, 56 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
index 373dbcc523b2..a19e7d79b847 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanva3.c
@@ -36,6 +36,8 @@ nva3_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
36 if (data && data[0]) { 36 if (data && data[0]) {
37 for (i = 0; i < size; i++) 37 for (i = 0; i < size; i++)
38 nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]); 38 nv_wr32(priv, 0x61c440 + soff, (i << 8) | data[i]);
39 for (; i < 0x60; i++)
40 nv_wr32(priv, 0x61c440 + soff, (i << 8));
39 nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003); 41 nv_mask(priv, 0x61c448 + soff, 0x80000003, 0x80000003);
40 } else 42 } else
41 if (data) { 43 if (data) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
index dc57e24fc1df..717639386ced 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/hdanvd0.c
@@ -41,6 +41,8 @@ nvd0_hda_eld(struct nv50_disp_priv *priv, int or, u8 *data, u32 size)
41 if (data && data[0]) { 41 if (data && data[0]) {
42 for (i = 0; i < size; i++) 42 for (i = 0; i < size; i++)
43 nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]); 43 nv_wr32(priv, 0x10ec00 + soff, (i << 8) | data[i]);
44 for (; i < 0x60; i++)
45 nv_wr32(priv, 0x10ec00 + soff, (i << 8));
44 nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003); 46 nv_mask(priv, 0x10ec10 + soff, 0x80000003, 0x80000003);
45 } else 47 } else
46 if (data) { 48 if (data) {
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
index ab1e918469a8..526b75242899 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
@@ -47,14 +47,8 @@ int
47nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) 47nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
48{ 48{
49 struct nv50_disp_priv *priv = (void *)object->engine; 49 struct nv50_disp_priv *priv = (void *)object->engine;
50 struct nouveau_bios *bios = nouveau_bios(priv);
51 const u16 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12;
52 const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; 50 const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3;
53 const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2;
54 const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); 51 const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR);
55 const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or);
56 struct dcb_output outp;
57 u8 ver, hdr;
58 u32 data; 52 u32 data;
59 int ret = -EINVAL; 53 int ret = -EINVAL;
60 54
@@ -62,8 +56,6 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size)
62 return -EINVAL; 56 return -EINVAL;
63 data = *(u32 *)args; 57 data = *(u32 *)args;
64 58
65 if (type && !dcb_outp_match(bios, type, mask, &ver, &hdr, &outp))
66 return -ENODEV;
67 59
68 switch (mthd & ~0x3f) { 60 switch (mthd & ~0x3f) {
69 case NV50_DISP_SOR_PWR: 61 case NV50_DISP_SOR_PWR:
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
index 49ecbb859b25..c19004301309 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
@@ -265,8 +265,8 @@ nv31_mpeg_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
265int 265int
266nv31_mpeg_init(struct nouveau_object *object) 266nv31_mpeg_init(struct nouveau_object *object)
267{ 267{
268 struct nouveau_engine *engine = nv_engine(object->engine); 268 struct nouveau_engine *engine = nv_engine(object);
269 struct nv31_mpeg_priv *priv = (void *)engine; 269 struct nv31_mpeg_priv *priv = (void *)object;
270 struct nouveau_fb *pfb = nouveau_fb(object); 270 struct nouveau_fb *pfb = nouveau_fb(object);
271 int ret, i; 271 int ret, i;
272 272
@@ -284,7 +284,10 @@ nv31_mpeg_init(struct nouveau_object *object)
284 /* PMPEG init */ 284 /* PMPEG init */
285 nv_wr32(priv, 0x00b32c, 0x00000000); 285 nv_wr32(priv, 0x00b32c, 0x00000000);
286 nv_wr32(priv, 0x00b314, 0x00000100); 286 nv_wr32(priv, 0x00b314, 0x00000100);
287 nv_wr32(priv, 0x00b220, nv44_graph_class(priv) ? 0x00000044 : 0x00000031); 287 if (nv_device(priv)->chipset >= 0x40 && nv44_graph_class(priv))
288 nv_wr32(priv, 0x00b220, 0x00000044);
289 else
290 nv_wr32(priv, 0x00b220, 0x00000031);
288 nv_wr32(priv, 0x00b300, 0x02001ec1); 291 nv_wr32(priv, 0x00b300, 0x02001ec1);
289 nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001); 292 nv_mask(priv, 0x00b32c, 0x00000001, 0x00000001);
290 293
diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
index f7c581ad1991..dd6196072e9c 100644
--- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
+++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
@@ -61,6 +61,7 @@ nv40_mpeg_context_ctor(struct nouveau_object *parent,
61 if (ret) 61 if (ret)
62 return ret; 62 return ret;
63 63
64 nv_wo32(&chan->base.base, 0x78, 0x02001ec1);
64 return 0; 65 return 0;
65} 66}
66 67
diff --git a/drivers/gpu/drm/nouveau/core/engine/xtensa.c b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
index 0639bc59d0a5..5f6ede7c4892 100644
--- a/drivers/gpu/drm/nouveau/core/engine/xtensa.c
+++ b/drivers/gpu/drm/nouveau/core/engine/xtensa.c
@@ -118,7 +118,13 @@ _nouveau_xtensa_init(struct nouveau_object *object)
118 return ret; 118 return ret;
119 } 119 }
120 120
121 ret = nouveau_gpuobj_new(object, NULL, fw->size, 0x1000, 0, 121 if (fw->size > 0x40000) {
122 nv_warn(xtensa, "firmware %s too large\n", name);
123 release_firmware(fw);
124 return -EINVAL;
125 }
126
127 ret = nouveau_gpuobj_new(object, NULL, 0x40000, 0x1000, 0,
122 &xtensa->gpu_fw); 128 &xtensa->gpu_fw);
123 if (ret) { 129 if (ret) {
124 release_firmware(fw); 130 release_firmware(fw);
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h
index f2e87b105666..fcf57fa309bf 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/vm.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/vm.h
@@ -55,7 +55,7 @@ struct nouveau_vma {
55struct nouveau_vm { 55struct nouveau_vm {
56 struct nouveau_vmmgr *vmm; 56 struct nouveau_vmmgr *vmm;
57 struct nouveau_mm mm; 57 struct nouveau_mm mm;
58 int refcount; 58 struct kref refcount;
59 59
60 struct list_head pgd_list; 60 struct list_head pgd_list;
61 atomic_t engref[NVDEV_SUBDEV_NR]; 61 atomic_t engref[NVDEV_SUBDEV_NR];
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
index 6c974dd83e8b..db9d6ddde52c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/priv.h
@@ -81,7 +81,7 @@ void nv44_fb_tile_prog(struct nouveau_fb *, int, struct nouveau_fb_tile *);
81void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, 81void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size,
82 u32 pitch, u32 flags, struct nouveau_fb_tile *); 82 u32 pitch, u32 flags, struct nouveau_fb_tile *);
83 83
84void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **); 84void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *);
85extern int nv50_fb_memtype[0x80]; 85extern int nv50_fb_memtype[0x80];
86 86
87#endif 87#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
index af5aa7ee8ad9..903baff77fdd 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv50.c
@@ -27,17 +27,10 @@
27#include "priv.h" 27#include "priv.h"
28 28
29void 29void
30nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) 30__nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem *mem)
31{ 31{
32 struct nouveau_mm_node *this; 32 struct nouveau_mm_node *this;
33 struct nouveau_mem *mem;
34 33
35 mem = *pmem;
36 *pmem = NULL;
37 if (unlikely(mem == NULL))
38 return;
39
40 mutex_lock(&pfb->base.mutex);
41 while (!list_empty(&mem->regions)) { 34 while (!list_empty(&mem->regions)) {
42 this = list_first_entry(&mem->regions, typeof(*this), rl_entry); 35 this = list_first_entry(&mem->regions, typeof(*this), rl_entry);
43 36
@@ -46,6 +39,19 @@ nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
46 } 39 }
47 40
48 nouveau_mm_free(&pfb->tags, &mem->tag); 41 nouveau_mm_free(&pfb->tags, &mem->tag);
42}
43
44void
45nv50_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
46{
47 struct nouveau_mem *mem = *pmem;
48
49 *pmem = NULL;
50 if (unlikely(mem == NULL))
51 return;
52
53 mutex_lock(&pfb->base.mutex);
54 __nv50_ram_put(pfb, mem);
49 mutex_unlock(&pfb->base.mutex); 55 mutex_unlock(&pfb->base.mutex);
50 56
51 kfree(mem); 57 kfree(mem);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
index 9c3634acbb9d..cf97c4de4a6b 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnvc0.c
@@ -33,11 +33,19 @@ void
33nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) 33nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem)
34{ 34{
35 struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb); 35 struct nouveau_ltcg *ltcg = nouveau_ltcg(pfb);
36 struct nouveau_mem *mem = *pmem;
36 37
37 if ((*pmem)->tag) 38 *pmem = NULL;
38 ltcg->tags_free(ltcg, &(*pmem)->tag); 39 if (unlikely(mem == NULL))
40 return;
39 41
40 nv50_ram_put(pfb, pmem); 42 mutex_lock(&pfb->base.mutex);
43 if (mem->tag)
44 ltcg->tags_free(ltcg, &mem->tag);
45 __nv50_ram_put(pfb, mem);
46 mutex_unlock(&pfb->base.mutex);
47
48 kfree(mem);
41} 49}
42 50
43int 51int
diff --git a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
index bf489dcf46e2..c4c1d415e7fe 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
@@ -103,7 +103,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
103 int i; 103 int i;
104 104
105 intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); 105 intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050);
106 if (nv_device(priv)->chipset >= 0x90) 106 if (nv_device(priv)->chipset > 0x92)
107 intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); 107 intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070);
108 108
109 hi = (intr0 & 0x0000ffff) | (intr1 << 16); 109 hi = (intr0 & 0x0000ffff) | (intr1 << 16);
@@ -115,7 +115,7 @@ nv50_gpio_intr(struct nouveau_subdev *subdev)
115 } 115 }
116 116
117 nv_wr32(priv, 0xe054, intr0); 117 nv_wr32(priv, 0xe054, intr0);
118 if (nv_device(priv)->chipset >= 0x90) 118 if (nv_device(priv)->chipset > 0x92)
119 nv_wr32(priv, 0xe074, intr1); 119 nv_wr32(priv, 0xe074, intr1);
120} 120}
121 121
@@ -146,7 +146,7 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
146 int ret; 146 int ret;
147 147
148 ret = nouveau_gpio_create(parent, engine, oclass, 148 ret = nouveau_gpio_create(parent, engine, oclass,
149 nv_device(parent)->chipset >= 0x90 ? 32 : 16, 149 nv_device(parent)->chipset > 0x92 ? 32 : 16,
150 &priv); 150 &priv);
151 *pobject = nv_object(priv); 151 *pobject = nv_object(priv);
152 if (ret) 152 if (ret)
@@ -182,7 +182,7 @@ nv50_gpio_init(struct nouveau_object *object)
182 /* disable, and ack any pending gpio interrupts */ 182 /* disable, and ack any pending gpio interrupts */
183 nv_wr32(priv, 0xe050, 0x00000000); 183 nv_wr32(priv, 0xe050, 0x00000000);
184 nv_wr32(priv, 0xe054, 0xffffffff); 184 nv_wr32(priv, 0xe054, 0xffffffff);
185 if (nv_device(priv)->chipset >= 0x90) { 185 if (nv_device(priv)->chipset > 0x92) {
186 nv_wr32(priv, 0xe070, 0x00000000); 186 nv_wr32(priv, 0xe070, 0x00000000);
187 nv_wr32(priv, 0xe074, 0xffffffff); 187 nv_wr32(priv, 0xe074, 0xffffffff);
188 } 188 }
@@ -195,7 +195,7 @@ nv50_gpio_fini(struct nouveau_object *object, bool suspend)
195{ 195{
196 struct nv50_gpio_priv *priv = (void *)object; 196 struct nv50_gpio_priv *priv = (void *)object;
197 nv_wr32(priv, 0xe050, 0x00000000); 197 nv_wr32(priv, 0xe050, 0x00000000);
198 if (nv_device(priv)->chipset >= 0x90) 198 if (nv_device(priv)->chipset > 0x92)
199 nv_wr32(priv, 0xe070, 0x00000000); 199 nv_wr32(priv, 0xe070, 0x00000000);
200 return nouveau_gpio_fini(&priv->base, suspend); 200 return nouveau_gpio_fini(&priv->base, suspend);
201} 201}
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
index 0cb322a5e72c..f25fc5fc7dd1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
@@ -41,7 +41,7 @@ nv50_mc_intr[] = {
41 { 0x04000000, NVDEV_ENGINE_DISP }, 41 { 0x04000000, NVDEV_ENGINE_DISP },
42 { 0x10000000, NVDEV_SUBDEV_BUS }, 42 { 0x10000000, NVDEV_SUBDEV_BUS },
43 { 0x80000000, NVDEV_ENGINE_SW }, 43 { 0x80000000, NVDEV_ENGINE_SW },
44 { 0x0000d101, NVDEV_SUBDEV_FB }, 44 { 0x0002d101, NVDEV_SUBDEV_FB },
45 {}, 45 {},
46}; 46};
47 47
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
index 67fcb6c852ac..ef3133e7575c 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
@@ -361,7 +361,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length,
361 361
362 INIT_LIST_HEAD(&vm->pgd_list); 362 INIT_LIST_HEAD(&vm->pgd_list);
363 vm->vmm = vmm; 363 vm->vmm = vmm;
364 vm->refcount = 1; 364 kref_init(&vm->refcount);
365 vm->fpde = offset >> (vmm->pgt_bits + 12); 365 vm->fpde = offset >> (vmm->pgt_bits + 12);
366 vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12); 366 vm->lpde = (offset + length - 1) >> (vmm->pgt_bits + 12);
367 367
@@ -441,8 +441,9 @@ nouveau_vm_unlink(struct nouveau_vm *vm, struct nouveau_gpuobj *mpgd)
441} 441}
442 442
443static void 443static void
444nouveau_vm_del(struct nouveau_vm *vm) 444nouveau_vm_del(struct kref *kref)
445{ 445{
446 struct nouveau_vm *vm = container_of(kref, typeof(*vm), refcount);
446 struct nouveau_vm_pgd *vpgd, *tmp; 447 struct nouveau_vm_pgd *vpgd, *tmp;
447 448
448 list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { 449 list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) {
@@ -458,27 +459,19 @@ int
458nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, 459nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr,
459 struct nouveau_gpuobj *pgd) 460 struct nouveau_gpuobj *pgd)
460{ 461{
461 struct nouveau_vm *vm; 462 if (ref) {
462 int ret; 463 int ret = nouveau_vm_link(ref, pgd);
463
464 vm = ref;
465 if (vm) {
466 ret = nouveau_vm_link(vm, pgd);
467 if (ret) 464 if (ret)
468 return ret; 465 return ret;
469 466
470 vm->refcount++; 467 kref_get(&ref->refcount);
471 } 468 }
472 469
473 vm = *ptr; 470 if (*ptr) {
474 *ptr = ref; 471 nouveau_vm_unlink(*ptr, pgd);
475 472 kref_put(&(*ptr)->refcount, nouveau_vm_del);
476 if (vm) {
477 nouveau_vm_unlink(vm, pgd);
478
479 if (--vm->refcount == 0)
480 nouveau_vm_del(vm);
481 } 473 }
482 474
475 *ptr = ref;
483 return 0; 476 return 0;
484} 477}
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 4e7ee5f4155c..af20fba3a1a4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -198,7 +198,12 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
198 size_t acc_size; 198 size_t acc_size;
199 int ret; 199 int ret;
200 int type = ttm_bo_type_device; 200 int type = ttm_bo_type_device;
201 int max_size = INT_MAX & ~((1 << drm->client.base.vm->vmm->lpg_shift) - 1); 201 int lpg_shift = 12;
202 int max_size;
203
204 if (drm->client.base.vm)
205 lpg_shift = drm->client.base.vm->vmm->lpg_shift;
206 max_size = INT_MAX & ~((1 << lpg_shift) - 1);
202 207
203 if (size <= 0 || size > max_size) { 208 if (size <= 0 || size > max_size) {
204 nv_warn(drm, "skipped size %x\n", (u32)size); 209 nv_warn(drm, "skipped size %x\n", (u32)size);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 4c1bc061fae2..8f6d63d7edd3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -398,7 +398,8 @@ void
398nouveau_fbcon_output_poll_changed(struct drm_device *dev) 398nouveau_fbcon_output_poll_changed(struct drm_device *dev)
399{ 399{
400 struct nouveau_drm *drm = nouveau_drm(dev); 400 struct nouveau_drm *drm = nouveau_drm(dev);
401 drm_fb_helper_hotplug_event(&drm->fbcon->helper); 401 if (drm->fbcon)
402 drm_fb_helper_hotplug_event(&drm->fbcon->helper);
402} 403}
403 404
404static int 405static int
diff --git a/drivers/gpu/drm/nouveau/nv17_fence.c b/drivers/gpu/drm/nouveau/nv17_fence.c
index 8e47a9bae8c3..22aa9963ea6f 100644
--- a/drivers/gpu/drm/nouveau/nv17_fence.c
+++ b/drivers/gpu/drm/nouveau/nv17_fence.c
@@ -76,7 +76,7 @@ nv17_fence_context_new(struct nouveau_channel *chan)
76 struct ttm_mem_reg *mem = &priv->bo->bo.mem; 76 struct ttm_mem_reg *mem = &priv->bo->bo.mem;
77 struct nouveau_object *object; 77 struct nouveau_object *object;
78 u32 start = mem->start * PAGE_SIZE; 78 u32 start = mem->start * PAGE_SIZE;
79 u32 limit = mem->start + mem->size - 1; 79 u32 limit = start + mem->size - 1;
80 int ret = 0; 80 int ret = 0;
81 81
82 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 82 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
index f9701e567db8..0ee363840035 100644
--- a/drivers/gpu/drm/nouveau/nv50_fence.c
+++ b/drivers/gpu/drm/nouveau/nv50_fence.c
@@ -39,6 +39,8 @@ nv50_fence_context_new(struct nouveau_channel *chan)
39 struct nv10_fence_chan *fctx; 39 struct nv10_fence_chan *fctx;
40 struct ttm_mem_reg *mem = &priv->bo->bo.mem; 40 struct ttm_mem_reg *mem = &priv->bo->bo.mem;
41 struct nouveau_object *object; 41 struct nouveau_object *object;
42 u32 start = mem->start * PAGE_SIZE;
43 u32 limit = start + mem->size - 1;
42 int ret, i; 44 int ret, i;
43 45
44 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 46 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
@@ -51,26 +53,28 @@ nv50_fence_context_new(struct nouveau_channel *chan)
51 fctx->base.sync = nv17_fence_sync; 53 fctx->base.sync = nv17_fence_sync;
52 54
53 ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 55 ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
54 NvSema, 0x0002, 56 NvSema, 0x003d,
55 &(struct nv_dma_class) { 57 &(struct nv_dma_class) {
56 .flags = NV_DMA_TARGET_VRAM | 58 .flags = NV_DMA_TARGET_VRAM |
57 NV_DMA_ACCESS_RDWR, 59 NV_DMA_ACCESS_RDWR,
58 .start = mem->start * PAGE_SIZE, 60 .start = start,
59 .limit = mem->size - 1, 61 .limit = limit,
60 }, sizeof(struct nv_dma_class), 62 }, sizeof(struct nv_dma_class),
61 &object); 63 &object);
62 64
63 /* dma objects for display sync channel semaphore blocks */ 65 /* dma objects for display sync channel semaphore blocks */
64 for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { 66 for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
65 struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); 67 struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
68 u32 start = bo->bo.mem.start * PAGE_SIZE;
69 u32 limit = start + bo->bo.mem.size - 1;
66 70
67 ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 71 ret = nouveau_object_new(nv_object(chan->cli), chan->handle,
68 NvEvoSema0 + i, 0x003d, 72 NvEvoSema0 + i, 0x003d,
69 &(struct nv_dma_class) { 73 &(struct nv_dma_class) {
70 .flags = NV_DMA_TARGET_VRAM | 74 .flags = NV_DMA_TARGET_VRAM |
71 NV_DMA_ACCESS_RDWR, 75 NV_DMA_ACCESS_RDWR,
72 .start = bo->bo.offset, 76 .start = start,
73 .limit = bo->bo.offset + 0xfff, 77 .limit = limit,
74 }, sizeof(struct nv_dma_class), 78 }, sizeof(struct nv_dma_class),
75 &object); 79 &object);
76 } 80 }