* [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3)
@ 2026-07-06 3:05 Dave Airlie
2026-07-06 3:16 ` sashiko-bot
2026-07-12 16:14 ` Danilo Krummrich
0 siblings, 2 replies; 3+ messages in thread
From: Dave Airlie @ 2026-07-06 3:05 UTC (permalink / raw)
To: dri-devel, nouveau; +Cc: dakr
From: Dave Airlie <airlied@redhat.com>
This avoids constant need to ioremap when instobjs move at least
on 64-bit systems.
This create the io mapping on first use, because creating it at init
time causes a resource mapping error, because nouveau hasn't kicked
simpledrm off the hardware yet, but ioremap_wc the whole BAR causes
an overlap with BOOTFB/simpledrm. I think the resource system could
do better here, but it's easier to just delay creating the mapping
until first use.
Signed-off-by: Dave Airlie <airlied@redhat.com>
---
v2: move the mapping into the main code.
v3: fixup some Sashiko review, just do mapping in boot code
which should always be called for bar2.
---
.../nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c | 1 +
.../drm/nouveau/nvkm/subdev/instmem/nv50.c | 39 ++++++++++++++-----
.../drm/nouveau/nvkm/subdev/instmem/priv.h | 1 +
3 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
index 700cea5def35..f128330f30d7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c
@@ -297,6 +297,7 @@ r535_fbsr = {
static void *
r535_instmem_dtor(struct nvkm_instmem *imem)
{
+ nv50_instmem_dtor(imem);
kfree(imem->func);
return imem;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
index 6fbaa1e5876d..f4489efc94a7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -30,10 +30,14 @@
#include <subdev/gsp.h>
#include <subdev/mmu.h>
+#include <linux/io-mapping.h>
+
struct nv50_instmem {
struct nvkm_instmem base;
u64 addr;
+ struct io_mapping iomap;
+
/* Mappings that can be evicted when BAR2 space has been exhausted. */
struct list_head lru;
};
@@ -124,7 +128,6 @@ nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
struct nv50_instobj *eobj;
struct nvkm_memory *memory = &iobj->base.memory;
struct nvkm_subdev *subdev = &imem->base.subdev;
- struct nvkm_device *device = subdev->device;
struct nvkm_vma *bar = NULL, *ebar;
u64 size = nvkm_memory_size(memory);
void *emap;
@@ -155,7 +158,7 @@ nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
mutex_unlock(&imem->base.mutex);
if (!eobj)
break;
- iounmap(emap);
+ io_mapping_unmap(emap);
nvkm_vmm_put(vmm, &ebar);
}
@@ -172,8 +175,7 @@ nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm)
/* Make the mapping visible to the host. */
iobj->bar = bar;
- iobj->map = ioremap_wc(device->func->resource_addr(device, NVKM_BAR2_INST) +
- (u32)iobj->bar->addr, size);
+ iobj->map = io_mapping_map_wc(&imem->iomap, (u32)iobj->bar->addr, size);
if (!iobj->map) {
nvkm_warn(subdev, "PRAMIN ioremap failed\n");
nvkm_vmm_put(vmm, &iobj->bar);
@@ -188,6 +190,16 @@ nv50_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
return nvkm_memory_map(memory, offset, vmm, vma, argv, argc);
}
+static bool
+check_io_mapping(struct nv50_instmem *imem)
+{
+ struct nvkm_device *device = imem->base.subdev.device;
+
+ return io_mapping_init_wc(&imem->iomap,
+ device->func->resource_addr(device, NVKM_BAR2_INST),
+ device->func->resource_size(device, NVKM_BAR2_INST)) != NULL;
+}
+
static void
nv50_instobj_release(struct nvkm_memory *memory)
{
@@ -239,7 +251,7 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
/* Attempt to get a direct CPU mapping of the object. */
if ((vmm = nvkm_bar_bar2_vmm(imem->subdev.device))) {
- if (!iobj->map)
+ if (!iobj->map && iobj->imem->iomap.size)
nv50_instobj_kmap(iobj, vmm);
map = iobj->map;
}
@@ -277,7 +289,12 @@ nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vmm *vmm)
iobj->lru.next = NULL;
}
- nv50_instobj_kmap(iobj, vmm);
+ /*
+ * boot is only called on BAR2, if we can't remap the complete
+ * BAR it's unlikely things are functioning well.
+ */
+ if (check_io_mapping(iobj->imem))
+ nv50_instobj_kmap(iobj, vmm);
nvkm_instmem_boot(imem);
mutex_unlock(&imem->mutex);
}
@@ -330,7 +347,7 @@ nv50_instobj_dtor(struct nvkm_memory *memory)
if (map) {
struct nvkm_vmm *vmm = nvkm_bar_bar2_vmm(imem->subdev.device);
- iounmap(map);
+ io_mapping_unmap(map);
if (likely(vmm)) /* Can be NULL during BAR destructor. */
nvkm_vmm_put(vmm, &bar);
}
@@ -406,10 +423,14 @@ nv50_instmem_fini(struct nvkm_instmem *base)
nv50_instmem(base)->addr = ~0ULL;
}
-static void *
+void *
nv50_instmem_dtor(struct nvkm_instmem *base)
{
- return nv50_instmem(base);
+ struct nv50_instmem *imem = nv50_instmem(base);
+
+ if (imem->iomap.size)
+ io_mapping_fini(&imem->iomap);
+ return imem;
}
static const struct nvkm_instmem_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
index 87bbdd786eaa..b423f01f5fcd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
@@ -26,6 +26,7 @@ int nv50_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero,
struct nvkm_memory **);
int nv50_instobj_wrap(struct nvkm_instmem *, struct nvkm_memory *vram,
struct nvkm_memory **bar2);
+void *nv50_instmem_dtor(struct nvkm_instmem *base);
void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *,
enum nvkm_subdev_type, int, struct nvkm_instmem *);
--
2.54.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3)
2026-07-06 3:05 [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3) Dave Airlie
@ 2026-07-06 3:16 ` sashiko-bot
2026-07-12 16:14 ` Danilo Krummrich
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-07-06 3:16 UTC (permalink / raw)
To: Dave Airlie; +Cc: dri-devel
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Unconditional execution of io_mapping_init_wc() in check_io_mapping() causes severe ioremap_wc memory leaks during BAR2 bootstrapping.
--
commit 17419e048ef493385192b9b14726d1e9ad616fed
Author: Dave Airlie <airlied@redhat.com>
nouveau/instmem: use iomapping interface for instmem handling (v3)
This replaces constant ioremapping with the io_mapping interface to avoid
the constant need to ioremap when instobjs move. It delays creating the
mapping until first use to avoid resource mapping errors with simpledrm.
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
> index 6fbaa1e5876dc..f4489efc94a79 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
[ ... ]
> @@ -188,6 +190,16 @@ nv50_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
> return nvkm_memory_map(memory, offset, vmm, vma, argv, argc);
> }
>
> +static bool
> +check_io_mapping(struct nv50_instmem *imem)
> +{
> + struct nvkm_device *device = imem->base.subdev.device;
> +
> + return io_mapping_init_wc(&imem->iomap,
> + device->func->resource_addr(device, NVKM_BAR2_INST),
> + device->func->resource_size(device, NVKM_BAR2_INST)) != NULL;
> +}
> +
[Severity: High]
Does this unconditionally initialize the mapping and leak the previous
ioremap_wc allocation if called more than once?
Since nv50_instobj_boot() acts as the .boot callback for BAR2 page tables,
it is invoked for every leaf page table during VMM bootstrap. Because BAR2
typically spans multiple page tables, check_io_mapping() gets executed
multiple times in a loop.
Should this check if the mapping is already initialized (e.g., checking if
imem->iomap.size is non-zero) before calling io_mapping_init_wc() to avoid
leaking the vmalloc space?
> static void
> nv50_instobj_release(struct nvkm_memory *memory)
> {
[ ... ]
> @@ -277,7 +289,12 @@ nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vmm *vmm)
> iobj->lru.next = NULL;
> }
>
> - nv50_instobj_kmap(iobj, vmm);
> + /*
> + * boot is only called on BAR2, if we can't remap the complete
> + * BAR it's unlikely things are functioning well.
> + */
> + if (check_io_mapping(iobj->imem))
> + nv50_instobj_kmap(iobj, vmm);
> nvkm_instmem_boot(imem);
> mutex_unlock(&imem->mutex);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260706030520.857104-1-airlied@gmail.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3)
2026-07-06 3:05 [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3) Dave Airlie
2026-07-06 3:16 ` sashiko-bot
@ 2026-07-12 16:14 ` Danilo Krummrich
1 sibling, 0 replies; 3+ messages in thread
From: Danilo Krummrich @ 2026-07-12 16:14 UTC (permalink / raw)
To: Dave Airlie; +Cc: dri-devel, nouveau, dakr
On Mon, 6 Jul 2026 13:05:20 +1000, Dave Airlie wrote:
> [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3)
Applied, thanks!
Branch: drm-misc-next
Tree: https://gitlab.freedesktop.org/drm/misc/kernel.git
[1/1] nouveau/instmem: use iomapping interface for instmem handling
commit: 34e27b90552a
The patch will appear in the next linux-next integration (typically within 24
hours on weekdays).
The patch is queued up for the upcoming merge window for the next major kernel
release.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-12 16:14 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 3:05 [PATCH] nouveau/instmem: use iomapping interface for instmem handling (v3) Dave Airlie
2026-07-06 3:16 ` sashiko-bot
2026-07-12 16:14 ` Danilo Krummrich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox