Commit 74a39954 authored by Ben Skeggs's avatar Ben Skeggs

drm/nouveau: use alternate memory type for system-memory buffers with kind != 0

Fixes bug on Tegra where we'd strip kind information from system memory
(ie. all) buffers, resulting in misrendering.

Behaviour on dGPU should be unchanged.
Reported-by: default avatarThierry Reding <treding@nvidia.com>
Fixes: d7722134 ("drm/nouveau: switch over to new memory and vmm interfaces")
Signed-off-by: default avatarBen Skeggs <bskeggs@redhat.com>
Tested-by: default avatarThierry Reding <treding@nvidia.com>
parent f29f18eb
...@@ -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;
} }
......
...@@ -156,8 +156,8 @@ struct nouveau_drm { ...@@ -156,8 +156,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 */
...@@ -216,6 +216,13 @@ nouveau_drm(struct drm_device *dev) ...@@ -216,6 +216,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);
......
...@@ -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) {
......
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