* Re: [PATCH v7 00/23] nova-core: Add memory management support
From: Alexandre Courbot @ 2026-02-20 1:54 UTC (permalink / raw)
To: Joel Fernandes
Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Danilo Krummrich, Alice Ryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Alistair Popple, Andrea Righi, Zhi Wang,
Philipp Stanner, Elle Rhumsaa, Daniel Almeida, Eliot Courtney,
joel, nouveau, dri-devel, rust-for-linux, linux-doc, amd-gfx,
intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260219194838.GA1013545@joelbox2>
On Fri Feb 20, 2026 at 4:48 AM JST, Joel Fernandes wrote:
> Hi Alex,
>
> Thanks for taking the time to go through the series and for the effort
> of doing the reordering. Just to clarify, do you mean I should be
> sending each of the phases separately for review instead of in one
> series?
>
> By any chance, do you have the tree after doing the rearrangement that I
> could take a look at? That would be very helpful so I don't repeat your
> rearrangement effort.
Sure: https://github.com/Gnurou/linux/tree/review/nova-mm-v10
I have rebased it on top of your `nova-mm-v7-20260218` tag, hopefully
that makes it easier to pick.
The top-of-trees of both my branch and your tag are identical, and I've
tried to limit the changes in each patch, but you will want to quickly
check them. I have fixed the transient build errors, but not the
formatting or clippy warnings to make sure my top-of-tree stayed
identical to yours and I haven't introduced any regression.
^ permalink raw reply
* [PATCH v2] gpu: ipu-v3: clean up kernel-doc warnings
From: Randy Dunlap @ 2026-02-19 21:52 UTC (permalink / raw)
To: dri-devel
Cc: Randy Dunlap, Philipp Zabel, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, imx,
linux-arm-kernel, Helge Deller, linux-fbdev
Correct all kernel-doc warnings:
- fix a typedef kernel-doc comment
- mark a list_head as private
- use Returns: for function return values
Warning: include/video/imx-ipu-image-convert.h:31 struct member 'list' not
described in 'ipu_image_convert_run'
Warning: include/video/imx-ipu-image-convert.h:40 function parameter
'ipu_image_convert_cb_t' not described in 'void'
Warning: include/video/imx-ipu-image-convert.h:40 expecting prototype for
ipu_image_convert_cb_t(). Prototype was for void() instead
Warning: include/video/imx-ipu-image-convert.h:66 No description found for
return value of 'ipu_image_convert_verify'
Warning: include/video/imx-ipu-image-convert.h:90 No description found for
return value of 'ipu_image_convert_prepare'
Warning: include/video/imx-ipu-image-convert.h:125 No description found for
return value of 'ipu_image_convert_queue'
Warning: include/video/imx-ipu-image-convert.h:163 No description found for
return value of 'ipu_image_convert'
Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
---
v2: add Reviewed-by, update Cc: list, rebase, resend
Cc: Philipp Zabel <p.zabel@pengutronix.de>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: imx@lists.linux.dev
Cc: linux-arm-kernel@lists.infradead.org
Cc: Helge Deller <deller@gmx.de>
Cc: linux-fbdev@vger.kernel.org
include/video/imx-ipu-image-convert.h | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
--- linux-next-20260218.orig/include/video/imx-ipu-image-convert.h
+++ linux-next-20260218/include/video/imx-ipu-image-convert.h
@@ -27,12 +27,13 @@ struct ipu_image_convert_run {
int status;
+ /* private: */
/* internal to image converter, callers don't touch */
struct list_head list;
};
/**
- * ipu_image_convert_cb_t - conversion callback function prototype
+ * typedef ipu_image_convert_cb_t - conversion callback function prototype
*
* @run: the completed conversion run pointer
* @ctx: a private context pointer for the callback
@@ -60,7 +61,7 @@ void ipu_image_convert_adjust(struct ipu
* @out: output image format
* @rot_mode: rotation mode
*
- * Returns 0 if the formats and rotation mode meet IPU restrictions,
+ * Returns: 0 if the formats and rotation mode meet IPU restrictions,
* -EINVAL otherwise.
*/
int ipu_image_convert_verify(struct ipu_image *in, struct ipu_image *out,
@@ -77,11 +78,11 @@ int ipu_image_convert_verify(struct ipu_
* @complete: run completion callback
* @complete_context: a context pointer for the completion callback
*
- * Returns an opaque conversion context pointer on success, error pointer
+ * In V4L2, drivers should call ipu_image_convert_prepare() at streamon.
+ *
+ * Returns: an opaque conversion context pointer on success, error pointer
* on failure. The input/output formats and rotation mode must already meet
* IPU retrictions.
- *
- * In V4L2, drivers should call ipu_image_convert_prepare() at streamon.
*/
struct ipu_image_convert_ctx *
ipu_image_convert_prepare(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
@@ -122,6 +123,8 @@ void ipu_image_convert_unprepare(struct
* In V4L2, drivers should call ipu_image_convert_queue() while
* streaming to queue the conversion of a received input buffer.
* For example mem2mem devices this would be called in .device_run.
+ *
+ * Returns: 0 on success or -errno on error.
*/
int ipu_image_convert_queue(struct ipu_image_convert_run *run);
@@ -155,6 +158,9 @@ void ipu_image_convert_abort(struct ipu_
* On successful return the caller can queue more run requests if needed, using
* the prepared context in run->ctx. The caller is responsible for unpreparing
* the context when no more conversion requests are needed.
+ *
+ * Returns: pointer to the created &struct ipu_image_convert_run that has
+ * been queued on success; an ERR_PTR(errno) on error.
*/
struct ipu_image_convert_run *
ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,
^ permalink raw reply
* Re: [PATCH v7 00/23] nova-core: Add memory management support
From: Joel Fernandes @ 2026-02-19 19:48 UTC (permalink / raw)
To: Alexandre Courbot
Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Danilo Krummrich, Alice Ryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Alistair Popple, Andrea Righi, Zhi Wang,
Philipp Stanner, Elle Rhumsaa, Daniel Almeida, Eliot Courtney,
joel, nouveau, dri-devel, rust-for-linux, linux-doc, amd-gfx,
intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <DGJ1G3D32OMK.30HANB1W46XVL@nvidia.com>
Hi Alex,
Thanks for taking the time to go through the series and for the effort
of doing the reordering. Just to clarify, do you mean I should be
sending each of the phases separately for review instead of in one
series?
By any chance, do you have the tree after doing the rearrangement that I
could take a look at? That would be very helpful so I don't repeat your
rearrangement effort.
Some comments below:
> Nice series, a few overall remarks before I dive deeper into each patch:
>
> - Use `gpu: nova-core:` (not just `nova-core:`) as the patch prefix.
Done.
> - There were a few clippy warnings/rustfmt diffs when I built it.
> - There are build failures introduced in patches 11 and 18 - basically
> the series doesn't build from 11 until the last patch.
> - This patchset is using the `module/mod.rs` pattern instead of
> `module.rs` for new modules. The latter is the preferred norm IIUC.
I will work on fixing these based on the reordered patches for the next
spin.
> Phase 1: GSP plumbing
> - nova-core: gsp: Return GspStaticInfo and FbLayout from boot()
> - nova-core: gsp: Extract usable FB region from GSP
> - nova-core: fb: Add usable_vram field to FbLayout
>
> These constitute a logical change by themselves, by getting more
> information from the GSP to know how much VRAM we have. You could even
> display the result as a dev_info of dev_dbg to remove the only remaining
> `dead_code`.
This looks good to me.
> Phase 2: PRAMIN support
> - nova-core: mm: Add support to use PRAMIN windows to write to VRAM
> - docs: gpu: nova-core: Document the PRAMIN aperture mechanism
>
> PRAMIN is needed by everything that follows.
This looks good to me.
> Phase 3: GpuMm
> - nova-core: mm: Add common memory management types
> - nova-core: mm: Add TLB flush support
> - nova-core: mm: Add GpuMm centralized memory manager
> - nova-core: mm: Use usable VRAM region for buddy allocator
>
> The common memory management types patch and TLB give us all we need to
> introduce GpuMm, which makes it more accessible that after going through
> all the page table types which it doesn't depend on. This culminates
> with using the result of phase 1, which also allows you to get rid of
> the temporary 1MB window hack if you rearrange the code a bit.
Yeah, that is a nice advantage!
> Phase 4: page tables / VMM
> - nova-core: mm: Add common types for all page table formats
> - nova-core: mm: Add MMU v2 page table types
> - nova-core: mm: Add MMU v3 page table types
> - nova-core: mm: Add unified page table entry wrapper enums
> - nova-core: mm: Add page table walker for MMU v2/v3
> - nova-core: mm: Add Virtual Memory Manager
> - nova-core: mm: Add virtual address range tracking to VMM
> - nova-core: mm: Add multi-page mapping API to VMM
>
> The main course, required for BAR1 - these follow the original order.
Sounds good.
> Phase 5: BAR1
> - nova-core: Add BAR1 aperture type and size constant
> - nova-core: gsp: Add BAR1 PDE base accessors
> - nova-core: mm: Add BAR1 user interface
> - nova-core: mm: Add BarUser to struct Gpu and create at boot
These sound good to me.
> All the BAR1 stuff now happens in one place. There is certainly room for
> merging a few patches to avoid introducing dead code and eliminating
> just after.
Yeah, I tried to keep the commits at a reasonable size to make review
easier. I will look into merging a little more to see where it is possible.
> Phase 6: tests
> - nova-core: mm: Add PRAMIN aperture self-tests
> - nova-core: mm: Add BAR1 memory management self-tests
This sounds good to me.
> I have done this reordering locally and it seems to build fine.
Please share your reorder tree if you still have it. That would likely save
me a lot of effort. Thanks.
> I'll do a patch-by-patch review following this order, but I wanted to
> share it first for other reviewers of this revision as it makes the
> series more accessible IMHO.
Looking forward to it. Thanks!
--
Joel Fernandes
^ permalink raw reply
* Re: [PATCH v7 00/23] nova-core: Add memory management support
From: Alexandre Courbot @ 2026-02-19 15:20 UTC (permalink / raw)
To: Joel Fernandes
Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Danilo Krummrich, Alice Ryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Alistair Popple, Andrea Righi, Zhi Wang,
Philipp Stanner, Elle Rhumsaa, Daniel Almeida, Eliot Courtney,
joel, nouveau, dri-devel, rust-for-linux, linux-doc, amd-gfx,
intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
Hi Joel,
On Thu Feb 19, 2026 at 6:19 AM JST, Joel Fernandes wrote:
> This series adds support for nova-core memory management, including VRAM
> allocation, PRAMIN, VMM, page table walking, and BAR 1 read/writes.
> These are critical for channel management, vGPU, and all memory
> management uses.
>
> These patches depend on the following preparatory patches:
> https://lore.kernel.org/all/20260218205507.689429-1-joelagnelf@nvidia.com/T/#t
>
> All patches (including the preparatory patches from the other series) can
> be found at:
> git://git.kernel.org/pub/scm/linux/kernel/git/jfern/linux.git (branch nova/mm or tag: nova-mm-v7-20260218)
>
> Earlier series of these patches:
> https://lore.kernel.org/linux-fbdev/DG0MRL6T7ACW.25G3GLJMP7PN1@kernel.org/T/#t
> https://lore.kernel.org/linux-fbdev/20260210233204.790524-1-joelagnelf@nvidia.com/
>
> Joel Fernandes (23):
> nova-core: mm: Add support to use PRAMIN windows to write to VRAM
> docs: gpu: nova-core: Document the PRAMIN aperture mechanism
> nova-core: Add BAR1 aperture type and size constant
> nova-core: gsp: Add BAR1 PDE base accessors
> nova-core: mm: Add common memory management types
> nova-core: mm: Add common types for all page table formats
> nova-core: mm: Add MMU v2 page table types
> nova-core: mm: Add MMU v3 page table types
> nova-core: mm: Add unified page table entry wrapper enums
> nova-core: mm: Add TLB flush support
> nova-core: mm: Add GpuMm centralized memory manager
> nova-core: mm: Add page table walker for MMU v2/v3
> nova-core: mm: Add Virtual Memory Manager
> nova-core: mm: Add virtual address range tracking to VMM
> nova-core: mm: Add multi-page mapping API to VMM
> nova-core: mm: Add BAR1 user interface
> nova-core: gsp: Return GspStaticInfo and FbLayout from boot()
> nova-core: mm: Add BAR1 memory management self-tests
> nova-core: mm: Add PRAMIN aperture self-tests
> nova-core: gsp: Extract usable FB region from GSP
> nova-core: fb: Add usable_vram field to FbLayout
> nova-core: mm: Use usable VRAM region for buddy allocator
> nova-core: mm: Add BarUser to struct Gpu and create at boot
Nice series, a few overall remarks before I dive deeper into each patch:
- Use `gpu: nova-core:` (not just `nova-core:`) as the patch prefix.
- There were a few clippy warnings/rustfmt diffs when I built it.
- There are build failures introduced in patches 11 and 18 - basically
the series doesn't build from 11 until the last patch.
- This patchset is using the `module/mod.rs` pattern instead of
`module.rs` for new modules. The latter is the preferred norm IIUC.
The end result of the series looks coherent, but the ordering of patches
makes it more tedious to review than it needs to be. We start with
PRAMIN, then add some BAR1 types that are not used until 10+ patches
later, switch to getting the framebuffer size from the GSP, add tests,
go back to GSP, etc. It is difficult to follow all these intertwined
topics (even though they eventually converge) and to know which of the
previous patches are relevant to the current one.
But there is a clear path, and after moving patches around (with only
very trivial conflicts) I got the following ordering which is more
logical IMHO:
Phase 1: GSP plumbing
- nova-core: gsp: Return GspStaticInfo and FbLayout from boot()
- nova-core: gsp: Extract usable FB region from GSP
- nova-core: fb: Add usable_vram field to FbLayout
These constitute a logical change by themselves, by getting more
information from the GSP to know how much VRAM we have. You could even
display the result as a dev_info of dev_dbg to remove the only remaining
`dead_code`.
Phase 2: PRAMIN support
- nova-core: mm: Add support to use PRAMIN windows to write to VRAM
- docs: gpu: nova-core: Document the PRAMIN aperture mechanism
PRAMIN is needed by everything that follows.
Phase 3: GpuMm
- nova-core: mm: Add common memory management types
- nova-core: mm: Add TLB flush support
- nova-core: mm: Add GpuMm centralized memory manager
- nova-core: mm: Use usable VRAM region for buddy allocator
The common memory management types patch and TLB give us all we need to
introduce GpuMm, which makes it more accessible that after going through
all the page table types which it doesn't depend on. This culminates
with using the result of phase 1, which also allows you to get rid of
the temporary 1MB window hack if you rearrange the code a bit.
Phase 4: page tables / VMM
- nova-core: mm: Add common types for all page table formats
- nova-core: mm: Add MMU v2 page table types
- nova-core: mm: Add MMU v3 page table types
- nova-core: mm: Add unified page table entry wrapper enums
- nova-core: mm: Add page table walker for MMU v2/v3
- nova-core: mm: Add Virtual Memory Manager
- nova-core: mm: Add virtual address range tracking to VMM
- nova-core: mm: Add multi-page mapping API to VMM
The main course, required for BAR1 - these follow the original order.
Phase 5: BAR1
- nova-core: Add BAR1 aperture type and size constant
- nova-core: gsp: Add BAR1 PDE base accessors
- nova-core: mm: Add BAR1 user interface
- nova-core: mm: Add BarUser to struct Gpu and create at boot
All the BAR1 stuff now happens in one place. There is certainly room for
merging a few patches to avoid introducing dead code and eliminating
just after.
Phase 6: tests
- nova-core: mm: Add PRAMIN aperture self-tests
- nova-core: mm: Add BAR1 memory management self-tests
I have done this reordering locally and it seems to build fine.
I'll do a patch-by-patch review following this order, but I wanted to
share it first for other reviewers of this revision as it makes the
series more accessible IMHO.
^ permalink raw reply
* Re: [PATCH v2] staging: fbtft: fb_tinylcd: replace udelay() with fsleep()
From: Andy Shevchenko @ 2026-02-19 14:55 UTC (permalink / raw)
To: tomasz.unger
Cc: andy, gregkh, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260219142942.74087-1-tomasz.unger@yahoo.pl>
On Thu, Feb 19, 2026 at 03:29:42PM +0100, tomasz.unger@yahoo.pl wrote:
> fsleep() is the preferred modern API for flexible sleeping as it
> automatically selects the best sleep mechanism based on the duration.
> Replace udelay() with fsleep() to improve power efficiency.
>
> init_display() is a driver initialization callback which runs in
> sleeping context, so fsleep() is safe to use here.
OK.
Acked-by: Andy Shevchenko <andriy.shevchenko@intel.com>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* [PATCH v2] staging: fbtft: fb_tinylcd: replace udelay() with fsleep()
From: tomasz.unger @ 2026-02-19 14:29 UTC (permalink / raw)
To: andy, gregkh
Cc: dri-devel, linux-fbdev, linux-staging, linux-kernel, Tomasz Unger
In-Reply-To: <20260219142942.74087-1-tomasz.unger.ref@yahoo.pl>
From: Tomasz Unger <tomasz.unger@yahoo.pl>
fsleep() is the preferred modern API for flexible sleeping as it
automatically selects the best sleep mechanism based on the duration.
Replace udelay() with fsleep() to improve power efficiency.
init_display() is a driver initialization callback which runs in
sleeping context, so fsleep() is safe to use here.
Signed-off-by: Tomasz Unger <tomasz.unger@yahoo.pl>
---
Changes in v2:
- Added sleeping context justification to commit message
- Replaced usleep_range() with fsleep() as suggested by Andy Shevchenko
drivers/staging/fbtft/fb_tinylcd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/fbtft/fb_tinylcd.c b/drivers/staging/fbtft/fb_tinylcd.c
index 9469248f2c50..3fb15df31592 100644
--- a/drivers/staging/fbtft/fb_tinylcd.c
+++ b/drivers/staging/fbtft/fb_tinylcd.c
@@ -41,7 +41,7 @@ static int init_display(struct fbtft_par *par)
0x00, 0x35, 0x33, 0x00, 0x00, 0x00);
write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
- udelay(250);
+ fsleep(250);
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
return 0;
--
2.53.0
^ permalink raw reply related
* [PATCH] staging: fbtft: fb_tinylcd: replace udelay() with fsleep()
From: tomasz.unger @ 2026-02-19 10:56 UTC (permalink / raw)
To: andy, gregkh
Cc: dri-devel, linux-fbdev, linux-staging, linux-kernel, Tomasz Unger
In-Reply-To: <20260219105628.43534-1-tomasz.unger.ref@yahoo.pl>
From: Tomasz Unger <tomasz.unger@yahoo.pl>
fsleep() is the preferred modern API for flexible sleeping as it
automatically selects the best sleep mechanism based on the duration.
Replace udelay() with fsleep() to improve power efficiency.
Signed-off-by: Tomasz Unger <tomasz.unger@yahoo.pl>
---
drivers/staging/fbtft/fb_tinylcd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/fbtft/fb_tinylcd.c b/drivers/staging/fbtft/fb_tinylcd.c
index 9469248f2c50..3fb15df31592 100644
--- a/drivers/staging/fbtft/fb_tinylcd.c
+++ b/drivers/staging/fbtft/fb_tinylcd.c
@@ -41,7 +41,7 @@ static int init_display(struct fbtft_par *par)
0x00, 0x35, 0x33, 0x00, 0x00, 0x00);
write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
- udelay(250);
+ fsleep(250);
write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
return 0;
--
2.53.0
^ permalink raw reply related
* Re: [PATCH] staging: fbtft: fb_tinylcd: replace udelay() with fsleep()
From: Greg KH @ 2026-02-19 11:16 UTC (permalink / raw)
To: tomasz.unger; +Cc: andy, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260219105628.43534-1-tomasz.unger@yahoo.pl>
On Thu, Feb 19, 2026 at 11:56:28AM +0100, tomasz.unger@yahoo.pl wrote:
> From: Tomasz Unger <tomasz.unger@yahoo.pl>
>
> fsleep() is the preferred modern API for flexible sleeping as it
> automatically selects the best sleep mechanism based on the duration.
> Replace udelay() with fsleep() to improve power efficiency.
>
> Signed-off-by: Tomasz Unger <tomasz.unger@yahoo.pl>
> ---
> drivers/staging/fbtft/fb_tinylcd.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/staging/fbtft/fb_tinylcd.c b/drivers/staging/fbtft/fb_tinylcd.c
> index 9469248f2c50..3fb15df31592 100644
> --- a/drivers/staging/fbtft/fb_tinylcd.c
> +++ b/drivers/staging/fbtft/fb_tinylcd.c
> @@ -41,7 +41,7 @@ static int init_display(struct fbtft_par *par)
> 0x00, 0x35, 0x33, 0x00, 0x00, 0x00);
> write_reg(par, MIPI_DCS_SET_PIXEL_FORMAT, 0x55);
> write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE);
> - udelay(250);
> + fsleep(250);
> write_reg(par, MIPI_DCS_SET_DISPLAY_ON);
>
> return 0;
> --
> 2.53.0
>
Hi,
This is the friendly patch-bot of Greg Kroah-Hartman. You have sent him
a patch that has triggered this response. He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created. Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.
You are receiving this message because of the following common error(s)
as indicated below:
- This looks like a new version of a previously submitted patch, but you
did not list below the --- line any changes from the previous version.
Please read the section entitled "The canonical patch format" in the
kernel file, Documentation/process/submitting-patches.rst for what
needs to be done here to properly describe this.
- You sent a patch that has been sent multiple times in the past, and is
identical to ones that have been rejected. Please always look at the
mailing list traffic to determine if you are duplicating other
people's work.
If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.
thanks,
greg k-h's patch email bot
^ permalink raw reply
* Re: [PATCH] staging: fbtft: fb_tinylcd: replace udelay() with fsleep()
From: Andy Shevchenko @ 2026-02-19 11:03 UTC (permalink / raw)
To: tomasz.unger
Cc: andy, gregkh, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260219105628.43534-1-tomasz.unger@yahoo.pl>
On Thu, Feb 19, 2026 at 11:56:28AM +0100, tomasz.unger@yahoo.pl wrote:
> fsleep() is the preferred modern API for flexible sleeping as it
> automatically selects the best sleep mechanism based on the duration.
> Replace udelay() with fsleep() to improve power efficiency.
Is this sleeping context?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH] staging: fbtft: fb_upd161704: replace udelay with usleep_range
From: Andy Shevchenko @ 2026-02-19 7:30 UTC (permalink / raw)
To: tomasz.unger
Cc: andy, gregkh, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260218180347.88034-1-tomasz.unger@yahoo.pl>
On Wed, Feb 18, 2026 at 07:03:47PM +0100, tomasz.unger@yahoo.pl wrote:
> From: Tomasz Unger <tomasz.unger@yahoo.pl>
NAK.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH] staging: fbtft: fb_tinylcd: replace udelay with usleep_range
From: Andy Shevchenko @ 2026-02-19 7:30 UTC (permalink / raw)
To: tomasz.unger
Cc: andy, gregkh, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260218175517.87544-1-tomasz.unger@yahoo.pl>
On Wed, Feb 18, 2026 at 06:55:17PM +0100, tomasz.unger@yahoo.pl wrote:
> From: Tomasz Unger <tomasz.unger@yahoo.pl>
NAK.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH] staging: fbtft: fb_ra8875: replace udelay with usleep_range
From: Andy Shevchenko @ 2026-02-19 7:30 UTC (permalink / raw)
To: tomasz.unger
Cc: andy, gregkh, dri-devel, linux-fbdev, linux-staging, linux-kernel
In-Reply-To: <20260218174737.86994-1-tomasz.unger@yahoo.pl>
On Wed, Feb 18, 2026 at 06:47:37PM +0100, tomasz.unger@yahoo.pl wrote:
> From: Tomasz Unger <tomasz.unger@yahoo.pl>
We do not accept changes without explanations.
Also where did you get this idea to convert udelay() to usleep_range()?
The API (in case it's okay to use) should be fsleep() nowadays.
(Note as well that we refer to the functions as 'func()' in the text.)
And last, but not least: have you checked carefully that this is even
possible change? This is quite a change in the behaviour and needs very
good justification and testing.
TL;DR: if any tool suggested this change to you, go and fix that tool
to stop spreading misleading ARs!
P.S.
NAK to all your three patches. Also check https://lore.kernel.org ML
archives on the similar changes in the past, they were all NAKed
(rejected).
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2] staging: sm750fb: add missing const to g_fbmode array
From: Dan Carpenter @ 2026-02-19 6:55 UTC (permalink / raw)
To: Eyüp Kerem Baş
Cc: Ethan Tidmore, sudipm.mukherjee, teddy.wang, gregkh, linux-fbdev,
linux-staging, linux-kernel
In-Reply-To: <20260216003939.206758-1-baseyupkerem@gmail.com>
On Mon, Feb 16, 2026 at 03:39:39AM +0300, Eyüp Kerem Baş wrote:
> Checkpatch reported a warning that the static const char * array should
> probably be static const char * const. This patch adds the missing const
> keyword to g_fbmode array, moving it to read-only memory.
>
> Signed-off-by: Eyüp Kerem Baş <baseyupkerem@gmail.com>
> ---
This beaks the build.
regards,
dan carpenter
^ permalink raw reply
* Re: [PATCH v10 2/8] gpu: Move DRM buddy allocator one level up (part two)
From: Alexandre Courbot @ 2026-02-19 3:18 UTC (permalink / raw)
To: Joel Fernandes
Cc: linux-kernel, David Airlie, Simona Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Jonathan Corbet, Shuah Khan,
Matthew Auld, Arun Pravin, Christian Koenig, Alex Deucher,
Jani Nikula, Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin,
Huang Rui, Matthew Brost, Thomas Hellström, Helge Deller,
Danilo Krummrich, Miguel Ojeda, Dave Airlie, Gary Guo,
Daniel Almeida, Koen Koning, dri-devel, nouveau, rust-for-linux,
linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260218205507.689429-3-joelagnelf@nvidia.com>
On Thu Feb 19, 2026 at 5:55 AM JST, Joel Fernandes wrote:
> Move the DRM buddy allocator one level up so that it can be used by GPU
> drivers (example, nova-core) that have usecases other than DRM (such as
> VFIO vGPU support). Modify the API, structures and Kconfigs to use
> "gpu_buddy" terminology. Adapt the drivers and tests to use the new API.
>
> The commit cannot be split due to bisectability, however no functional
> change is intended. Verified by running K-UNIT tests and build tested
> various configurations.
Patches 1 and 2 have the exact same commit log, but each one does only
part of it. Let's only keep the part of the log that applies to each
patch.
>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> Reviewed-by: Dave Airlie <airlied@redhat.com>
> [airlied: I've split this into two so git can find copies easier.
> I've also just nuked drm_random library, that stuff needs to be done
> elsewhere and only the buddy tests seem to be using it].
> Signed-off-by: Dave Airlie <airlied@redhat.com>
> ---
> Documentation/gpu/drm-mm.rst | 6 +
> MAINTAINERS | 8 +-
> drivers/gpu/Kconfig | 13 +
> drivers/gpu/Makefile | 1 +
> drivers/gpu/buddy.c | 556 +++++++++---------
> drivers/gpu/drm/Kconfig | 1 +
> drivers/gpu/drm/Makefile | 2 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +-
> .../gpu/drm/amd/amdgpu/amdgpu_res_cursor.h | 12 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 79 +--
> drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 18 +-
> drivers/gpu/drm/drm_buddy.c | 77 +++
> drivers/gpu/drm/i915/i915_scatterlist.c | 8 +-
> drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 55 +-
> drivers/gpu/drm/i915/i915_ttm_buddy_manager.h | 4 +-
> .../drm/i915/selftests/intel_memory_region.c | 20 +-
> .../gpu/drm/ttm/tests/ttm_bo_validate_test.c | 4 +-
> drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 18 +-
> drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 2 +-
> drivers/gpu/drm/xe/xe_res_cursor.h | 34 +-
> drivers/gpu/drm/xe/xe_svm.c | 12 +-
> drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 71 +--
> drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 2 +-
> drivers/gpu/tests/Makefile | 2 +-
> drivers/gpu/tests/gpu_buddy_test.c | 412 ++++++-------
> drivers/gpu/tests/gpu_random.c | 16 +-
> drivers/gpu/tests/gpu_random.h | 18 +-
> drivers/video/Kconfig | 1 +
> include/drm/drm_buddy.h | 18 +
> include/linux/gpu_buddy.h | 120 ++--
> 30 files changed, 853 insertions(+), 739 deletions(-)
> create mode 100644 drivers/gpu/Kconfig
> create mode 100644 drivers/gpu/drm/drm_buddy.c
> create mode 100644 include/drm/drm_buddy.h
>
> diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
> index ceee0e663237..32fb506db05b 100644
> --- a/Documentation/gpu/drm-mm.rst
> +++ b/Documentation/gpu/drm-mm.rst
> @@ -532,6 +532,12 @@ Buddy Allocator Function References (GPU buddy)
> .. kernel-doc:: drivers/gpu/buddy.c
> :export:
>
> +DRM Buddy Specific Logging Function References
> +----------------------------------------------
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_buddy.c
> + :export:
> +
> DRM Cache Handling and Fast WC memcpy()
> =======================================
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dc82a6bd1a61..14b4f9af0e36 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8905,15 +8905,17 @@ T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
> F: drivers/gpu/drm/ttm/
> F: include/drm/ttm/
>
> -DRM BUDDY ALLOCATOR
> +GPU BUDDY ALLOCATOR
> M: Matthew Auld <matthew.auld@intel.com>
> M: Arun Pravin <arunpravin.paneerselvam@amd.com>
> R: Christian Koenig <christian.koenig@amd.com>
> L: dri-devel@lists.freedesktop.org
> S: Maintained
> T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
> -F: drivers/gpu/drm/drm_buddy.c
> -F: drivers/gpu/drm/tests/drm_buddy_test.c
> +F: drivers/gpu/drm_buddy.c
This line should be `drivers/gpu/drm/drm_buddy.c`.
> +F: drivers/gpu/buddy.c
> +F: drivers/gpu/tests/gpu_buddy_test.c
> +F: include/linux/gpu_buddy.h
These files have been moved in patch 1, so their MAINTAINERS entry
should also be modified there.
^ permalink raw reply
* Re: [PATCH -next v9 1/3] rust: clist: Add support to interface with C linked lists
From: Alexandre Courbot @ 2026-02-19 2:47 UTC (permalink / raw)
To: Joel Fernandes
Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Danilo Krummrich, Alice Ryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Alistair Popple, Andrea Righi, Zhi Wang,
Philipp Stanner, Elle Rhumsaa, Daniel Almeida, nouveau, dri-devel,
rust-for-linux, linux-doc, amd-gfx, intel-gfx, intel-xe,
linux-fbdev
In-Reply-To: <1771462209.c70cb872032e4abe@nvidia.com>
On Thu Feb 19, 2026 at 9:59 AM JST, Joel Fernandes wrote:
> On Thu, 19 Feb 2026 09:35:31 +0900, Alexandre Courbot wrote:
>
> [...]
>
>> I asked this a couple of times ([1], [2]) but got no reply, so let me
>> try again. :) Given that `list_head` is doubly-linked, can we also
>> implement `DoubleEndedIterator`?
>>
>> This can be done in a follow-up patch but should be there eventually as
>> C lists are often parsed in both directions.
>>
>> [1] https://lore.kernel.org/all/DEGQCMSX1SGZ.2NQDPG5KUNA9D@nvidia.com/
>> [2] https://lore.kernel.org/all/DEOLRLCZQMBG.1WHBR4YL8SKYR@nvidia.com/
>
> There was a lot of redesign and you only mentioned it as an optional
> suggestion and there several higher priority comments.
>
> Anyway, I disagree. I don't think there's a use case for
> DoubleEndedIterator at the moment -- none of the current users of clist need
> reverse iteration. I'd prefer to keep the interface minimal and add it when
> there's an actual need for it, rather than adding API surface that nobody
> uses. If a usecase comes up, we can always trivially add it.
It's a double-linked list still, and `DoubleEndedIterator` a standard
Rust trait. Adding it now would spare us the trouble of deciding which
tree takes the feature when it eventually lands.
But even without it the series still stands, so your call.
^ permalink raw reply
* Re: [PATCH 13/13] lib/fonts: Remove internal symbols and macros from public header file
From: kernel test robot @ 2026-02-19 2:08 UTC (permalink / raw)
To: Thomas Zimmermann, gregkh, deller, sam
Cc: oe-kbuild-all, linux-fbdev, dri-devel, linux-kernel,
Thomas Zimmermann
In-Reply-To: <20260218083855.10743-14-tzimmermann@suse.de>
Hi Thomas,
kernel test robot noticed the following build errors:
[auto build test ERROR on 0082025812a31eda451fb14f13f52683ed375c49]
url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Declare-src-parameter-of-fb_pad_-helpers-as-constant/20260218-164243
base: 0082025812a31eda451fb14f13f52683ed375c49
patch link: https://lore.kernel.org/r/20260218083855.10743-14-tzimmermann%40suse.de
patch subject: [PATCH 13/13] lib/fonts: Remove internal symbols and macros from public header file
config: powerpc-allmodconfig (https://download.01.org/0day-ci/archive/20260219/202602191044.XKx5ACdn-lkp@intel.com/config)
compiler: powerpc64-linux-gcc (GCC) 15.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260219/202602191044.XKx5ACdn-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602191044.XKx5ACdn-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from arch/powerpc/kernel/btext.c:23:
arch/powerpc/kernel/btext.c: In function 'draw_byte':
>> arch/powerpc/kernel/btext.c:467:46: error: 'font_sun_8x16' undeclared (first use in this function); did you mean 'font_vga_8x16'?
467 | const unsigned char *font = PTRRELOC(font_sun_8x16.data) + font_index;
| ^~~~~~~~~~~~~
arch/powerpc/include/asm/setup.h:19:34: note: in definition of macro 'PTRRELOC'
19 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x)))
| ^
arch/powerpc/kernel/btext.c:467:46: note: each undeclared identifier is reported only once for each function it appears in
467 | const unsigned char *font = PTRRELOC(font_sun_8x16.data) + font_index;
| ^~~~~~~~~~~~~
arch/powerpc/include/asm/setup.h:19:34: note: in definition of macro 'PTRRELOC'
19 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x)))
| ^
vim +467 arch/powerpc/kernel/btext.c
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 462
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 463 static noinline void draw_byte(unsigned char c, long locX, long locY)
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 464 {
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 465 unsigned char *base = calc_base(locX << 3, locY << 4);
0ebc7feae79ac0 Dr. David Alan Gilbert 2023-08-25 466 unsigned int font_index = c * 16;
b94b7356756164 Finn Thain 2025-11-10 @467 const unsigned char *font = PTRRELOC(font_sun_8x16.data) + font_index;
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 468 int rb = dispDeviceRowBytes;
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 469
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 470 rmci_maybe_on();
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 471 switch(dispDeviceDepth) {
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 472 case 24:
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 473 case 32:
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 474 draw_byte_32(font, (unsigned int *)base, rb);
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 475 break;
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 476 case 15:
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 477 case 16:
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 478 draw_byte_16(font, (unsigned int *)base, rb);
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 479 break;
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 480 case 8:
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 481 draw_byte_8(font, (unsigned int *)base, rb);
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 482 break;
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 483 }
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 484 rmci_maybe_off();
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 485 }
7191b615759ec1 Benjamin Herrenschmidt 2013-07-25 486
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH -next v9 1/3] rust: clist: Add support to interface with C linked lists
From: Joel Fernandes @ 2026-02-19 0:59 UTC (permalink / raw)
To: Alexandre Courbot
Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Danilo Krummrich, Alice Ryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Alistair Popple, Andrea Righi, Zhi Wang,
Philipp Stanner, Elle Rhumsaa, Daniel Almeida, nouveau, dri-devel,
rust-for-linux, linux-doc, amd-gfx, intel-gfx, intel-xe,
linux-fbdev
In-Reply-To: <DGIIMT4F1GWA.12UFBEUAC80VW@nvidia.com>
On Thu, 19 Feb 2026 09:35:31 +0900, Alexandre Courbot wrote:
[...]
> I asked this a couple of times ([1], [2]) but got no reply, so let me
> try again. :) Given that `list_head` is doubly-linked, can we also
> implement `DoubleEndedIterator`?
>
> This can be done in a follow-up patch but should be there eventually as
> C lists are often parsed in both directions.
>
> [1] https://lore.kernel.org/all/DEGQCMSX1SGZ.2NQDPG5KUNA9D@nvidia.com/
> [2] https://lore.kernel.org/all/DEOLRLCZQMBG.1WHBR4YL8SKYR@nvidia.com/
There was a lot of redesign and you only mentioned it as an optional
suggestion and there several higher priority comments.
Anyway, I disagree. I don't think there's a use case for
DoubleEndedIterator at the moment -- none of the current users of clist need
reverse iteration. I'd prefer to keep the interface minimal and add it when
there's an actual need for it, rather than adding API surface that nobody
uses. If a usecase comes up, we can always trivially add it.
(will look at other comments in the morning, its night for me).
Thanks,
--
Joel Fernandes
^ permalink raw reply
* Re: [PATCH -next v9 1/3] rust: clist: Add support to interface with C linked lists
From: Alexandre Courbot @ 2026-02-19 0:35 UTC (permalink / raw)
To: Joel Fernandes
Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Simona Vetter,
Jonathan Corbet, Alex Deucher, Christian König, Jani Nikula,
Joonas Lahtinen, Rodrigo Vivi, Tvrtko Ursulin, Huang Rui,
Matthew Auld, Matthew Brost, Lucas De Marchi,
Thomas Hellström, Helge Deller, Danilo Krummrich, Alice Ryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Alistair Popple, Andrea Righi, Zhi Wang,
Philipp Stanner, Elle Rhumsaa, Daniel Almeida, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev
In-Reply-To: <20260210233204.790524-2-joelagnelf@nvidia.com>
I saw that v10 has been sent, but since the code is mostly identical
this review should still apply (I was in the middle of writing it before
going to sleep).
On Wed Feb 11, 2026 at 8:32 AM JST, Joel Fernandes wrote:
> Add a new module `clist` for working with C's doubly circular linked
> lists. Provide low-level iteration over list nodes.
>
> Typed iteration over actual items is provided with a `clist_create`
> macro to assist in creation of the `CList` type.
>
> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
> Acked-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> ---
> MAINTAINERS | 7 +
> rust/helpers/helpers.c | 1 +
> rust/helpers/list.c | 17 +++
> rust/kernel/clist.rs | 320 +++++++++++++++++++++++++++++++++++++++++
> rust/kernel/lib.rs | 1 +
> 5 files changed, 346 insertions(+)
> create mode 100644 rust/helpers/list.c
> create mode 100644 rust/kernel/clist.rs
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 7cfb766112cd..b0050b478dc9 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -23205,6 +23205,13 @@ S: Maintained
> T: git https://github.com/Rust-for-Linux/linux.git rust-analyzer-next
> F: scripts/generate_rust_analyzer.py
>
> +RUST TO C LIST INTERFACES
> +M: Joel Fernandes <joelagnelf@nvidia.com>
> +M: Alexandre Courbot <acourbot@nvidia.com>
> +L: rust-for-linux@vger.kernel.org
> +S: Maintained
> +F: rust/kernel/clist.rs
> +
> RXRPC SOCKETS (AF_RXRPC)
> M: David Howells <dhowells@redhat.com>
> M: Marc Dionne <marc.dionne@auristor.com>
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index a3c42e51f00a..724fcb8240ac 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -35,6 +35,7 @@
> #include "io.c"
> #include "jump_label.c"
> #include "kunit.c"
> +#include "list.c"
> #include "maple_tree.c"
> #include "mm.c"
> #include "mutex.c"
> diff --git a/rust/helpers/list.c b/rust/helpers/list.c
> new file mode 100644
> index 000000000000..4c1f9c111ec8
> --- /dev/null
> +++ b/rust/helpers/list.c
> @@ -0,0 +1,17 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +/*
> + * Helpers for C Circular doubly linked list implementation.
nit: "Circular" doesn't need a capital "C".
> + */
> +
> +#include <linux/list.h>
> +
> +__rust_helper void rust_helper_INIT_LIST_HEAD(struct list_head *list)
> +{
> + INIT_LIST_HEAD(list);
> +}
> +
> +__rust_helper void rust_helper_list_add_tail(struct list_head *new, struct list_head *head)
> +{
> + list_add_tail(new, head);
> +}
> diff --git a/rust/kernel/clist.rs b/rust/kernel/clist.rs
> new file mode 100644
> index 000000000000..8aa72b5d54be
> --- /dev/null
> +++ b/rust/kernel/clist.rs
> @@ -0,0 +1,320 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! A C doubly circular intrusive linked list interface for rust code.
> +//!
> +//! # Examples
> +//!
> +//! ```
> +//! use kernel::{
> +//! bindings,
> +//! clist_create,
> +//! types::Opaque, //
> +//! };
> +//! # // Create test list with values (0, 10, 20) - normally done by C code but it is
> +//! # // emulated here for doctests using the C bindings.
> +//! # use core::mem::MaybeUninit;
> +//! #
> +//! # /// C struct with embedded `list_head` (typically will be allocated by C code).
> +//! # #[repr(C)]
> +//! # pub struct SampleItemC {
> +//! # pub value: i32,
> +//! # pub link: bindings::list_head,
> +//! # }
> +//! #
> +//! # let mut head = MaybeUninit::<bindings::list_head>::uninit();
> +//! #
> +//! # let head = head.as_mut_ptr();
> +//! # // SAFETY: head and all the items are test objects allocated in this scope.
> +//! # unsafe { bindings::INIT_LIST_HEAD(head) };
> +//! #
> +//! # let mut items = [
> +//! # MaybeUninit::<SampleItemC>::uninit(),
> +//! # MaybeUninit::<SampleItemC>::uninit(),
> +//! # MaybeUninit::<SampleItemC>::uninit(),
> +//! # ];
> +//! #
> +//! # for (i, item) in items.iter_mut().enumerate() {
> +//! # let ptr = item.as_mut_ptr();
> +//! # // SAFETY: pointers are to allocated test objects with a list_head field.
> +//! # unsafe {
> +//! # (*ptr).value = i as i32 * 10;
> +//! # // &raw mut computes address of link directly as link is uninitialized.
> +//! # bindings::INIT_LIST_HEAD(&raw mut (*ptr).link);
> +//! # bindings::list_add_tail(&mut (*ptr).link, head);
Is the `INIT_LIST_HEAD` line needed? `list_add_tail` will immediately
overwrite the initial values of `ptr.link`.
> +//! # }
> +//! # }
> +//!
> +//! // Rust wrapper for the C struct.
> +//! // The list item struct in this example is defined in C code as:
> +//! // struct SampleItemC {
> +//! // int value;
> +//! // struct list_head link;
> +//! // };
> +//! //
> +//! #[repr(transparent)]
> +//! pub struct Item(Opaque<SampleItemC>);
> +//!
> +//! impl Item {
> +//! pub fn value(&self) -> i32 {
> +//! // SAFETY: [`Item`] has same layout as [`SampleItemC`].
> +//! unsafe { (*self.0.get()).value }
> +//! }
> +//! }
> +//!
> +//! // Create typed [`CList`] from sentinel head.
> +//! // SAFETY: head is valid, items are [`SampleItemC`] with embedded `link` field.
> +//! let list = unsafe { clist_create!(head, Item, SampleItemC, link) };
`head` appears in the documentation for the first time here - it would
help to make at least its declaration visible, or add a comment
specifying its type.
> +//!
> +//! // Iterate directly over typed items.
> +//! let mut found_0 = false;
> +//! let mut found_10 = false;
> +//! let mut found_20 = false;
> +//!
> +//! for item in list.iter() {
> +//! let val = item.value();
> +//! if val == 0 { found_0 = true; }
> +//! if val == 10 { found_10 = true; }
> +//! if val == 20 { found_20 = true; }
> +//! }
> +//!
> +//! assert!(found_0 && found_10 && found_20);
> +//! ```
> +
> +use core::{
> + iter::FusedIterator,
> + marker::PhantomData, //
> +};
> +
> +use crate::{
> + bindings,
> + types::Opaque, //
> +};
> +
> +use pin_init::{
> + pin_data,
> + pin_init,
> + PinInit //
> +};
> +
> +/// Wraps a `list_head` object for use in intrusive linked lists.
> +///
> +/// # Invariants
> +///
> +/// - [`CListHead`] represents an allocated and valid `list_head` structure.
> +#[pin_data]
> +#[repr(transparent)]
> +pub struct CListHead {
> + #[pin]
> + inner: Opaque<bindings::list_head>,
> +}
> +
> +impl CListHead {
> + /// Create a `&CListHead` reference from a raw `list_head` pointer.
> + ///
> + /// # Safety
> + ///
> + /// - `ptr` must be a valid pointer to an allocated and initialized `list_head` structure.
> + /// - `ptr` must remain valid and unmodified for the lifetime `'a`.
> + /// - The list and all linked `list_head` nodes must not be modified by non-Rust code
> + /// for the lifetime `'a`.
> + #[inline]
> + pub unsafe fn from_raw<'a>(ptr: *mut bindings::list_head) -> &'a Self {
> + // SAFETY:
> + // - [`CListHead`] has same layout as `list_head`.
> + // - `ptr` is valid and unmodified for 'a per caller guarantees.
> + unsafe { &*ptr.cast() }
> + }
> +
> + /// Get the raw `list_head` pointer.
> + #[inline]
> + pub fn as_raw(&self) -> *mut bindings::list_head {
> + self.inner.get()
> + }
> +
> + /// Get the next [`CListHead`] in the list.
> + #[inline]
> + pub fn next(&self) -> &Self {
> + let raw = self.as_raw();
> + // SAFETY:
> + // - `self.as_raw()` is valid per type invariants.
> + // - The `next` pointer is guaranteed to be non-NULL.
Safety nit: the SAFETY comment should mention what guarantees that `next` is
non-NULL. Also the safety section of `from_raw` has 3 items, but this
only justifies 2.
> + unsafe { Self::from_raw((*raw).next) }
> + }
> +
> + /// Check if this node is linked in a list (not isolated).
> + #[inline]
> + pub fn is_linked(&self) -> bool {
> + let raw = self.as_raw();
> + // SAFETY: self.as_raw() is valid per type invariants.
> + unsafe { (*raw).next != raw && (*raw).prev != raw }
> + }
This will return true on a non-empty sentinel head - is that intended?
Since this is only used in `CList::is_empty`, and in the GPU buddy's
`is_empty` method, is this the right name? The code also mirrors C's
`list_empty`...
> +
> + /// Pin-initializer that initializes the list head.
> + pub fn new() -> impl PinInit<Self> {
> + pin_init!(Self {
> + // SAFETY: `INIT_LIST_HEAD` initializes `slot` to a valid empty list.
> + inner <- Opaque::ffi_init(|slot| unsafe { bindings::INIT_LIST_HEAD(slot) }),
> + })
> + }
> +}
> +
> +// SAFETY: [`CListHead`] can be sent to any thread.
> +unsafe impl Send for CListHead {}
That safety comment is circular. I guess you mean to say that
`list_head` can be sent to any thread?
> +
> +// SAFETY: [`CListHead`] can be shared among threads as it is not modified
> +// by non-Rust code per safety requirements of [`CListHead::from_raw`].
> +unsafe impl Sync for CListHead {}
> +
> +impl PartialEq for CListHead {
> + #[inline]
> + fn eq(&self, other: &Self) -> bool {
> + core::ptr::eq(self, other)
> + }
> +}
> +
> +impl Eq for CListHead {}
> +
> +/// Low-level iterator over `list_head` nodes.
> +///
> +/// An iterator used to iterate over a C intrusive linked list (`list_head`). Caller has to
> +/// perform conversion of returned [`CListHead`] to an item (using `container_of` macro or similar).
> +///
> +/// # Invariants
> +///
> +/// [`CListHeadIter`] is iterating over an allocated, initialized and valid list.
> +struct CListHeadIter<'a> {
> + /// Current position in the list.
> + current: &'a CListHead,
> + /// The sentinel head (used to detect end of iteration).
> + sentinel: &'a CListHead,
> +}
> +
> +impl<'a> Iterator for CListHeadIter<'a> {
> + type Item = &'a CListHead;
> +
> + #[inline]
> + fn next(&mut self) -> Option<Self::Item> {
> + // Check if we've reached the sentinel (end of list).
> + if self.current == self.sentinel {
> + return None;
> + }
> +
> + let item = self.current;
> + self.current = item.next();
> + Some(item)
> + }
> +}
> +
> +impl<'a> FusedIterator for CListHeadIter<'a> {}
I asked this a couple of times ([1], [2]) but got no reply, so let me
try again. :) Given that `list_head` is doubly-linked, can we also
implement `DoubleEndedIterator`?
This can be done in a follow-up patch but should be there eventually as
C lists are often parsed in both directions.
[1] https://lore.kernel.org/all/DEGQCMSX1SGZ.2NQDPG5KUNA9D@nvidia.com/
[2] https://lore.kernel.org/all/DEOLRLCZQMBG.1WHBR4YL8SKYR@nvidia.com/
> +
> +/// A typed C linked list with a sentinel head.
> +///
> +/// A sentinel head represents the entire linked list and can be used for
> +/// iteration over items of type `T`, it is not associated with a specific item.
> +///
> +/// The const generic `OFFSET` specifies the byte offset of the `list_head` field within
> +/// the struct that `T` wraps.
> +///
> +/// # Invariants
> +///
> +/// - The [`CListHead`] is an allocated and valid sentinel C `list_head` structure.
> +/// - `OFFSET` is the byte offset of the `list_head` field within the struct that `T` wraps.
> +/// - All the list's `list_head` nodes are allocated and have valid next/prev pointers.
> +#[repr(transparent)]
> +pub struct CList<T, const OFFSET: usize>(CListHead, PhantomData<T>);
> +
> +impl<T, const OFFSET: usize> CList<T, OFFSET> {
> + /// Create a typed [`CList`] reference from a raw sentinel `list_head` pointer.
> + ///
> + /// # Safety
> + ///
> + /// - `ptr` must be a valid pointer to an allocated and initialized `list_head` structure
> + /// representing a list sentinel.
> + /// - `ptr` must remain valid and unmodified for the lifetime `'a`.
> + /// - The list must contain items where the `list_head` field is at byte offset `OFFSET`.
> + /// - `T` must be `#[repr(transparent)]` over the C struct.
> + #[inline]
> + pub unsafe fn from_raw<'a>(ptr: *mut bindings::list_head) -> &'a Self {
> + // SAFETY:
> + // - [`CList`] has same layout as [`CListHead`] due to repr(transparent).
> + // - Caller guarantees `ptr` is a valid, sentinel `list_head` object.
> + unsafe { &*ptr.cast() }
> + }
IIUC you can call `CListHead::from_raw` here instead of repeating its
code.
> +
> + /// Check if the list is empty.
> + #[inline]
> + pub fn is_empty(&self) -> bool {
> + !self.0.is_linked()
> + }
> +
> + /// Create an iterator over typed items.
> + #[inline]
> + pub fn iter(&self) -> CListIter<'_, T, OFFSET> {
> + let head = &self.0;
> + CListIter {
> + head_iter: CListHeadIter {
> + current: head.next(),
> + sentinel: head,
> + },
> + _phantom: PhantomData,
> + }
> + }
> +}
> +
> +/// High-level iterator over typed list items.
> +pub struct CListIter<'a, T, const OFFSET: usize> {
> + head_iter: CListHeadIter<'a>,
> + _phantom: PhantomData<&'a T>,
> +}
> +
> +impl<'a, T, const OFFSET: usize> Iterator for CListIter<'a, T, OFFSET> {
> + type Item = &'a T;
> +
> + fn next(&mut self) -> Option<Self::Item> {
This method is the only one not marked `#[inline]`.
> + let head = self.head_iter.next()?;
> +
> + // Convert to item using OFFSET.
> + // SAFETY: `item_ptr` calculation from `OFFSET` (calculated using offset_of!)
> + // is valid per invariants.
> + Some(unsafe { &*head.as_raw().byte_sub(OFFSET).cast::<T>() })
> + }
> +}
> +
> +impl<'a, T, const OFFSET: usize> FusedIterator for CListIter<'a, T, OFFSET> {}
> +
> +/// Create a C doubly-circular linked list interface `CList` from a raw `list_head` pointer.
> +///
> +/// This macro creates a `CList<T, OFFSET>` that can iterate over items of type `$rust_type`
> +/// linked via the `$field` field in the underlying C struct `$c_type`.
> +///
> +/// # Arguments
> +///
> +/// - `$head`: Raw pointer to the sentinel `list_head` object (`*mut bindings::list_head`).
> +/// - `$rust_type`: Each item's rust wrapper type.
> +/// - `$c_type`: Each item's C struct type that contains the embedded `list_head`.
> +/// - `$field`: The name of the `list_head` field within the C struct.
> +///
> +/// # Safety
> +///
> +/// This is an unsafe macro. The caller must ensure:
> +///
> +/// - `$head` is a valid, initialized sentinel `list_head` pointing to a list that remains
> +/// unmodified for the lifetime of the rust `CList`.
> +/// - The list contains items of type `$c_type` linked via an embedded `$field`.
> +/// - `$rust_type` is `#[repr(transparent)]` over `$c_type` or has compatible layout.
> +///
> +/// # Examples
> +///
> +/// Refer to the examples in this module's documentation.
> +#[macro_export]
> +macro_rules! clist_create {
> + ($head:expr, $rust_type:ty, $c_type:ty, $($field:tt).+) => {{
> + // Compile-time check that field path is a list_head.
> + let _: fn(*const $c_type) -> *const $crate::bindings::list_head =
> + |p| &raw const (*p).$($field).+;
> +
> + // Calculate offset and create `CList`.
> + const OFFSET: usize = ::core::mem::offset_of!($c_type, $($field).+);
> + $crate::clist::CList::<$rust_type, OFFSET>::from_raw($head)
> + }};
> +}
I find it difficult to remember which argument fits where in the macro's
syntax (I have the same problem every time I need to use
`list_for_each_entry_safe` for instance).
Since Rust macros let us be more creative, how about something like
this:
let list = unsafe { clist_create!(head => Item, SampleItemC.link) };
It makes it more obvious that we use `head` to iterate through a list of
`Item`s, using the `link` member of `SampleItemC`. There are probably
better syntaxes; the above is just an example.
^ permalink raw reply
* Re: [PATCH 13/13] lib/fonts: Remove internal symbols and macros from public header file
From: kernel test robot @ 2026-02-18 21:47 UTC (permalink / raw)
To: Thomas Zimmermann, gregkh, deller, sam
Cc: llvm, oe-kbuild-all, linux-fbdev, dri-devel, linux-kernel,
Thomas Zimmermann
In-Reply-To: <20260218083855.10743-14-tzimmermann@suse.de>
Hi Thomas,
kernel test robot noticed the following build errors:
[auto build test ERROR on 0082025812a31eda451fb14f13f52683ed375c49]
url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/fbdev-Declare-src-parameter-of-fb_pad_-helpers-as-constant/20260218-164243
base: 0082025812a31eda451fb14f13f52683ed375c49
patch link: https://lore.kernel.org/r/20260218083855.10743-14-tzimmermann%40suse.de
patch subject: [PATCH 13/13] lib/fonts: Remove internal symbols and macros from public header file
config: sparc64-allmodconfig (https://download.01.org/0day-ci/archive/20260219/202602190548.KwDrx2RS-lkp@intel.com/config)
compiler: clang version 23.0.0git (https://github.com/llvm/llvm-project e86750b29fa0ff207cd43213d66dabe565417638)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260219/202602190548.KwDrx2RS-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202602190548.KwDrx2RS-lkp@intel.com/
All errors (new ones prefixed by >>):
>> arch/sparc/kernel/btext.c:195:30: error: use of undeclared identifier 'font_sun_8x16'; did you mean 'font_vga_8x16'?
195 | const unsigned char *font = font_sun_8x16.data + font_index;
| ^~~~~~~~~~~~~
| font_vga_8x16
include/linux/font.h:99:31: note: 'font_vga_8x16' declared here
99 | extern const struct font_desc font_vga_8x16;
| ^
1 error generated.
vim +195 arch/sparc/kernel/btext.c
c57ec52f2647e5 David S. Miller 2009-11-27 190
c57ec52f2647e5 David S. Miller 2009-11-27 191 static void draw_byte(unsigned char c, long locX, long locY)
c57ec52f2647e5 David S. Miller 2009-11-27 192 {
c57ec52f2647e5 David S. Miller 2009-11-27 193 unsigned char *base = calc_base(locX << 3, locY << 4);
0f1991949d9bd5 Dr. David Alan Gilbert 2023-08-07 194 unsigned int font_index = c * 16;
0f1991949d9bd5 Dr. David Alan Gilbert 2023-08-07 @195 const unsigned char *font = font_sun_8x16.data + font_index;
c57ec52f2647e5 David S. Miller 2009-11-27 196 int rb = dispDeviceRowBytes;
c57ec52f2647e5 David S. Miller 2009-11-27 197
c57ec52f2647e5 David S. Miller 2009-11-27 198 switch(dispDeviceDepth) {
c57ec52f2647e5 David S. Miller 2009-11-27 199 case 24:
c57ec52f2647e5 David S. Miller 2009-11-27 200 case 32:
c57ec52f2647e5 David S. Miller 2009-11-27 201 draw_byte_32(font, (unsigned int *)base, rb);
c57ec52f2647e5 David S. Miller 2009-11-27 202 break;
c57ec52f2647e5 David S. Miller 2009-11-27 203 case 15:
c57ec52f2647e5 David S. Miller 2009-11-27 204 case 16:
c57ec52f2647e5 David S. Miller 2009-11-27 205 draw_byte_16(font, (unsigned int *)base, rb);
c57ec52f2647e5 David S. Miller 2009-11-27 206 break;
c57ec52f2647e5 David S. Miller 2009-11-27 207 case 8:
c57ec52f2647e5 David S. Miller 2009-11-27 208 draw_byte_8(font, (unsigned int *)base, rb);
c57ec52f2647e5 David S. Miller 2009-11-27 209 break;
c57ec52f2647e5 David S. Miller 2009-11-27 210 }
c57ec52f2647e5 David S. Miller 2009-11-27 211 }
c57ec52f2647e5 David S. Miller 2009-11-27 212
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* [PATCH v7 23/23] nova-core: mm: Add BarUser to struct Gpu and create at boot
From: Joel Fernandes @ 2026-02-18 21:20 UTC (permalink / raw)
To: linux-kernel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Alex Deucher,
Christian König, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Huang Rui, Matthew Auld, Matthew Brost,
Lucas De Marchi, Thomas Hellström, Helge Deller,
Danilo Krummrich, Alice Ryhl, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, John Hubbard, Alistair Popple,
Timur Tabi, Edwin Peer, Alexandre Courbot, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, Philipp Stanner,
Elle Rhumsaa, Daniel Almeida, Eliot Courtney, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev, Joel Fernandes, Nikola Djukic
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
Add a BarUser field to struct Gpu and eagerly create it during GPU
initialization. The BarUser provides the BAR1 user interface for CPU
access to GPU virtual memory through the GPU's MMU.
The BarUser is initialized using BAR1 PDE base address from GSP static
info, MMU version and BAR1 size obtained from platform device.
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index 670a2a89c6ec..159ccea8464a 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -26,7 +26,12 @@
commands::GetGspStaticInfoReply,
Gsp, //
},
- mm::GpuMm,
+ mm::{
+ bar_user::BarUser,
+ pagetable::MmuVersion,
+ GpuMm,
+ VramAddress, //
+ },
regs,
};
@@ -35,6 +40,7 @@
struct BootParams {
usable_vram_start: u64,
usable_vram_size: u64,
+ bar1_pde_base: u64,
}
macro_rules! define_chipset {
@@ -272,6 +278,8 @@ pub(crate) struct Gpu {
gsp: Gsp,
/// Static GPU information from GSP.
gsp_static_info: GetGspStaticInfoReply,
+ /// BAR1 user interface for CPU access to GPU virtual memory.
+ bar_user: BarUser,
}
impl Gpu {
@@ -285,6 +293,7 @@ pub(crate) fn new<'a>(
let boot_params: Cell<BootParams> = Cell::new(BootParams {
usable_vram_start: 0,
usable_vram_size: 0,
+ bar1_pde_base: 0,
});
try_pin_init!(Self {
@@ -329,6 +338,7 @@ pub(crate) fn new<'a>(
boot_params.set(BootParams {
usable_vram_start: usable_vram.start,
usable_vram_size: usable_vram.end - usable_vram.start,
+ bar1_pde_base: info.bar1_pde_base(),
});
info
@@ -345,6 +355,16 @@ pub(crate) fn new<'a>(
})?
},
+ // Create BAR1 user interface for CPU access to GPU virtual memory.
+ // Uses the BAR1 PDE base from GSP and full BAR1 size for VA space.
+ bar_user: {
+ let params = boot_params.get();
+ let pdb_addr = VramAddress::new(params.bar1_pde_base);
+ let mmu_version = MmuVersion::from(spec.chipset.arch());
+ let bar1_size = pdev.resource_len(1)?;
+ BarUser::new(pdb_addr, mmu_version, bar1_size)?
+ },
+
bar: devres_bar,
})
}
--
2.34.1
^ permalink raw reply related
* [PATCH v7 22/23] nova-core: mm: Use usable VRAM region for buddy allocator
From: Joel Fernandes @ 2026-02-18 21:20 UTC (permalink / raw)
To: linux-kernel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Alex Deucher,
Christian König, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Huang Rui, Matthew Auld, Matthew Brost,
Lucas De Marchi, Thomas Hellström, Helge Deller,
Danilo Krummrich, Alice Ryhl, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, John Hubbard, Alistair Popple,
Timur Tabi, Edwin Peer, Alexandre Courbot, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, Philipp Stanner,
Elle Rhumsaa, Daniel Almeida, Eliot Courtney, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev, Joel Fernandes, Nikola Djukic
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
The buddy allocator manages the actual usable VRAM. On my GA102 Ampere
with 24GB video memory, that is ~23.7GB on a 24GB GPU enabling proper
GPU memory allocation for driver use.
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
drivers/gpu/nova-core/gpu.rs | 62 ++++++++++++++++++++++-----
drivers/gpu/nova-core/gsp/boot.rs | 7 ++-
drivers/gpu/nova-core/gsp/commands.rs | 2 -
3 files changed, 57 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index af5a0ffe78aa..670a2a89c6ec 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
+use core::cell::Cell;
+
use kernel::{
device,
devres::Devres,
@@ -7,7 +9,7 @@
gpu::buddy::GpuBuddyParams,
pci,
prelude::*,
- sizes::{SZ_1M, SZ_4K},
+ sizes::SZ_4K,
sync::Arc, //
};
@@ -28,6 +30,13 @@
regs,
};
+/// Parameters extracted from GSP boot for initializing memory subsystems.
+#[derive(Clone, Copy)]
+struct BootParams {
+ usable_vram_start: u64,
+ usable_vram_size: u64,
+}
+
macro_rules! define_chipset {
({ $($variant:ident = $value:expr),* $(,)* }) =>
{
@@ -271,6 +280,13 @@ pub(crate) fn new<'a>(
devres_bar: Arc<Devres<Bar0>>,
bar: &'a Bar0,
) -> impl PinInit<Self, Error> + 'a {
+ // Cell to share boot parameters between GSP boot and subsequent initializations.
+ // Contains usable VRAM region from FbLayout and BAR1 PDE base from GSP info.
+ let boot_params: Cell<BootParams> = Cell::new(BootParams {
+ usable_vram_start: 0,
+ usable_vram_size: 0,
+ });
+
try_pin_init!(Self {
spec: Spec::new(pdev.as_ref(), bar).inspect(|spec| {
dev_info!(pdev.as_ref(),"NVIDIA ({})\n", spec);
@@ -292,18 +308,42 @@ pub(crate) fn new<'a>(
sec2_falcon: Falcon::new(pdev.as_ref(), spec.chipset)?,
- // Create GPU memory manager owning memory management resources.
- // This will be initialized with the usable VRAM region from GSP in a later
- // patch. For now, we use a placeholder of 1MB.
- mm <- GpuMm::new(devres_bar.clone(), &GpuBuddyParams {
- base_offset_bytes: 0,
- physical_memory_size_bytes: SZ_1M as u64,
- chunk_size_bytes: SZ_4K as u64,
- })?,
-
gsp <- Gsp::new(pdev),
- gsp_static_info: { gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon)?.0 },
+ // Boot GSP and extract usable VRAM region for buddy allocator.
+ gsp_static_info: {
+ let (info, fb_layout) = gsp.boot(pdev, bar, spec.chipset, gsp_falcon, sec2_falcon)?;
+
+ let usable_vram = fb_layout.usable_vram.as_ref().ok_or_else(|| {
+ dev_err!(pdev.as_ref(), "No usable FB regions found from GSP\n");
+ ENODEV
+ })?;
+
+ dev_info!(
+ pdev.as_ref(),
+ "Using FB region: {:#x}..{:#x}\n",
+ usable_vram.start,
+ usable_vram.end
+ );
+
+ boot_params.set(BootParams {
+ usable_vram_start: usable_vram.start,
+ usable_vram_size: usable_vram.end - usable_vram.start,
+ });
+
+ info
+ },
+
+ // Create GPU memory manager owning memory management resources.
+ // Uses the usable VRAM region from GSP for buddy allocator.
+ mm <- {
+ let params = boot_params.get();
+ GpuMm::new(devres_bar.clone(), GpuBuddyParams {
+ base_offset_bytes: params.usable_vram_start,
+ physical_memory_size_bytes: params.usable_vram_size,
+ chunk_size_bytes: SZ_4K as u64,
+ })?
+ },
bar: devres_bar,
})
diff --git a/drivers/gpu/nova-core/gsp/boot.rs b/drivers/gpu/nova-core/gsp/boot.rs
index 7a4a0c759267..bc4446282613 100644
--- a/drivers/gpu/nova-core/gsp/boot.rs
+++ b/drivers/gpu/nova-core/gsp/boot.rs
@@ -150,7 +150,7 @@ pub(crate) fn boot(
let gsp_fw = KBox::pin_init(GspFirmware::new(dev, chipset, FIRMWARE_VERSION), GFP_KERNEL)?;
- let fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
+ let mut fb_layout = FbLayout::new(chipset, bar, &gsp_fw)?;
dev_dbg!(dev, "{:#x?}\n", fb_layout);
Self::run_fwsec_frts(dev, gsp_falcon, bar, &bios, &fb_layout)?;
@@ -252,6 +252,11 @@ pub(crate) fn boot(
Err(e) => dev_warn!(pdev.as_ref(), "GPU name unavailable: {:?}\n", e),
}
+ // Populate usable VRAM from GSP response.
+ if let Some((base, size)) = info.usable_fb_region() {
+ fb_layout.set_usable_vram(base, size);
+ }
+
Ok((info, fb_layout))
}
}
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index 44f8b08683f9..8b3fa29c57f1 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -191,7 +191,6 @@ pub(crate) struct GetGspStaticInfoReply {
gpu_name: [u8; 64],
bar1_pde_base: u64,
/// First usable FB region `(base, size)` for memory allocation.
- #[expect(dead_code)]
usable_fb_region: Option<(u64, u64)>,
}
@@ -242,7 +241,6 @@ pub(crate) fn bar1_pde_base(&self) -> u64 {
/// Returns the usable FB region `(base, size)` for driver allocation which is
/// already retrieved from the GSP.
- #[expect(dead_code)]
pub(crate) fn usable_fb_region(&self) -> Option<(u64, u64)> {
self.usable_fb_region
}
--
2.34.1
^ permalink raw reply related
* [PATCH v7 21/23] nova-core: fb: Add usable_vram field to FbLayout
From: Joel Fernandes @ 2026-02-18 21:20 UTC (permalink / raw)
To: linux-kernel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Alex Deucher,
Christian König, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Huang Rui, Matthew Auld, Matthew Brost,
Lucas De Marchi, Thomas Hellström, Helge Deller,
Danilo Krummrich, Alice Ryhl, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, John Hubbard, Alistair Popple,
Timur Tabi, Edwin Peer, Alexandre Courbot, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, Philipp Stanner,
Elle Rhumsaa, Daniel Almeida, Eliot Courtney, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev, Joel Fernandes, Nikola Djukic
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
Add usable_vram field to FbLayout to store the usable VRAM region for
driver allocations. This is populated after GSP boot with the region
extracted from GSP's fbRegionInfoParams.
FbLayout is now a two-phase structure:
1. new() computes firmware layout from hardware
2. set_usable_vram() populates usable region from GSP
The new usable_vram field represents the actual usable VRAM region
(~23.7GB on a 24GB GPU GA102 Ampere GPU).
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
drivers/gpu/nova-core/fb.rs | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/nova-core/fb.rs b/drivers/gpu/nova-core/fb.rs
index c62abcaed547..779447952b19 100644
--- a/drivers/gpu/nova-core/fb.rs
+++ b/drivers/gpu/nova-core/fb.rs
@@ -97,6 +97,10 @@ pub(crate) fn unregister(&self, bar: &Bar0) {
/// Layout of the GPU framebuffer memory.
///
/// Contains ranges of GPU memory reserved for a given purpose during the GSP boot process.
+///
+/// This structure is populated in 2 steps:
+/// 1. [`FbLayout::new()`] computes firmware layout from hardware.
+/// 2. [`FbLayout::set_usable_vram()`] populates usable region from GSP response.
#[derive(Debug)]
pub(crate) struct FbLayout {
/// Range of the framebuffer. Starts at `0`.
@@ -111,10 +115,14 @@ pub(crate) struct FbLayout {
pub(crate) elf: Range<u64>,
/// WPR2 heap.
pub(crate) wpr2_heap: Range<u64>,
- /// WPR2 region range, starting with an instance of `GspFwWprMeta`.
+ /// WPR2 region range, starting with an instance of [`GspFwWprMeta`].
pub(crate) wpr2: Range<u64>,
+ /// Non-WPR heap carved before WPR2, used by GSP firmware.
pub(crate) heap: Range<u64>,
pub(crate) vf_partition_count: u8,
+ /// Usable VRAM region for driver allocations (from GSP `fbRegionInfoParams`).
+ /// Initially [`None`], populated after GSP boot with usable region info.
+ pub(crate) usable_vram: Option<Range<u64>>,
}
impl FbLayout {
@@ -212,6 +220,19 @@ pub(crate) fn new(chipset: Chipset, bar: &Bar0, gsp_fw: &GspFirmware) -> Result<
wpr2,
heap,
vf_partition_count: 0,
+ usable_vram: None,
})
}
+
+ /// Set the usable VRAM region from GSP response.
+ ///
+ /// Called after GSP boot with the first usable region extracted from
+ /// GSP's `fbRegionInfoParams`. Usable regions are those that:
+ /// - Are not reserved for firmware internal use.
+ /// - Are not protected (hardware-enforced access restrictions).
+ /// - Support compression (can use GPU memory compression for bandwidth).
+ /// - Support ISO (isochronous memory for display requiring guaranteed bandwidth).
+ pub(crate) fn set_usable_vram(&mut self, base: u64, size: u64) {
+ self.usable_vram = Some(base..base.saturating_add(size));
+ }
}
--
2.34.1
^ permalink raw reply related
* [PATCH v7 20/23] nova-core: gsp: Extract usable FB region from GSP
From: Joel Fernandes @ 2026-02-18 21:20 UTC (permalink / raw)
To: linux-kernel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Alex Deucher,
Christian König, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Huang Rui, Matthew Auld, Matthew Brost,
Lucas De Marchi, Thomas Hellström, Helge Deller,
Danilo Krummrich, Alice Ryhl, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, John Hubbard, Alistair Popple,
Timur Tabi, Edwin Peer, Alexandre Courbot, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, Philipp Stanner,
Elle Rhumsaa, Daniel Almeida, Eliot Courtney, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev, Joel Fernandes, Nikola Djukic
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
Add first_usable_fb_region() to GspStaticConfigInfo to extract the first
usable FB region from GSP's fbRegionInfoParams. Usable regions are those
that are not reserved or protected.
The extracted region is stored in GetGspStaticInfoReply and exposed via
usable_fb_region() API for use by the memory subsystem.
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
drivers/gpu/nova-core/gsp/commands.rs | 13 +++++++++-
drivers/gpu/nova-core/gsp/fw/commands.rs | 30 ++++++++++++++++++++++++
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index bf9e3086565f..44f8b08683f9 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -186,10 +186,13 @@ fn init(&self) -> impl Init<Self::Command, Self::InitError> {
}
}
-/// The reply from the GSP to the [`GetGspInfo`] command.
+/// The reply from the GSP to the [`GetGspStaticInfo`] command.
pub(crate) struct GetGspStaticInfoReply {
gpu_name: [u8; 64],
bar1_pde_base: u64,
+ /// First usable FB region `(base, size)` for memory allocation.
+ #[expect(dead_code)]
+ usable_fb_region: Option<(u64, u64)>,
}
impl MessageFromGsp for GetGspStaticInfoReply {
@@ -204,6 +207,7 @@ fn read(
Ok(GetGspStaticInfoReply {
gpu_name: msg.gpu_name_str(),
bar1_pde_base: msg.bar1_pde_base(),
+ usable_fb_region: msg.first_usable_fb_region(),
})
}
}
@@ -235,6 +239,13 @@ pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> {
pub(crate) fn bar1_pde_base(&self) -> u64 {
self.bar1_pde_base
}
+
+ /// Returns the usable FB region `(base, size)` for driver allocation which is
+ /// already retrieved from the GSP.
+ #[expect(dead_code)]
+ pub(crate) fn usable_fb_region(&self) -> Option<(u64, u64)> {
+ self.usable_fb_region
+ }
}
/// Send the [`GetGspInfo`] command and awaits for its reply.
diff --git a/drivers/gpu/nova-core/gsp/fw/commands.rs b/drivers/gpu/nova-core/gsp/fw/commands.rs
index f069f4092911..976eca5a59c4 100644
--- a/drivers/gpu/nova-core/gsp/fw/commands.rs
+++ b/drivers/gpu/nova-core/gsp/fw/commands.rs
@@ -122,6 +122,36 @@ impl GspStaticConfigInfo {
pub(crate) fn bar1_pde_base(&self) -> u64 {
self.0.bar1PdeBase
}
+
+ /// Extract the first usable FB region from GSP firmware data.
+ ///
+ /// Returns the first region suitable for driver memory allocation as a `(base, size)` tuple.
+ /// Usable regions are those that:
+ /// - Are not reserved for firmware internal use.
+ /// - Are not protected (hardware-enforced access restrictions).
+ /// - Support compression (can use GPU memory compression for bandwidth).
+ /// - Support ISO (isochronous memory for display requiring guaranteed bandwidth).
+ pub(crate) fn first_usable_fb_region(&self) -> Option<(u64, u64)> {
+ let fb_info = &self.0.fbRegionInfoParams;
+ for i in 0..fb_info.numFBRegions as usize {
+ if let Some(reg) = fb_info.fbRegion.get(i) {
+ // Skip malformed regions where limit < base.
+ if reg.limit < reg.base {
+ continue;
+ }
+ // Filter: not reserved, not protected, supports compression and ISO.
+ if reg.reserved == 0
+ && reg.bProtected == 0
+ && reg.supportCompressed != 0
+ && reg.supportISO != 0
+ {
+ let size = reg.limit - reg.base + 1;
+ return Some((reg.base, size));
+ }
+ }
+ }
+ None
+ }
}
// SAFETY: Padding is explicit and will not contain uninitialized data.
--
2.34.1
^ permalink raw reply related
* [PATCH v7 19/23] nova-core: mm: Add PRAMIN aperture self-tests
From: Joel Fernandes @ 2026-02-18 21:20 UTC (permalink / raw)
To: linux-kernel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Alex Deucher,
Christian König, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Huang Rui, Matthew Auld, Matthew Brost,
Lucas De Marchi, Thomas Hellström, Helge Deller,
Danilo Krummrich, Alice Ryhl, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, John Hubbard, Alistair Popple,
Timur Tabi, Edwin Peer, Alexandre Courbot, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, Philipp Stanner,
Elle Rhumsaa, Daniel Almeida, Eliot Courtney, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev, Joel Fernandes, Nikola Djukic
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
Add self-tests for the PRAMIN aperture mechanism to verify correct
operation during GPU probe. The tests validate various alignment
requirements and corner cases.
The tests are default disabled and behind CONFIG_NOVA_PRAMIN_SELFTESTS.
When enabled, tests run after GSP boot during probe.
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
drivers/gpu/nova-core/Kconfig | 4 +-
drivers/gpu/nova-core/gpu.rs | 3 +
drivers/gpu/nova-core/mm/pramin.rs | 161 +++++++++++++++++++++++++++++
3 files changed, 166 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index d0d4177adb1b..35de55aabcfc 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -21,7 +21,7 @@ config NOVA_MM_SELFTESTS
depends on NOVA_CORE
help
Enable self-tests for the memory management subsystem. When enabled,
- tests are run during GPU probe to verify page table walking, and BAR1
- virtual memory mapping functionality.
+ tests are run during GPU probe to verify PRAMIN aperture access,
+ page table walking, and BAR1 virtual memory mapping functionality.
This is a testing option and is default-disabled.
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index f17bf1bf0b12..af5a0ffe78aa 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -338,6 +338,9 @@ fn run_mm_selftests(
let mmu_version = MmuVersion::from(self.spec.chipset.arch());
+ // PRAMIN aperture self-tests.
+ crate::mm::pramin::run_self_test(pdev.as_ref(), self.bar.clone(), mmu_version)?;
+
// BAR1 self-tests.
let bar1 = Arc::pin_init(
pdev.iomap_region_sized::<BAR1_SIZE>(1, c"nova-core/bar1"),
diff --git a/drivers/gpu/nova-core/mm/pramin.rs b/drivers/gpu/nova-core/mm/pramin.rs
index 77916f5b231e..da98208b9cb7 100644
--- a/drivers/gpu/nova-core/mm/pramin.rs
+++ b/drivers/gpu/nova-core/mm/pramin.rs
@@ -291,3 +291,164 @@ fn drop(&mut self) {
// MutexGuard drops automatically, releasing the lock.
}
}
+
+/// Run PRAMIN self-tests during boot if self-tests are enabled.
+#[cfg(CONFIG_NOVA_MM_SELFTESTS)]
+pub(crate) fn run_self_test(
+ dev: &kernel::device::Device,
+ bar: Arc<Devres<Bar0>>,
+ mmu_version: super::pagetable::MmuVersion,
+) -> Result {
+ use super::pagetable::MmuVersion;
+
+ // PRAMIN support is only for MMU v2 for now (Turing/Ampere/Ada).
+ if mmu_version != MmuVersion::V2 {
+ dev_info!(
+ dev,
+ "PRAMIN: Skipping self-tests for MMU {:?} (only V2 supported)\n",
+ mmu_version
+ );
+ return Ok(());
+ }
+
+ dev_info!(dev, "PRAMIN: Starting self-test...\n");
+
+ let pramin = Arc::pin_init(Pramin::new(bar)?, GFP_KERNEL)?;
+ let mut win = pramin.window()?;
+
+ // Use offset 0x1000 as test area.
+ let base: usize = 0x1000;
+
+ // Test 1: Read/write at byte-aligned locations.
+ for i in 0u8..4 {
+ let offset = base + 1 + usize::from(i); // Offsets 0x1001, 0x1002, 0x1003, 0x1004
+ let val = 0xA0 + i;
+ win.try_write8(offset, val)?;
+ let read_val = win.try_read8(offset)?;
+ if read_val != val {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: wrote {:#x}, read {:#x}\n",
+ offset,
+ val,
+ read_val
+ );
+ return Err(EIO);
+ }
+ }
+
+ // Test 2: Write `u32` and read back as `u8`s.
+ let test2_offset = base + 0x10;
+ let test2_val: u32 = 0xDEADBEEF;
+ win.try_write32(test2_offset, test2_val)?;
+
+ // Read back as individual bytes (little-endian: EF BE AD DE).
+ let expected_bytes: [u8; 4] = [0xEF, 0xBE, 0xAD, 0xDE];
+ for (i, &expected) in expected_bytes.iter().enumerate() {
+ let read_val = win.try_read8(test2_offset + i)?;
+ if read_val != expected {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: expected {:#x}, read {:#x}\n",
+ test2_offset + i,
+ expected,
+ read_val
+ );
+ return Err(EIO);
+ }
+ }
+
+ // Test 3: Window repositioning across 1MB boundaries.
+ // Write to offset > 1MB to trigger window slide, then verify.
+ let test3_offset_a: usize = base; // First 1MB region.
+ let test3_offset_b: usize = 0x200000 + base; // 2MB + base (different 1MB region).
+ let val_a: u32 = 0x11111111;
+ let val_b: u32 = 0x22222222;
+
+ // Write to first region.
+ win.try_write32(test3_offset_a, val_a)?;
+
+ // Write to second region (triggers window reposition).
+ win.try_write32(test3_offset_b, val_b)?;
+
+ // Read back from second region.
+ let read_b = win.try_read32(test3_offset_b)?;
+ if read_b != val_b {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: expected {:#x}, read {:#x}\n",
+ test3_offset_b,
+ val_b,
+ read_b
+ );
+ return Err(EIO);
+ }
+
+ // Read back from first region (triggers window reposition again).
+ let read_a = win.try_read32(test3_offset_a)?;
+ if read_a != val_a {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - offset {:#x}: expected {:#x}, read {:#x}\n",
+ test3_offset_a,
+ val_a,
+ read_a
+ );
+ return Err(EIO);
+ }
+
+ // Test 4: Invalid offset rejection (beyond 40-bit address space).
+ {
+ // 40-bit address space limit check.
+ let invalid_offset: usize = MAX_VRAM_OFFSET + 1;
+ let result = win.try_read32(invalid_offset);
+ if result.is_ok() {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - read at invalid offset {:#x} should have failed\n",
+ invalid_offset
+ );
+ return Err(EIO);
+ }
+ }
+
+ // Test 5: Misaligned multi-byte access rejection.
+ // Verify that misaligned `u16`/`u32`/`u64` accesses are properly rejected.
+ {
+ // `u16` at odd offset (not 2-byte aligned).
+ let offset_u16 = base + 0x21;
+ if win.try_write16(offset_u16, 0xABCD).is_ok() {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - misaligned u16 write at {:#x} should have failed\n",
+ offset_u16
+ );
+ return Err(EIO);
+ }
+
+ // `u32` at 2-byte-aligned (not 4-byte-aligned) offset.
+ let offset_u32 = base + 0x32;
+ if win.try_write32(offset_u32, 0x12345678).is_ok() {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - misaligned u32 write at {:#x} should have failed\n",
+ offset_u32
+ );
+ return Err(EIO);
+ }
+
+ // `u64` read at 4-byte-aligned (not 8-byte-aligned) offset.
+ let offset_u64 = base + 0x44;
+ if win.try_read64(offset_u64).is_ok() {
+ dev_err!(
+ dev,
+ "PRAMIN: FAIL - misaligned u64 read at {:#x} should have failed\n",
+ offset_u64
+ );
+ return Err(EIO);
+ }
+ }
+
+ dev_info!(dev, "PRAMIN: All self-tests PASSED\n");
+ Ok(())
+}
--
2.34.1
^ permalink raw reply related
* [PATCH v7 18/23] nova-core: mm: Add BAR1 memory management self-tests
From: Joel Fernandes @ 2026-02-18 21:20 UTC (permalink / raw)
To: linux-kernel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jonathan Corbet, Alex Deucher,
Christian König, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Huang Rui, Matthew Auld, Matthew Brost,
Lucas De Marchi, Thomas Hellström, Helge Deller,
Danilo Krummrich, Alice Ryhl, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, John Hubbard, Alistair Popple,
Timur Tabi, Edwin Peer, Alexandre Courbot, Andrea Righi,
Andy Ritger, Zhi Wang, Balbir Singh, Philipp Stanner,
Elle Rhumsaa, Daniel Almeida, Eliot Courtney, joel, nouveau,
dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
intel-xe, linux-fbdev, Joel Fernandes, Nikola Djukic
In-Reply-To: <20260218212020.800836-1-joelagnelf@nvidia.com>
Add self-tests for BAR1 access during driver probe when
CONFIG_NOVA_MM_SELFTESTS is enabled (default disabled). This results in
testing the Vmm, GPU buddy allocator and BAR1 region all of which should
function correctly for the tests to pass.
Cc: Nikola Djukic <ndjukic@nvidia.com>
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
drivers/gpu/nova-core/Kconfig | 10 ++
drivers/gpu/nova-core/driver.rs | 2 +
drivers/gpu/nova-core/gpu.rs | 48 ++++++++
drivers/gpu/nova-core/gsp/commands.rs | 1 -
drivers/gpu/nova-core/mm/bar_user.rs | 164 ++++++++++++++++++++++++++
5 files changed, 224 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index 6513007bf66f..d0d4177adb1b 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -15,3 +15,13 @@ config NOVA_CORE
This driver is work in progress and may not be functional.
If M is selected, the module will be called nova_core.
+
+config NOVA_MM_SELFTESTS
+ bool "Memory management self-tests"
+ depends on NOVA_CORE
+ help
+ Enable self-tests for the memory management subsystem. When enabled,
+ tests are run during GPU probe to verify page table walking, and BAR1
+ virtual memory mapping functionality.
+
+ This is a testing option and is default-disabled.
diff --git a/drivers/gpu/nova-core/driver.rs b/drivers/gpu/nova-core/driver.rs
index d8b2e967ba4c..7d0d09939835 100644
--- a/drivers/gpu/nova-core/driver.rs
+++ b/drivers/gpu/nova-core/driver.rs
@@ -92,6 +92,8 @@ fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> impl PinInit<Self, E
Ok(try_pin_init!(Self {
gpu <- Gpu::new(pdev, bar.clone(), bar.access(pdev.as_ref())?),
+ // Run optional GPU selftests.
+ _: { gpu.run_selftests(pdev)? },
_reg <- auxiliary::Registration::new(
pdev.as_ref(),
c"nova-drm",
diff --git a/drivers/gpu/nova-core/gpu.rs b/drivers/gpu/nova-core/gpu.rs
index e217e5c7cb32..f17bf1bf0b12 100644
--- a/drivers/gpu/nova-core/gpu.rs
+++ b/drivers/gpu/nova-core/gpu.rs
@@ -319,4 +319,52 @@ pub(crate) fn unbind(&self, dev: &device::Device<device::Core>) {
.inspect(|bar| self.sysmem_flush.unregister(bar))
.is_err());
}
+
+ /// Run selftests on the constructed [`Gpu`].
+ pub(crate) fn run_selftests(
+ mut self: Pin<&mut Self>,
+ pdev: &pci::Device<device::Bound>,
+ ) -> Result {
+ self.as_mut().run_mm_selftests(pdev)?;
+ Ok(())
+ }
+
+ #[cfg(CONFIG_NOVA_MM_SELFTESTS)]
+ fn run_mm_selftests(
+ mut self: Pin<&mut Self>,
+ pdev: &pci::Device<device::Bound>,
+ ) -> Result {
+ use crate::driver::BAR1_SIZE;
+
+ let mmu_version = MmuVersion::from(self.spec.chipset.arch());
+
+ // BAR1 self-tests.
+ let bar1 = Arc::pin_init(
+ pdev.iomap_region_sized::<BAR1_SIZE>(1, c"nova-core/bar1"),
+ GFP_KERNEL,
+ )?;
+ let bar1_access = bar1.access(pdev.as_ref())?;
+
+ let proj = self.as_mut().project();
+ let bar1_pde_base = proj.gsp_static_info.bar1_pde_base();
+ let mm = proj.mm.as_ref().get_ref();
+
+ crate::mm::bar_user::run_self_test(
+ pdev.as_ref(),
+ mm,
+ bar1_access,
+ bar1_pde_base,
+ mmu_version,
+ )?;
+
+ Ok(())
+ }
+
+ #[cfg(not(CONFIG_NOVA_MM_SELFTESTS))]
+ fn run_mm_selftests(
+ self: Pin<&mut Self>,
+ _pdev: &pci::Device<device::Bound>,
+ ) -> Result {
+ Ok(())
+ }
}
diff --git a/drivers/gpu/nova-core/gsp/commands.rs b/drivers/gpu/nova-core/gsp/commands.rs
index a7778d5d9e32..bf9e3086565f 100644
--- a/drivers/gpu/nova-core/gsp/commands.rs
+++ b/drivers/gpu/nova-core/gsp/commands.rs
@@ -232,7 +232,6 @@ pub(crate) fn gpu_name(&self) -> core::result::Result<&str, GpuNameError> {
}
/// Returns the BAR1 Page Directory Entry base address.
- #[expect(dead_code)]
pub(crate) fn bar1_pde_base(&self) -> u64 {
self.bar1_pde_base
}
diff --git a/drivers/gpu/nova-core/mm/bar_user.rs b/drivers/gpu/nova-core/mm/bar_user.rs
index 74119c4d365e..5edaacf4c9d0 100644
--- a/drivers/gpu/nova-core/mm/bar_user.rs
+++ b/drivers/gpu/nova-core/mm/bar_user.rs
@@ -152,3 +152,167 @@ fn drop(&mut self) {
}
}
}
+
+/// Check if the PDB has valid, VRAM-backed page tables.
+///
+/// Returns `Err(ENOENT)` if page tables are missing or not in VRAM.
+#[cfg(CONFIG_NOVA_MM_SELFTESTS)]
+fn check_valid_page_tables(mm: &GpuMm, pdb_addr: VramAddress) -> Result {
+ use crate::mm::pagetable::ver2::Pde;
+ use crate::mm::pagetable::AperturePde;
+
+ let mut window = mm.pramin().window()?;
+ let pdb_entry_raw = window.try_read64(pdb_addr.raw())?;
+ let pdb_entry = Pde::new(pdb_entry_raw);
+
+ if !pdb_entry.is_valid() {
+ return Err(ENOENT);
+ }
+
+ if pdb_entry.aperture() != AperturePde::VideoMemory {
+ return Err(ENOENT);
+ }
+
+ Ok(())
+}
+
+/// Run MM subsystem self-tests during probe.
+///
+/// Tests page table infrastructure and `BAR1` MMIO access using the `BAR1`
+/// address space. Uses the `GpuMm`'s buddy allocator / to allocate page tables
+/// and test pages as needed.
+#[cfg(CONFIG_NOVA_MM_SELFTESTS)]
+pub(crate) fn run_self_test(
+ dev: &kernel::device::Device,
+ mm: &GpuMm,
+ bar1: &crate::driver::Bar1,
+ bar1_pdb: u64,
+ mmu_version: MmuVersion,
+) -> Result {
+ use crate::mm::vmm::Vmm;
+ use crate::mm::PAGE_SIZE;
+ use kernel::gpu::buddy::BuddyFlags;
+ use kernel::gpu::buddy::GpuBuddyAllocParams;
+ use kernel::sizes::{
+ SZ_4K,
+ SZ_64K, //
+ };
+
+ // Self-tests only support MMU v2 for now.
+ if mmu_version != MmuVersion::V2 {
+ dev_info!(
+ dev,
+ "MM: Skipping self-tests for MMU {:?} (only V2 supported)\n",
+ mmu_version
+ );
+ return Ok(());
+ }
+
+ // Test patterns.
+ const PATTERN_PRAMIN: u32 = 0xDEAD_BEEF;
+ const PATTERN_BAR1: u32 = 0xCAFE_BABE;
+
+ dev_info!(dev, "MM: Starting self-test...\n");
+
+ let pdb_addr = VramAddress::new(bar1_pdb);
+
+ // Check if initial page tables are in VRAM.
+ if check_valid_page_tables(mm, pdb_addr).is_err() {
+ dev_info!(dev, "MM: Self-test SKIPPED - no valid VRAM page tables\n");
+ return Ok(());
+ }
+
+ // Setup a test page from the buddy allocator.
+ let alloc_params = GpuBuddyAllocParams {
+ start_range_address: 0,
+ end_range_address: 0,
+ size_bytes: SZ_4K as u64,
+ min_block_size_bytes: SZ_4K as u64,
+ buddy_flags: BuddyFlags::try_new(0)?,
+ };
+
+ let test_page_blocks = KBox::pin_init(mm.buddy().alloc_blocks(&alloc_params), GFP_KERNEL)?;
+ let test_vram_offset = test_page_blocks.iter().next().ok_or(ENOMEM)?.offset();
+ let test_vram = VramAddress::new(test_vram_offset);
+ let test_pfn = Pfn::from(test_vram);
+
+ // Create a VMM of size 64K to track virtual memory mappings.
+ let mut vmm = Vmm::new(pdb_addr, MmuVersion::V2, SZ_64K as u64)?;
+
+ // Create a test mapping.
+ let mapped = vmm.map_pages(mm, &[test_pfn], None, true)?;
+ let test_vfn = mapped.vfn_start;
+
+ // Pre-compute test addresses for each access path.
+ // Use distinct offsets within the page for read (0x100) and write (0x200) tests.
+ let bar1_base_offset = test_vfn.raw() as usize * PAGE_SIZE;
+ let bar1_read_offset: usize = bar1_base_offset + 0x100;
+ let bar1_write_offset: usize = bar1_base_offset + 0x200;
+ let vram_read_addr: usize = test_vram.raw() + 0x100;
+ let vram_write_addr: usize = test_vram.raw() + 0x200;
+
+ // Test 1: Write via PRAMIN, read via BAR1.
+ {
+ let mut window = mm.pramin().window()?;
+ window.try_write32(vram_read_addr, PATTERN_PRAMIN)?;
+ }
+
+ // Read back via BAR1 aperture.
+ let bar1_value = bar1.try_read32(bar1_read_offset)?;
+
+ let test1_passed = if bar1_value == PATTERN_PRAMIN {
+ true
+ } else {
+ dev_err!(
+ dev,
+ "MM: Test 1 FAILED - Expected {:#010x}, got {:#010x}\n",
+ PATTERN_PRAMIN,
+ bar1_value
+ );
+ false
+ };
+
+ // Test 2: Write via BAR1, read via PRAMIN.
+ bar1.try_write32(PATTERN_BAR1, bar1_write_offset)?;
+
+ // Read back via PRAMIN.
+ let pramin_value = {
+ let mut window = mm.pramin().window()?;
+ window.try_read32(vram_write_addr)?
+ };
+
+ let test2_passed = if pramin_value == PATTERN_BAR1 {
+ true
+ } else {
+ dev_err!(
+ dev,
+ "MM: Test 2 FAILED - Expected {:#010x}, got {:#010x}\n",
+ PATTERN_BAR1,
+ pramin_value
+ );
+ false
+ };
+
+ // Cleanup - invalidate PTE.
+ vmm.unmap_pages(mm, mapped)?;
+
+ // Test 3: Two-phase prepare/execute API.
+ let prepared = vmm.prepare_map(mm, 1, None)?;
+ let mapped2 = vmm.execute_map(mm, prepared, &[test_pfn], true)?;
+ let readback = vmm.read_mapping(mm, mapped2.vfn_start)?;
+ let test3_passed = if readback == Some(test_pfn) {
+ true
+ } else {
+ dev_err!(dev, "MM: Test 3 FAILED - Two-phase map readback mismatch\n");
+ false
+ };
+ vmm.unmap_pages(mm, mapped2)?;
+
+ if test1_passed && test2_passed && test3_passed {
+ dev_info!(dev, "MM: All self-tests PASSED\n");
+ Ok(())
+ } else {
+ dev_err!(dev, "MM: Self-tests FAILED\n");
+ Err(EIO)
+ }
+}
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox