Commit 46dec616 authored by Thierry Reding's avatar Thierry Reding Committed by Dave Airlie

drm/nouveau: Fixup gk20a instobj hierarchy

Commit 12c9b05d ("drm/nouveau/imem: support allocations not
preserved across suspend") uses container_of() to cast from struct
nvkm_memory to struct nvkm_instobj, assuming that all instance objects
are derived from struct nvkm_instobj. For the gk20a family that's not
the case and they are derived from struct nvkm_memory instead. This
causes some subtle data corruption (nvkm_instobj.preserve ends up
mapping to gk20a_instobj.vaddr) that causes a NULL pointer dereference
in gk20a_instobj_acquire_iommu() (and possibly elsewhere) and also
prevents suspend/resume from working.

Fix this by making struct gk20a_instobj derive from struct nvkm_instobj
instead.

Fixes: 12c9b05d ("drm/nouveau/imem: support allocations not preserved across suspend")
Reported-by: default avatarJonathan Hunter <jonathanh@nvidia.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Tested-by: default avatarJon Hunter <jonathanh@nvidia.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231208104653.1917055-1-thierry.reding@gmail.com
parent f8678a33
...@@ -49,14 +49,14 @@ ...@@ -49,14 +49,14 @@
#include <subdev/mmu.h> #include <subdev/mmu.h>
struct gk20a_instobj { struct gk20a_instobj {
struct nvkm_memory memory; struct nvkm_instobj base;
struct nvkm_mm_node *mn; struct nvkm_mm_node *mn;
struct gk20a_instmem *imem; struct gk20a_instmem *imem;
/* CPU mapping */ /* CPU mapping */
u32 *vaddr; u32 *vaddr;
}; };
#define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory) #define gk20a_instobj(p) container_of((p), struct gk20a_instobj, base.memory)
/* /*
* Used for objects allocated using the DMA API * Used for objects allocated using the DMA API
...@@ -148,7 +148,7 @@ gk20a_instobj_iommu_recycle_vaddr(struct gk20a_instobj_iommu *obj) ...@@ -148,7 +148,7 @@ gk20a_instobj_iommu_recycle_vaddr(struct gk20a_instobj_iommu *obj)
list_del(&obj->vaddr_node); list_del(&obj->vaddr_node);
vunmap(obj->base.vaddr); vunmap(obj->base.vaddr);
obj->base.vaddr = NULL; obj->base.vaddr = NULL;
imem->vaddr_use -= nvkm_memory_size(&obj->base.memory); imem->vaddr_use -= nvkm_memory_size(&obj->base.base.memory);
nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", imem->vaddr_use, nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", imem->vaddr_use,
imem->vaddr_max); imem->vaddr_max);
} }
...@@ -283,7 +283,7 @@ gk20a_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, ...@@ -283,7 +283,7 @@ gk20a_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
{ {
struct gk20a_instobj *node = gk20a_instobj(memory); struct gk20a_instobj *node = gk20a_instobj(memory);
struct nvkm_vmm_map map = { struct nvkm_vmm_map map = {
.memory = &node->memory, .memory = &node->base.memory,
.offset = offset, .offset = offset,
.mem = node->mn, .mem = node->mn,
}; };
...@@ -391,8 +391,8 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align, ...@@ -391,8 +391,8 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align,
return -ENOMEM; return -ENOMEM;
*_node = &node->base; *_node = &node->base;
nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory); nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.base.memory);
node->base.memory.ptrs = &gk20a_instobj_ptrs; node->base.base.memory.ptrs = &gk20a_instobj_ptrs;
node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT,
&node->handle, GFP_KERNEL, &node->handle, GFP_KERNEL,
...@@ -438,8 +438,8 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, ...@@ -438,8 +438,8 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align,
*_node = &node->base; *_node = &node->base;
node->dma_addrs = (void *)(node->pages + npages); node->dma_addrs = (void *)(node->pages + npages);
nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory); nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.base.memory);
node->base.memory.ptrs = &gk20a_instobj_ptrs; node->base.base.memory.ptrs = &gk20a_instobj_ptrs;
/* Allocate backing memory */ /* Allocate backing memory */
for (i = 0; i < npages; i++) { for (i = 0; i < npages; i++) {
...@@ -533,7 +533,7 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, ...@@ -533,7 +533,7 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
else else
ret = gk20a_instobj_ctor_dma(imem, size >> PAGE_SHIFT, ret = gk20a_instobj_ctor_dma(imem, size >> PAGE_SHIFT,
align, &node); align, &node);
*pmemory = node ? &node->memory : NULL; *pmemory = node ? &node->base.memory : NULL;
if (ret) if (ret)
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