diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-09-01 19:31:40 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-09-01 19:31:40 -0400 |
| commit | 9c725e5bcdae59d5383d4aec33a34c822582dda5 (patch) | |
| tree | 3d55827f5f44f16cb0aada2713029f7490f557d4 /drivers/gpu/drm/nouveau | |
| parent | efa27f9cec09518c9b574e3ab4a0a41717237429 (diff) | |
| parent | 679fe80fbe964ea7f9f71781c2ca65b630949da3 (diff) | |
Merge branch 'drm-next-3.12' of git://people.freedesktop.org/~agd5f/linux into drm-next
Alex writes:
This is the radeon drm-next request. Big changes include:
- support for dpm on CIK parts
- support for ASPM on CIK parts
- support for berlin GPUs
- major ring handling cleanup
- remove the old 3D blit code for bo moves in favor of CP DMA or sDMA
- lots of bug fixes
[airlied: fix up a bunch of conflicts from drm_order removal]
* 'drm-next-3.12' of git://people.freedesktop.org/~agd5f/linux: (898 commits)
drm/radeon/dpm: make sure dc performance level limits are valid (CI)
drm/radeon/dpm: make sure dc performance level limits are valid (BTC-SI) (v2)
drm/radeon: gcc fixes for extended dpm tables
drm/radeon: gcc fixes for kb/kv dpm
drm/radeon: gcc fixes for ci dpm
drm/radeon: gcc fixes for si dpm
drm/radeon: gcc fixes for ni dpm
drm/radeon: gcc fixes for trinity dpm
drm/radeon: gcc fixes for sumo dpm
drm/radeonn: gcc fixes for rv7xx/eg/btc dpm
drm/radeon: gcc fixes for rv6xx dpm
drm/radeon: gcc fixes for radeon_atombios.c
drm/radeon: enable UVD interrupts on CIK
drm/radeon: fix init ordering for r600+
drm/radeon/dpm: only need to reprogram uvd if uvd pg is enabled
drm/radeon: check the return value of uvd_v1_0_start in uvd_v1_0_init
drm/radeon: split out radeon_uvd_resume from uvd_v4_2_resume
radeon kms: fix uninitialised hotplug work usage in r100_irq_process()
drm/radeon/audio: set up the sads on DCE3.2 asics
drm/radeon: fix handling of variable sized arrays for router objects
...
Conflicts:
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem_dmabuf.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
Diffstat (limited to 'drivers/gpu/drm/nouveau')
31 files changed, 177 insertions, 104 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index d8291724dbd4..7a4e0891c5f8 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c | |||
| @@ -98,6 +98,8 @@ nouveau_mm_head(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, | |||
| 98 | u32 splitoff; | 98 | u32 splitoff; |
| 99 | u32 s, e; | 99 | u32 s, e; |
| 100 | 100 | ||
| 101 | BUG_ON(!type); | ||
| 102 | |||
| 101 | list_for_each_entry(this, &mm->free, fl_entry) { | 103 | list_for_each_entry(this, &mm->free, fl_entry) { |
| 102 | e = this->offset + this->length; | 104 | e = this->offset + this->length; |
| 103 | s = this->offset; | 105 | s = this->offset; |
| @@ -162,6 +164,8 @@ nouveau_mm_tail(struct nouveau_mm *mm, u8 type, u32 size_max, u32 size_min, | |||
| 162 | struct nouveau_mm_node *prev, *this, *next; | 164 | struct nouveau_mm_node *prev, *this, *next; |
| 163 | u32 mask = align - 1; | 165 | u32 mask = align - 1; |
| 164 | 166 | ||
| 167 | BUG_ON(!type); | ||
| 168 | |||
| 165 | list_for_each_entry_reverse(this, &mm->free, fl_entry) { | 169 | list_for_each_entry_reverse(this, &mm->free, fl_entry) { |
| 166 | u32 e = this->offset + this->length; | 170 | u32 e = this->offset + this->length; |
| 167 | u32 s = this->offset; | 171 | u32 s = this->offset; |
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 | |||
| 47 | nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) | 47 | nv50_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, | |||
| 265 | int | 265 | int |
| 266 | nv31_mpeg_init(struct nouveau_object *object) | 266 | nv31_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/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index d5502267c30f..9d2cd2006250 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h | |||
| @@ -20,8 +20,8 @@ nouveau_mc(void *obj) | |||
| 20 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC]; | 20 | return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_MC]; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | #define nouveau_mc_create(p,e,o,d) \ | 23 | #define nouveau_mc_create(p,e,o,m,d) \ |
| 24 | nouveau_mc_create_((p), (e), (o), sizeof(**d), (void **)d) | 24 | nouveau_mc_create_((p), (e), (o), (m), sizeof(**d), (void **)d) |
| 25 | #define nouveau_mc_destroy(p) ({ \ | 25 | #define nouveau_mc_destroy(p) ({ \ |
| 26 | struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \ | 26 | struct nouveau_mc *pmc = (p); _nouveau_mc_dtor(nv_object(pmc)); \ |
| 27 | }) | 27 | }) |
| @@ -33,7 +33,8 @@ nouveau_mc(void *obj) | |||
| 33 | }) | 33 | }) |
| 34 | 34 | ||
| 35 | int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *, | 35 | int nouveau_mc_create_(struct nouveau_object *, struct nouveau_object *, |
| 36 | struct nouveau_oclass *, int, void **); | 36 | struct nouveau_oclass *, const struct nouveau_mc_intr *, |
| 37 | int, void **); | ||
| 37 | void _nouveau_mc_dtor(struct nouveau_object *); | 38 | void _nouveau_mc_dtor(struct nouveau_object *); |
| 38 | int _nouveau_mc_init(struct nouveau_object *); | 39 | int _nouveau_mc_init(struct nouveau_object *); |
| 39 | int _nouveau_mc_fini(struct nouveau_object *, bool); | 40 | int _nouveau_mc_fini(struct nouveau_object *, bool); |
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 { | |||
| 55 | struct nouveau_vm { | 55 | struct 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 *); | |||
| 81 | void nv46_fb_tile_init(struct nouveau_fb *, int i, u32 addr, u32 size, | 81 | void 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 | ||
| 84 | void nv50_ram_put(struct nouveau_fb *, struct nouveau_mem **); | 84 | void __nv50_ram_put(struct nouveau_fb *, struct nouveau_mem *); |
| 85 | extern int nv50_fb_memtype[0x80]; | 85 | extern int nv50_fb_memtype[0x80]; |
| 86 | 86 | ||
| 87 | #endif | 87 | #endif |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c index 19e3a9a63a02..ab7ef0ac9e34 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv49.c | |||
| @@ -40,15 +40,15 @@ nv49_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 40 | return ret; | 40 | return ret; |
| 41 | 41 | ||
| 42 | switch (pfb914 & 0x00000003) { | 42 | switch (pfb914 & 0x00000003) { |
| 43 | case 0x00000000: pfb->ram->type = NV_MEM_TYPE_DDR1; break; | 43 | case 0x00000000: ram->type = NV_MEM_TYPE_DDR1; break; |
| 44 | case 0x00000001: pfb->ram->type = NV_MEM_TYPE_DDR2; break; | 44 | case 0x00000001: ram->type = NV_MEM_TYPE_DDR2; break; |
| 45 | case 0x00000002: pfb->ram->type = NV_MEM_TYPE_GDDR3; break; | 45 | case 0x00000002: ram->type = NV_MEM_TYPE_GDDR3; break; |
| 46 | case 0x00000003: break; | 46 | case 0x00000003: break; |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; | 49 | ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; |
| 50 | pfb->ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; | 50 | ram->parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1; |
| 51 | pfb->ram->tags = nv_rd32(pfb, 0x100320); | 51 | ram->tags = nv_rd32(pfb, 0x100320); |
| 52 | return 0; | 52 | return 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c index 7192aa6e5577..63a6aab86028 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/ramnv4e.c | |||
| @@ -38,8 +38,8 @@ nv4e_ram_create(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 38 | if (ret) | 38 | if (ret) |
| 39 | return ret; | 39 | return ret; |
| 40 | 40 | ||
| 41 | pfb->ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; | 41 | ram->size = nv_rd32(pfb, 0x10020c) & 0xff000000; |
| 42 | pfb->ram->type = NV_MEM_TYPE_STOLEN; | 42 | ram->type = NV_MEM_TYPE_STOLEN; |
| 43 | return 0; | 43 | return 0; |
| 44 | } | 44 | } |
| 45 | 45 | ||
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 | ||
| 29 | void | 29 | void |
| 30 | nv50_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 | |||
| 44 | void | ||
| 45 | nv50_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 | |||
| 33 | nvc0_ram_put(struct nouveau_fb *pfb, struct nouveau_mem **pmem) | 33 | nvc0_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 | ||
| 43 | int | 51 | int |
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/ltcg/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c index bcca883018f4..cce65cc56514 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/ltcg/nvc0.c | |||
| @@ -30,8 +30,9 @@ struct nvc0_ltcg_priv { | |||
| 30 | struct nouveau_ltcg base; | 30 | struct nouveau_ltcg base; |
| 31 | u32 part_nr; | 31 | u32 part_nr; |
| 32 | u32 subp_nr; | 32 | u32 subp_nr; |
| 33 | struct nouveau_mm tags; | ||
| 34 | u32 num_tags; | 33 | u32 num_tags; |
| 34 | u32 tag_base; | ||
| 35 | struct nouveau_mm tags; | ||
| 35 | struct nouveau_mm_node *tag_ram; | 36 | struct nouveau_mm_node *tag_ram; |
| 36 | }; | 37 | }; |
| 37 | 38 | ||
| @@ -117,10 +118,6 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | |||
| 117 | u32 tag_size, tag_margin, tag_align; | 118 | u32 tag_size, tag_margin, tag_align; |
| 118 | int ret; | 119 | int ret; |
| 119 | 120 | ||
| 120 | nv_wr32(priv, 0x17e8d8, priv->part_nr); | ||
| 121 | if (nv_device(pfb)->card_type >= NV_E0) | ||
| 122 | nv_wr32(priv, 0x17e000, priv->part_nr); | ||
| 123 | |||
| 124 | /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ | 121 | /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ |
| 125 | priv->num_tags = (pfb->ram->size >> 17) / 4; | 122 | priv->num_tags = (pfb->ram->size >> 17) / 4; |
| 126 | if (priv->num_tags > (1 << 17)) | 123 | if (priv->num_tags > (1 << 17)) |
| @@ -142,7 +139,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | |||
| 142 | tag_size += tag_align; | 139 | tag_size += tag_align; |
| 143 | tag_size = (tag_size + 0xfff) >> 12; /* round up */ | 140 | tag_size = (tag_size + 0xfff) >> 12; /* round up */ |
| 144 | 141 | ||
| 145 | ret = nouveau_mm_tail(&pfb->vram, 0, tag_size, tag_size, 1, | 142 | ret = nouveau_mm_tail(&pfb->vram, 1, tag_size, tag_size, 1, |
| 146 | &priv->tag_ram); | 143 | &priv->tag_ram); |
| 147 | if (ret) { | 144 | if (ret) { |
| 148 | priv->num_tags = 0; | 145 | priv->num_tags = 0; |
| @@ -152,7 +149,7 @@ nvc0_ltcg_init_tag_ram(struct nouveau_fb *pfb, struct nvc0_ltcg_priv *priv) | |||
| 152 | tag_base += tag_align - 1; | 149 | tag_base += tag_align - 1; |
| 153 | ret = do_div(tag_base, tag_align); | 150 | ret = do_div(tag_base, tag_align); |
| 154 | 151 | ||
| 155 | nv_wr32(priv, 0x17e8d4, tag_base); | 152 | priv->tag_base = tag_base; |
| 156 | } | 153 | } |
| 157 | ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1); | 154 | ret = nouveau_mm_init(&priv->tags, 0, priv->num_tags, 1); |
| 158 | 155 | ||
| @@ -182,8 +179,6 @@ nvc0_ltcg_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 182 | } | 179 | } |
| 183 | priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; | 180 | priv->subp_nr = nv_rd32(priv, 0x17e8dc) >> 28; |
| 184 | 181 | ||
| 185 | nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ | ||
| 186 | |||
| 187 | ret = nvc0_ltcg_init_tag_ram(pfb, priv); | 182 | ret = nvc0_ltcg_init_tag_ram(pfb, priv); |
| 188 | if (ret) | 183 | if (ret) |
| 189 | return ret; | 184 | return ret; |
| @@ -209,13 +204,32 @@ nvc0_ltcg_dtor(struct nouveau_object *object) | |||
| 209 | nouveau_ltcg_destroy(ltcg); | 204 | nouveau_ltcg_destroy(ltcg); |
| 210 | } | 205 | } |
| 211 | 206 | ||
| 207 | static int | ||
| 208 | nvc0_ltcg_init(struct nouveau_object *object) | ||
| 209 | { | ||
| 210 | struct nouveau_ltcg *ltcg = (struct nouveau_ltcg *)object; | ||
| 211 | struct nvc0_ltcg_priv *priv = (struct nvc0_ltcg_priv *)ltcg; | ||
| 212 | int ret; | ||
| 213 | |||
| 214 | ret = nouveau_ltcg_init(ltcg); | ||
| 215 | if (ret) | ||
| 216 | return ret; | ||
| 217 | |||
| 218 | nv_mask(priv, 0x17e820, 0x00100000, 0x00000000); /* INTR_EN &= ~0x10 */ | ||
| 219 | nv_wr32(priv, 0x17e8d8, priv->part_nr); | ||
| 220 | if (nv_device(ltcg)->card_type >= NV_E0) | ||
| 221 | nv_wr32(priv, 0x17e000, priv->part_nr); | ||
| 222 | nv_wr32(priv, 0x17e8d4, priv->tag_base); | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 212 | struct nouveau_oclass | 226 | struct nouveau_oclass |
| 213 | nvc0_ltcg_oclass = { | 227 | nvc0_ltcg_oclass = { |
| 214 | .handle = NV_SUBDEV(LTCG, 0xc0), | 228 | .handle = NV_SUBDEV(LTCG, 0xc0), |
| 215 | .ofuncs = &(struct nouveau_ofuncs) { | 229 | .ofuncs = &(struct nouveau_ofuncs) { |
| 216 | .ctor = nvc0_ltcg_ctor, | 230 | .ctor = nvc0_ltcg_ctor, |
| 217 | .dtor = nvc0_ltcg_dtor, | 231 | .dtor = nvc0_ltcg_dtor, |
| 218 | .init = _nouveau_ltcg_init, | 232 | .init = nvc0_ltcg_init, |
| 219 | .fini = _nouveau_ltcg_fini, | 233 | .fini = _nouveau_ltcg_fini, |
| 220 | }, | 234 | }, |
| 221 | }; | 235 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 2e7c5fd3de3d..20f9a538746e 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c | |||
| @@ -86,7 +86,9 @@ _nouveau_mc_dtor(struct nouveau_object *object) | |||
| 86 | 86 | ||
| 87 | int | 87 | int |
| 88 | nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | 88 | nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, |
| 89 | struct nouveau_oclass *oclass, int length, void **pobject) | 89 | struct nouveau_oclass *oclass, |
| 90 | const struct nouveau_mc_intr *intr_map, | ||
| 91 | int length, void **pobject) | ||
| 90 | { | 92 | { |
| 91 | struct nouveau_device *device = nv_device(parent); | 93 | struct nouveau_device *device = nv_device(parent); |
| 92 | struct nouveau_mc *pmc; | 94 | struct nouveau_mc *pmc; |
| @@ -98,6 +100,8 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 98 | if (ret) | 100 | if (ret) |
| 99 | return ret; | 101 | return ret; |
| 100 | 102 | ||
| 103 | pmc->intr_map = intr_map; | ||
| 104 | |||
| 101 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, | 105 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, |
| 102 | IRQF_SHARED, "nouveau", pmc); | 106 | IRQF_SHARED, "nouveau", pmc); |
| 103 | if (ret < 0) | 107 | if (ret < 0) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c index 8c769715227b..64aa4edb0d9d 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c | |||
| @@ -50,12 +50,11 @@ nv04_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 50 | struct nv04_mc_priv *priv; | 50 | struct nv04_mc_priv *priv; |
| 51 | int ret; | 51 | int ret; |
| 52 | 52 | ||
| 53 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 53 | ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv); |
| 54 | *pobject = nv_object(priv); | 54 | *pobject = nv_object(priv); |
| 55 | if (ret) | 55 | if (ret) |
| 56 | return ret; | 56 | return ret; |
| 57 | 57 | ||
| 58 | priv->base.intr_map = nv04_mc_intr; | ||
| 59 | return 0; | 58 | return 0; |
| 60 | } | 59 | } |
| 61 | 60 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c index 51919371810f..d9891782bf28 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv44.c | |||
| @@ -36,12 +36,11 @@ nv44_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 36 | struct nv44_mc_priv *priv; | 36 | struct nv44_mc_priv *priv; |
| 37 | int ret; | 37 | int ret; |
| 38 | 38 | ||
| 39 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 39 | ret = nouveau_mc_create(parent, engine, oclass, nv04_mc_intr, &priv); |
| 40 | *pobject = nv_object(priv); | 40 | *pobject = nv_object(priv); |
| 41 | if (ret) | 41 | if (ret) |
| 42 | return ret; | 42 | return ret; |
| 43 | 43 | ||
| 44 | priv->base.intr_map = nv04_mc_intr; | ||
| 45 | return 0; | 44 | return 0; |
| 46 | } | 45 | } |
| 47 | 46 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index 0cb322a5e72c..2b1afe225db8 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 | ||
| @@ -53,12 +53,11 @@ nv50_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 53 | struct nv50_mc_priv *priv; | 53 | struct nv50_mc_priv *priv; |
| 54 | int ret; | 54 | int ret; |
| 55 | 55 | ||
| 56 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 56 | ret = nouveau_mc_create(parent, engine, oclass, nv50_mc_intr, &priv); |
| 57 | *pobject = nv_object(priv); | 57 | *pobject = nv_object(priv); |
| 58 | if (ret) | 58 | if (ret) |
| 59 | return ret; | 59 | return ret; |
| 60 | 60 | ||
| 61 | priv->base.intr_map = nv50_mc_intr; | ||
| 62 | return 0; | 61 | return 0; |
| 63 | } | 62 | } |
| 64 | 63 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index e82fd21b5041..0d57b4d3e001 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | |||
| @@ -54,12 +54,11 @@ nv98_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 54 | struct nv98_mc_priv *priv; | 54 | struct nv98_mc_priv *priv; |
| 55 | int ret; | 55 | int ret; |
| 56 | 56 | ||
| 57 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 57 | ret = nouveau_mc_create(parent, engine, oclass, nv98_mc_intr, &priv); |
| 58 | *pobject = nv_object(priv); | 58 | *pobject = nv_object(priv); |
| 59 | if (ret) | 59 | if (ret) |
| 60 | return ret; | 60 | return ret; |
| 61 | 61 | ||
| 62 | priv->base.intr_map = nv98_mc_intr; | ||
| 63 | return 0; | 62 | return 0; |
| 64 | } | 63 | } |
| 65 | 64 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index c5da3babbc62..104175c5a2dd 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c | |||
| @@ -57,12 +57,11 @@ nvc0_mc_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 57 | struct nvc0_mc_priv *priv; | 57 | struct nvc0_mc_priv *priv; |
| 58 | int ret; | 58 | int ret; |
| 59 | 59 | ||
| 60 | ret = nouveau_mc_create(parent, engine, oclass, &priv); | 60 | ret = nouveau_mc_create(parent, engine, oclass, nvc0_mc_intr, &priv); |
| 61 | *pobject = nv_object(priv); | 61 | *pobject = nv_object(priv); |
| 62 | if (ret) | 62 | if (ret) |
| 63 | return ret; | 63 | return ret; |
| 64 | 64 | ||
| 65 | priv->base.intr_map = nvc0_mc_intr; | ||
| 66 | return 0; | 65 | return 0; |
| 67 | } | 66 | } |
| 68 | 67 | ||
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 | ||
| 443 | static void | 443 | static void |
| 444 | nouveau_vm_del(struct nouveau_vm *vm) | 444 | nouveau_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 | |||
| 458 | nouveau_vm_ref(struct nouveau_vm *ref, struct nouveau_vm **ptr, | 459 | nouveau_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/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c index 6413552df21c..d4fbf11360fe 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c +++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c | |||
| @@ -607,6 +607,24 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | |||
| 607 | regp->ramdac_a34 = 0x1; | 607 | regp->ramdac_a34 = 0x1; |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | static int | ||
| 611 | nv_crtc_swap_fbs(struct drm_crtc *crtc, struct drm_framebuffer *old_fb) | ||
| 612 | { | ||
| 613 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
| 614 | struct nouveau_framebuffer *nvfb = nouveau_framebuffer(crtc->fb); | ||
| 615 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
| 616 | int ret; | ||
| 617 | |||
| 618 | ret = nouveau_bo_pin(nvfb->nvbo, TTM_PL_FLAG_VRAM); | ||
| 619 | if (ret == 0) { | ||
| 620 | if (disp->image[nv_crtc->index]) | ||
| 621 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
| 622 | nouveau_bo_ref(nvfb->nvbo, &disp->image[nv_crtc->index]); | ||
| 623 | } | ||
| 624 | |||
| 625 | return ret; | ||
| 626 | } | ||
| 627 | |||
| 610 | /** | 628 | /** |
| 611 | * Sets up registers for the given mode/adjusted_mode pair. | 629 | * Sets up registers for the given mode/adjusted_mode pair. |
| 612 | * | 630 | * |
| @@ -623,10 +641,15 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
| 623 | struct drm_device *dev = crtc->dev; | 641 | struct drm_device *dev = crtc->dev; |
| 624 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 642 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| 625 | struct nouveau_drm *drm = nouveau_drm(dev); | 643 | struct nouveau_drm *drm = nouveau_drm(dev); |
| 644 | int ret; | ||
| 626 | 645 | ||
| 627 | NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); | 646 | NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); |
| 628 | drm_mode_debug_printmodeline(adjusted_mode); | 647 | drm_mode_debug_printmodeline(adjusted_mode); |
| 629 | 648 | ||
| 649 | ret = nv_crtc_swap_fbs(crtc, old_fb); | ||
| 650 | if (ret) | ||
| 651 | return ret; | ||
| 652 | |||
| 630 | /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ | 653 | /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ |
| 631 | nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); | 654 | nv_lock_vga_crtc_shadow(dev, nv_crtc->index, -1); |
| 632 | 655 | ||
| @@ -723,6 +746,7 @@ static void nv_crtc_commit(struct drm_crtc *crtc) | |||
| 723 | 746 | ||
| 724 | static void nv_crtc_destroy(struct drm_crtc *crtc) | 747 | static void nv_crtc_destroy(struct drm_crtc *crtc) |
| 725 | { | 748 | { |
| 749 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
| 726 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 750 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
| 727 | 751 | ||
| 728 | if (!nv_crtc) | 752 | if (!nv_crtc) |
| @@ -730,6 +754,10 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) | |||
| 730 | 754 | ||
| 731 | drm_crtc_cleanup(crtc); | 755 | drm_crtc_cleanup(crtc); |
| 732 | 756 | ||
| 757 | if (disp->image[nv_crtc->index]) | ||
| 758 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
| 759 | nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); | ||
| 760 | |||
| 733 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); | 761 | nouveau_bo_unmap(nv_crtc->cursor.nvbo); |
| 734 | nouveau_bo_unpin(nv_crtc->cursor.nvbo); | 762 | nouveau_bo_unpin(nv_crtc->cursor.nvbo); |
| 735 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); | 763 | nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); |
| @@ -755,6 +783,16 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) | |||
| 755 | } | 783 | } |
| 756 | 784 | ||
| 757 | static void | 785 | static void |
| 786 | nv_crtc_disable(struct drm_crtc *crtc) | ||
| 787 | { | ||
| 788 | struct nv04_display *disp = nv04_display(crtc->dev); | ||
| 789 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||
| 790 | if (disp->image[nv_crtc->index]) | ||
| 791 | nouveau_bo_unpin(disp->image[nv_crtc->index]); | ||
| 792 | nouveau_bo_ref(NULL, &disp->image[nv_crtc->index]); | ||
| 793 | } | ||
| 794 | |||
| 795 | static void | ||
| 758 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, | 796 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, |
| 759 | uint32_t size) | 797 | uint32_t size) |
| 760 | { | 798 | { |
| @@ -792,7 +830,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
| 792 | struct drm_framebuffer *drm_fb; | 830 | struct drm_framebuffer *drm_fb; |
| 793 | struct nouveau_framebuffer *fb; | 831 | struct nouveau_framebuffer *fb; |
| 794 | int arb_burst, arb_lwm; | 832 | int arb_burst, arb_lwm; |
| 795 | int ret; | ||
| 796 | 833 | ||
| 797 | NV_DEBUG(drm, "index %d\n", nv_crtc->index); | 834 | NV_DEBUG(drm, "index %d\n", nv_crtc->index); |
| 798 | 835 | ||
| @@ -802,10 +839,8 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
| 802 | return 0; | 839 | return 0; |
| 803 | } | 840 | } |
| 804 | 841 | ||
| 805 | |||
| 806 | /* If atomic, we want to switch to the fb we were passed, so | 842 | /* If atomic, we want to switch to the fb we were passed, so |
| 807 | * now we update pointers to do that. (We don't pin; just | 843 | * now we update pointers to do that. |
| 808 | * assume we're already pinned and update the base address.) | ||
| 809 | */ | 844 | */ |
| 810 | if (atomic) { | 845 | if (atomic) { |
| 811 | drm_fb = passed_fb; | 846 | drm_fb = passed_fb; |
| @@ -813,17 +848,6 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
| 813 | } else { | 848 | } else { |
| 814 | drm_fb = crtc->fb; | 849 | drm_fb = crtc->fb; |
| 815 | fb = nouveau_framebuffer(crtc->fb); | 850 | fb = nouveau_framebuffer(crtc->fb); |
| 816 | /* If not atomic, we can go ahead and pin, and unpin the | ||
| 817 | * old fb we were passed. | ||
| 818 | */ | ||
| 819 | ret = nouveau_bo_pin(fb->nvbo, TTM_PL_FLAG_VRAM); | ||
| 820 | if (ret) | ||
| 821 | return ret; | ||
| 822 | |||
| 823 | if (passed_fb) { | ||
| 824 | struct nouveau_framebuffer *ofb = nouveau_framebuffer(passed_fb); | ||
| 825 | nouveau_bo_unpin(ofb->nvbo); | ||
| 826 | } | ||
| 827 | } | 851 | } |
| 828 | 852 | ||
| 829 | nv_crtc->fb.offset = fb->nvbo->bo.offset; | 853 | nv_crtc->fb.offset = fb->nvbo->bo.offset; |
| @@ -878,6 +902,9 @@ static int | |||
| 878 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | 902 | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, |
| 879 | struct drm_framebuffer *old_fb) | 903 | struct drm_framebuffer *old_fb) |
| 880 | { | 904 | { |
| 905 | int ret = nv_crtc_swap_fbs(crtc, old_fb); | ||
| 906 | if (ret) | ||
| 907 | return ret; | ||
| 881 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); | 908 | return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false); |
| 882 | } | 909 | } |
| 883 | 910 | ||
| @@ -1074,6 +1101,7 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { | |||
| 1074 | .mode_set_base = nv04_crtc_mode_set_base, | 1101 | .mode_set_base = nv04_crtc_mode_set_base, |
| 1075 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, | 1102 | .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic, |
| 1076 | .load_lut = nv_crtc_gamma_load, | 1103 | .load_lut = nv_crtc_gamma_load, |
| 1104 | .disable = nv_crtc_disable, | ||
| 1077 | }; | 1105 | }; |
| 1078 | 1106 | ||
| 1079 | int | 1107 | int |
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index a0a031dad13f..9928187f0a7d 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h | |||
| @@ -81,6 +81,7 @@ struct nv04_display { | |||
| 81 | uint32_t saved_vga_font[4][16384]; | 81 | uint32_t saved_vga_font[4][16384]; |
| 82 | uint32_t dac_users[4]; | 82 | uint32_t dac_users[4]; |
| 83 | struct nouveau_object *core; | 83 | struct nouveau_object *core; |
| 84 | struct nouveau_bo *image[2]; | ||
| 84 | }; | 85 | }; |
| 85 | 86 | ||
| 86 | static inline struct nv04_display * | 87 | static inline struct nv04_display * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e4444bacd0b2..755c38d06271 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_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 44202bf7b819..77ffded68837 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
| @@ -580,6 +580,9 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
| 580 | ret = nv50_display_flip_next(crtc, fb, chan, 0); | 580 | ret = nv50_display_flip_next(crtc, fb, chan, 0); |
| 581 | if (ret) | 581 | if (ret) |
| 582 | goto fail_unreserve; | 582 | goto fail_unreserve; |
| 583 | } else { | ||
| 584 | struct nv04_display *dispnv04 = nv04_display(dev); | ||
| 585 | nouveau_bo_ref(new_bo, &dispnv04->image[nouveau_crtc(crtc)->index]); | ||
| 583 | } | 586 | } |
| 584 | 587 | ||
| 585 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | 588 | ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); |
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 | |||
| 398 | nouveau_fbcon_output_poll_changed(struct drm_device *dev) | 398 | nouveau_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 | ||
| 404 | static int | 405 | static 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/nv40_pm.c b/drivers/gpu/drm/nouveau/nv40_pm.c index 3af5bcd0b203..625f80d53dc2 100644 --- a/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/drivers/gpu/drm/nouveau/nv40_pm.c | |||
| @@ -131,7 +131,7 @@ nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | |||
| 131 | if (clk < pll->vco1.max_freq) | 131 | if (clk < pll->vco1.max_freq) |
| 132 | pll->vco2.max_freq = 0; | 132 | pll->vco2.max_freq = 0; |
| 133 | 133 | ||
| 134 | pclk->pll_calc(pclk, pll, clk, &coef); | 134 | ret = pclk->pll_calc(pclk, pll, clk, &coef); |
| 135 | if (ret == 0) | 135 | if (ret == 0) |
| 136 | return -ERANGE; | 136 | return -ERANGE; |
| 137 | 137 | ||
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 | } |
