Commit 51b83e14 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'linux-4.15' of git://github.com/skeggsb/linux into drm-fixes

nouveau regression fixes, and some minor fixes.

* 'linux-4.15' of git://github.com/skeggsb/linux:
  drm/nouveau: use alternate memory type for system-memory buffers with kind != 0
  drm/nouveau: avoid GPU page sizes > PAGE_SIZE for buffer objects in host memory
  drm/nouveau/mmu/gp10b: use correct implementation
  drm/nouveau/pci: do a msi rearm on init
  drm/nouveau/imem/nv50: fix refcount_t warning
  drm/nouveau/bios/dp: support DP Info Table 2.0
  drm/nouveau/fbcon: fix NULL pointer access in nouveau_fbcon_destroy
parents 38f73db7 74a39954
...@@ -224,7 +224,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, ...@@ -224,7 +224,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
/* Determine if we can get a cache-coherent map, forcing /* Determine if we can get a cache-coherent map, forcing
* uncached mapping if we can't. * uncached mapping if we can't.
*/ */
if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED) if (!nouveau_drm_use_coherent_gpu_mapping(drm))
nvbo->force_coherent = true; nvbo->force_coherent = true;
} }
...@@ -262,7 +262,8 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, ...@@ -262,7 +262,8 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE && if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE &&
(flags & TTM_PL_FLAG_VRAM) && !vmm->page[i].vram) (flags & TTM_PL_FLAG_VRAM) && !vmm->page[i].vram)
continue; continue;
if ((flags & TTM_PL_FLAG_TT ) && !vmm->page[i].host) if ((flags & TTM_PL_FLAG_TT) &&
(!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT))
continue; continue;
/* Select this page size if it's the first that supports /* Select this page size if it's the first that supports
......
...@@ -157,8 +157,8 @@ struct nouveau_drm { ...@@ -157,8 +157,8 @@ struct nouveau_drm {
struct nvif_object copy; struct nvif_object copy;
int mtrr; int mtrr;
int type_vram; int type_vram;
int type_host; int type_host[2];
int type_ncoh; int type_ncoh[2];
} ttm; } ttm;
/* GEM interface support */ /* GEM interface support */
...@@ -217,6 +217,13 @@ nouveau_drm(struct drm_device *dev) ...@@ -217,6 +217,13 @@ nouveau_drm(struct drm_device *dev)
return dev->dev_private; return dev->dev_private;
} }
static inline bool
nouveau_drm_use_coherent_gpu_mapping(struct nouveau_drm *drm)
{
struct nvif_mmu *mmu = &drm->client.mmu;
return !(mmu->type[drm->ttm.type_host[0]].type & NVIF_MEM_UNCACHED);
}
int nouveau_pmops_suspend(struct device *); int nouveau_pmops_suspend(struct device *);
int nouveau_pmops_resume(struct device *); int nouveau_pmops_resume(struct device *);
bool nouveau_pmops_runtime(void); bool nouveau_pmops_runtime(void);
......
...@@ -429,7 +429,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) ...@@ -429,7 +429,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
drm_fb_helper_unregister_fbi(&fbcon->helper); drm_fb_helper_unregister_fbi(&fbcon->helper);
drm_fb_helper_fini(&fbcon->helper); drm_fb_helper_fini(&fbcon->helper);
if (nouveau_fb->nvbo) { if (nouveau_fb && nouveau_fb->nvbo) {
nouveau_vma_del(&nouveau_fb->vma); nouveau_vma_del(&nouveau_fb->vma);
nouveau_bo_unmap(nouveau_fb->nvbo); nouveau_bo_unmap(nouveau_fb->nvbo);
nouveau_bo_unpin(nouveau_fb->nvbo); nouveau_bo_unpin(nouveau_fb->nvbo);
......
...@@ -103,10 +103,10 @@ nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt) ...@@ -103,10 +103,10 @@ nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt)
u8 type; u8 type;
int ret; int ret;
if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED) if (!nouveau_drm_use_coherent_gpu_mapping(drm))
type = drm->ttm.type_ncoh; type = drm->ttm.type_ncoh[!!mem->kind];
else else
type = drm->ttm.type_host; type = drm->ttm.type_host[0];
if (mem->kind && !(mmu->type[type].type & NVIF_MEM_KIND)) if (mem->kind && !(mmu->type[type].type & NVIF_MEM_KIND))
mem->comp = mem->kind = 0; mem->comp = mem->kind = 0;
......
...@@ -235,27 +235,46 @@ nouveau_ttm_global_release(struct nouveau_drm *drm) ...@@ -235,27 +235,46 @@ nouveau_ttm_global_release(struct nouveau_drm *drm)
drm->ttm.mem_global_ref.release = NULL; drm->ttm.mem_global_ref.release = NULL;
} }
int static int
nouveau_ttm_init(struct nouveau_drm *drm) nouveau_ttm_init_host(struct nouveau_drm *drm, u8 kind)
{ {
struct nvkm_device *device = nvxx_device(&drm->client.device);
struct nvkm_pci *pci = device->pci;
struct nvif_mmu *mmu = &drm->client.mmu; struct nvif_mmu *mmu = &drm->client.mmu;
struct drm_device *dev = drm->dev; int typei;
int typei, ret;
typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE | typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE |
NVIF_MEM_COHERENT); kind | NVIF_MEM_COHERENT);
if (typei < 0) if (typei < 0)
return -ENOSYS; return -ENOSYS;
drm->ttm.type_host = typei; drm->ttm.type_host[!!kind] = typei;
typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE); typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE | kind);
if (typei < 0) if (typei < 0)
return -ENOSYS; return -ENOSYS;
drm->ttm.type_ncoh = typei; drm->ttm.type_ncoh[!!kind] = typei;
return 0;
}
int
nouveau_ttm_init(struct nouveau_drm *drm)
{
struct nvkm_device *device = nvxx_device(&drm->client.device);
struct nvkm_pci *pci = device->pci;
struct nvif_mmu *mmu = &drm->client.mmu;
struct drm_device *dev = drm->dev;
int typei, ret;
ret = nouveau_ttm_init_host(drm, 0);
if (ret)
return ret;
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
drm->client.device.info.chipset != 0x50) {
ret = nouveau_ttm_init_host(drm, NVIF_MEM_KIND);
if (ret)
return ret;
}
if (drm->client.device.info.platform != NV_DEVICE_INFO_V0_SOC && if (drm->client.device.info.platform != NV_DEVICE_INFO_V0_SOC &&
drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
......
...@@ -2369,7 +2369,7 @@ nv13b_chipset = { ...@@ -2369,7 +2369,7 @@ nv13b_chipset = {
.imem = gk20a_instmem_new, .imem = gk20a_instmem_new,
.ltc = gp100_ltc_new, .ltc = gp100_ltc_new,
.mc = gp10b_mc_new, .mc = gp10b_mc_new,
.mmu = gf100_mmu_new, .mmu = gp10b_mmu_new,
.secboot = gp10b_secboot_new, .secboot = gp10b_secboot_new,
.pmu = gm20b_pmu_new, .pmu = gm20b_pmu_new,
.timer = gk20a_timer_new, .timer = gk20a_timer_new,
......
...@@ -36,6 +36,7 @@ nvbios_dp_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) ...@@ -36,6 +36,7 @@ nvbios_dp_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
if (data) { if (data) {
*ver = nvbios_rd08(bios, data + 0x00); *ver = nvbios_rd08(bios, data + 0x00);
switch (*ver) { switch (*ver) {
case 0x20:
case 0x21: case 0x21:
case 0x30: case 0x30:
case 0x40: case 0x40:
...@@ -63,6 +64,7 @@ nvbios_dpout_entry(struct nvkm_bios *bios, u8 idx, ...@@ -63,6 +64,7 @@ nvbios_dpout_entry(struct nvkm_bios *bios, u8 idx,
if (data && idx < *cnt) { if (data && idx < *cnt) {
u16 outp = nvbios_rd16(bios, data + *hdr + idx * *len); u16 outp = nvbios_rd16(bios, data + *hdr + idx * *len);
switch (*ver * !!outp) { switch (*ver * !!outp) {
case 0x20:
case 0x21: case 0x21:
case 0x30: case 0x30:
*hdr = nvbios_rd08(bios, data + 0x04); *hdr = nvbios_rd08(bios, data + 0x04);
...@@ -96,12 +98,16 @@ nvbios_dpout_parse(struct nvkm_bios *bios, u8 idx, ...@@ -96,12 +98,16 @@ nvbios_dpout_parse(struct nvkm_bios *bios, u8 idx,
info->type = nvbios_rd16(bios, data + 0x00); info->type = nvbios_rd16(bios, data + 0x00);
info->mask = nvbios_rd16(bios, data + 0x02); info->mask = nvbios_rd16(bios, data + 0x02);
switch (*ver) { switch (*ver) {
case 0x20:
info->mask |= 0x00c0; /* match any link */
/* fall-through */
case 0x21: case 0x21:
case 0x30: case 0x30:
info->flags = nvbios_rd08(bios, data + 0x05); info->flags = nvbios_rd08(bios, data + 0x05);
info->script[0] = nvbios_rd16(bios, data + 0x06); info->script[0] = nvbios_rd16(bios, data + 0x06);
info->script[1] = nvbios_rd16(bios, data + 0x08); info->script[1] = nvbios_rd16(bios, data + 0x08);
info->lnkcmp = nvbios_rd16(bios, data + 0x0a); if (*len >= 0x0c)
info->lnkcmp = nvbios_rd16(bios, data + 0x0a);
if (*len >= 0x0f) { if (*len >= 0x0f) {
info->script[2] = nvbios_rd16(bios, data + 0x0c); info->script[2] = nvbios_rd16(bios, data + 0x0c);
info->script[3] = nvbios_rd16(bios, data + 0x0e); info->script[3] = nvbios_rd16(bios, data + 0x0e);
...@@ -170,6 +176,7 @@ nvbios_dpcfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx, ...@@ -170,6 +176,7 @@ nvbios_dpcfg_parse(struct nvkm_bios *bios, u16 outp, u8 idx,
memset(info, 0x00, sizeof(*info)); memset(info, 0x00, sizeof(*info));
if (data) { if (data) {
switch (*ver) { switch (*ver) {
case 0x20:
case 0x21: case 0x21:
info->dc = nvbios_rd08(bios, data + 0x02); info->dc = nvbios_rd08(bios, data + 0x02);
info->pe = nvbios_rd08(bios, data + 0x03); info->pe = nvbios_rd08(bios, data + 0x03);
......
...@@ -249,7 +249,7 @@ nv50_instobj_acquire(struct nvkm_memory *memory) ...@@ -249,7 +249,7 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
iobj->base.memory.ptrs = &nv50_instobj_fast; iobj->base.memory.ptrs = &nv50_instobj_fast;
else else
iobj->base.memory.ptrs = &nv50_instobj_slow; iobj->base.memory.ptrs = &nv50_instobj_slow;
refcount_inc(&iobj->maps); refcount_set(&iobj->maps, 1);
} }
mutex_unlock(&imem->subdev.mutex); mutex_unlock(&imem->subdev.mutex);
......
...@@ -136,6 +136,13 @@ nvkm_pci_init(struct nvkm_subdev *subdev) ...@@ -136,6 +136,13 @@ nvkm_pci_init(struct nvkm_subdev *subdev)
return ret; return ret;
pci->irq = pdev->irq; pci->irq = pdev->irq;
/* Ensure MSI interrupts are armed, for the case where there are
* already interrupts pending (for whatever reason) at load time.
*/
if (pci->msi)
pci->func->msi_rearm(pci);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment