Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* Re: [PATCH -next v8 2/3] rust: gpu: Add GPU buddy allocator bindings
From: Joel Fernandes @ 2026-02-10 22:06 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Jonathan Corbet, Alex Deucher,
	Christian König, Jani Nikula, Joonas Lahtinen, Vivi Rodrigo,
	Tvrtko Ursulin, Rui Huang, Matthew Auld, Matthew Brost,
	Lucas De Marchi, Thomas Hellström, Helge Deller, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <DGBL94I0E5UB.4LNH3JODOKPV@kernel.org>



On 2/10/2026 4:10 PM, Danilo Krummrich wrote:
>> I'll change this to return `impl PinInit<AllocatedBlocks, Error>` in the next
>> version. If a shared ownership use case arises later, we
>> can always add an `Arc`-returning convenience wrapper.
>
> I don't think we should, don't give drivers a reason to go for more allocations
> they actually need for convinience.

I wasn't implying to give reason to go for more allocations, it is about a
reference to the same allocation that may be required to be shared from multiple
objects for whatever reason. But again, currently we don't have a use case for that.

-- 
Joel Fernandes


^ permalink raw reply

* Re: [PATCH -next v8 2/3] rust: gpu: Add GPU buddy allocator bindings
From: Joel Fernandes @ 2026-02-10 21:43 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: linux-kernel@vger.kernel.org, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Jonathan Corbet,
	Alex Deucher, Christian König, Jani Nikula, Joonas Lahtinen,
	Vivi Rodrigo, Tvrtko Ursulin, Rui Huang, Matthew Auld,
	Matthew Brost, Lucas De Marchi, Thomas Hellström,
	Helge Deller, 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, joel@joelfernandes.org,
	nouveau@lists.freedesktop.org, dri-devel@lists.freedesktop.org,
	rust-for-linux@vger.kernel.org, linux-doc@vger.kernel.org,
	amd-gfx@lists.freedesktop.org, intel-gfx@lists.freedesktop.org,
	intel-xe@lists.freedesktop.org, linux-fbdev@vger.kernel.org
In-Reply-To: <DGBL94I0E5UB.4LNH3JODOKPV@kernel.org>

Agreed with all these comments, will revise accordingly.

Thanks.

> On Feb 10, 2026, at 4:10 PM, Danilo Krummrich <dakr@kernel.org> wrote:
> 
> On Tue Feb 10, 2026 at 9:09 PM CET, Joel Fernandes wrote:
>>>> +impl GpuBuddyInner {
>>>> +    /// Create a pin-initializer for the buddy allocator.
>>>> +    fn new(params: &GpuBuddyParams) -> impl PinInit<Self, Error> {
>>> 
>>> I think we can just pass them by value, they shouldn't be needed anymore after
>>> the GpuBuddy instance has been constructed.
>> 
>> Dave Airlie specifically reviewed this in RFC v6 and recommended passing by
>> reference rather than by value [2]:
>> 
>>  "maybe we should pass them as non-mutable references, but I don't think
>>   there is any point in passing them by value ever."
>> 
>> The params are also reused in practice -- the doc examples show the same
>> `GpuBuddyParams` being used repeatedly. References
>> avoid unnecessary copies for this reuse pattern.
> 
> Well, that's for GpuBuddyAllocParams, those are indeed reused and shouldn't be
> copied all the time.
> 
> But my comment was about GpuBuddyParams, I don't see a reason those are reused
> (neither are they in the example), so it makes more sense to pass them by value,
> such that they are consumed. (I.e.  I'm not asking for adding Copy/Clone.)
> 
>> 
>> [2] https://lore.kernel.org/all/CAPM=9tyL_Cq3+qWc4A41p7eqnNDLS1APUEeUbaQyJ46YDkipVw@mail.gmail.com/
>> 
>>>> +    pub fn new(params: &GpuBuddyParams) -> Result<Self> {
>>> 
>>> Same here, we should be able to take this by value.
>> 
>> Same reasoning as above.
>> 
>>>> +    pub fn alloc_blocks(&self, params: &GpuBuddyAllocParams) -> Result<Arc<AllocatedBlocks>> {
>>> 
>>> Why do we force a reference count here? I think we should just return
>>> impl PinInit<AllocatedBlocks, Error> and let the driver decide where to
>>> initialize the object, no?
>>> 
>>> I.e. what if the driver wants to store additional data in a driver private
>>> structure? Then we'd need two allocations otherwise and another reference count
>>> in the worst case.
>> 
>> Good point. The reason I had `Arc` was to anticipate potential shared ownership
>> use cases, but at the moment there is no such use case
>> in nova-core -- each `AllocatedBlocks` has a single owner.
> 
> Sure, but drivers can always pass an impl PinInit to Arc::pin_init() themselves.
> 
>> I'll change this to return `impl PinInit<AllocatedBlocks, Error>` in the next
>> version. If a shared ownership use case arises later, we
>> can always add an `Arc`-returning convenience wrapper.
> 
> I don't think we should, don't give drivers a reason to go for more allocations
> they actually need for convinience.

^ permalink raw reply

* Re: [PATCH -next v8 2/3] rust: gpu: Add GPU buddy allocator bindings
From: Danilo Krummrich @ 2026-02-10 21:10 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Jonathan Corbet, Alex Deucher,
	Christian König, Jani Nikula, Joonas Lahtinen, Vivi Rodrigo,
	Tvrtko Ursulin, Rui Huang, Matthew Auld, Matthew Brost,
	Lucas De Marchi, Thomas Hellström, Helge Deller, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <1770754015.1979311.8126@nvidia.com>

On Tue Feb 10, 2026 at 9:09 PM CET, Joel Fernandes wrote:
>>> +impl GpuBuddyInner {
>>> +    /// Create a pin-initializer for the buddy allocator.
>>> +    fn new(params: &GpuBuddyParams) -> impl PinInit<Self, Error> {
>> 
>> I think we can just pass them by value, they shouldn't be needed anymore after
>> the GpuBuddy instance has been constructed.
>
> Dave Airlie specifically reviewed this in RFC v6 and recommended passing by
> reference rather than by value [2]:
>
>   "maybe we should pass them as non-mutable references, but I don't think
>    there is any point in passing them by value ever."
>
> The params are also reused in practice -- the doc examples show the same
> `GpuBuddyParams` being used repeatedly. References
> avoid unnecessary copies for this reuse pattern.

Well, that's for GpuBuddyAllocParams, those are indeed reused and shouldn't be
copied all the time.

But my comment was about GpuBuddyParams, I don't see a reason those are reused
(neither are they in the example), so it makes more sense to pass them by value,
such that they are consumed. (I.e.  I'm not asking for adding Copy/Clone.)

>
> [2] https://lore.kernel.org/all/CAPM=9tyL_Cq3+qWc4A41p7eqnNDLS1APUEeUbaQyJ46YDkipVw@mail.gmail.com/
>
>>> +    pub fn new(params: &GpuBuddyParams) -> Result<Self> {
>> 
>> Same here, we should be able to take this by value.
>
> Same reasoning as above.
>
>>> +    pub fn alloc_blocks(&self, params: &GpuBuddyAllocParams) -> Result<Arc<AllocatedBlocks>> {
>> 
>> Why do we force a reference count here? I think we should just return
>> impl PinInit<AllocatedBlocks, Error> and let the driver decide where to
>> initialize the object, no?
>> 
>> I.e. what if the driver wants to store additional data in a driver private
>> structure? Then we'd need two allocations otherwise and another reference count
>> in the worst case.
>
> Good point. The reason I had `Arc` was to anticipate potential shared ownership
> use cases, but at the moment there is no such use case
> in nova-core -- each `AllocatedBlocks` has a single owner.

Sure, but drivers can always pass an impl PinInit to Arc::pin_init() themselves.

> I'll change this to return `impl PinInit<AllocatedBlocks, Error>` in the next
> version. If a shared ownership use case arises later, we
> can always add an `Arc`-returning convenience wrapper.

I don't think we should, don't give drivers a reason to go for more allocations
they actually need for convinience.

^ permalink raw reply

* Re: [PATCH -next v8 2/3] rust: gpu: Add GPU buddy allocator bindings
From: Joel Fernandes @ 2026-02-10 20:09 UTC (permalink / raw)
  To: Danilo Krummrich
  Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Jonathan Corbet, Alex Deucher,
	Christian König, Jani Nikula, Joonas Lahtinen, Vivi Rodrigo,
	Tvrtko Ursulin, Rui Huang, Matthew Auld, Matthew Brost,
	Lucas De Marchi, Thomas Hellström, Helge Deller, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <DGB9G697GSWO.3VBFGU5MKFPMR@kernel.org>

Hi Danilo,

Thanks for the review!

On Tue, Feb 10, 2026 at 12:55:01PM +0100, Danilo Krummrich wrote:
> On Mon Feb 9, 2026 at 10:42 PM CET, Joel Fernandes wrote:
> 
> [...]
> 
>> +//! params.size_bytes = SZ_8M as u64;
> 
> It looks there are ~30 occurences of `as u64` in this example code, which seems
> quite inconvinient for drivers.
> 
> In nova-core I proposed to have FromSafeCast / IntoSafeCast for usize, u32 and
> u64, which would help here as well, once factored out.
> 
> But even this seems pretty annoying. I wonder if we should just have separate
> 64-bit size constants, as they'd be pretty useful in other places as well, e.g.
> GPUVM.

Agreed, the `as u64` casts are verbose. Note that these are only in the doc
examples -- actual driver code (e.g. nova-core) already uses
FromSafeCast/IntoSafeCast from your nova-core patches [1]. Once those traits
are factored out of nova-core into a shared kernel crate location, I can update
the examples to use them instead.

Since the doc examples live outside nova-core, I suggest let us keep it as using
as for now. Thoughts?

[1] https://lore.kernel.org/all/20251029-nova-as-v3-5-6a30c7333ad9@nvidia.com/

>> +#[pin_data(PinnedDrop)]
>> +struct GpuBuddyInner {
>> +    #[pin]
>> +    inner: Opaque<bindings::gpu_buddy>,
>> +    #[pin]
>> +    lock: Mutex<()>,
> 
> Why don't we have the mutex around the Opaque<bindings::gpu_buddy>? It's the
> only field the mutex does protect.
> 
> Is it because mutex does not take an impl PinInit? If so, we should add a
> comment with a proper TODO.

Correct, that is the reason. I'll add a TODO comment in
the next version explaining this limitation.

>> +impl GpuBuddyInner {
>> +    /// Create a pin-initializer for the buddy allocator.
>> +    fn new(params: &GpuBuddyParams) -> impl PinInit<Self, Error> {
> 
> I think we can just pass them by value, they shouldn't be needed anymore after
> the GpuBuddy instance has been constructed.

Dave Airlie specifically reviewed this in RFC v6 and recommended passing by
reference rather than by value [2]:

  "maybe we should pass them as non-mutable references, but I don't think
   there is any point in passing them by value ever."

The params are also reused in practice -- the doc examples show the same
`GpuBuddyParams` being used repeatedly. References
avoid unnecessary copies for this reuse pattern.

[2] https://lore.kernel.org/all/CAPM=9tyL_Cq3+qWc4A41p7eqnNDLS1APUEeUbaQyJ46YDkipVw@mail.gmail.com/

>> +    pub fn new(params: &GpuBuddyParams) -> Result<Self> {
> 
> Same here, we should be able to take this by value.

Same reasoning as above.

>> +    pub fn alloc_blocks(&self, params: &GpuBuddyAllocParams) -> Result<Arc<AllocatedBlocks>> {
> 
> Why do we force a reference count here? I think we should just return
> impl PinInit<AllocatedBlocks, Error> and let the driver decide where to
> initialize the object, no?
> 
> I.e. what if the driver wants to store additional data in a driver private
> structure? Then we'd need two allocations otherwise and another reference count
> in the worst case.

Good point. The reason I had `Arc` was to anticipate potential shared ownership
use cases, but at the moment there is no such use case
in nova-core -- each `AllocatedBlocks` has a single owner.

I'll change this to return `impl PinInit<AllocatedBlocks, Error>` in the next
version. If a shared ownership use case arises later, we
can always add an `Arc`-returning convenience wrapper.

For the nova-core side, the field would change from
`KVec<Arc<AllocatedBlocks>>` to `KVec<Pin<KBox<AllocatedBlocks>>>`, which
works fine I think.

-- 
Joel Fernandes


^ permalink raw reply

* Re: [PATCH -next v8 1/3] rust: clist: Add support to interface with C linked lists
From: Daniel Almeida @ 2026-02-10 17:15 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, 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, joel, nouveau, dri-devel, rust-for-linux, linux-doc,
	amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260209214246.2783990-2-joelagnelf@nvidia.com>

Hi Joel,

> On 9 Feb 2026, at 18:42, Joel Fernandes <joelagnelf@nvidia.com> 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.
> 
> Acked-by: Gary Guo <gary@garyguo.net>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> 


Sorry for not replying to your question on v7, I’ve been a bit sick recently.

Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>


^ permalink raw reply

* Re: [PATCH -next v8 2/3] rust: gpu: Add GPU buddy allocator bindings
From: Danilo Krummrich @ 2026-02-10 11:55 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, 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, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260209214246.2783990-3-joelagnelf@nvidia.com>

On Mon Feb 9, 2026 at 10:42 PM CET, Joel Fernandes wrote:

[...]

> +//! params.size_bytes = SZ_8M as u64;

It looks there are ~30 occurences of `as u64` in this example code, which seems
quite inconvinient for drivers.

In nova-core I proposed to have FromSafeCast / IntoSafeCast for usize, u32 and
u64, which would help here as well, once factored out.

But even this seems pretty annoying. I wonder if we should just have separate
64-bit size constants, as they'd be pretty useful in other places as well, e.g.
GPUVM.

> +/// Inner structure holding the actual buddy allocator.
> +///
> +/// # Synchronization
> +///
> +/// The C `gpu_buddy` API requires synchronization (see `include/linux/gpu_buddy.h`).
> +/// The internal [`GpuBuddyGuard`] ensures that the lock is held for all
> +/// allocator and free operations, preventing races between concurrent allocations
> +/// and the freeing that occurs when [`AllocatedBlocks`] is dropped.
> +///
> +/// # Invariants
> +///
> +/// The inner [`Opaque`] contains a valid, initialized buddy allocator.
> +#[pin_data(PinnedDrop)]
> +struct GpuBuddyInner {
> +    #[pin]
> +    inner: Opaque<bindings::gpu_buddy>,
> +    #[pin]
> +    lock: Mutex<()>,

Why don't we have the mutex around the Opaque<bindings::gpu_buddy>? It's the
only field the mutex does protect.

Is it because mutex does not take an impl PinInit? If so, we should add a
comment with a proper TODO.

> +    /// Base offset for all allocations (does not change after init).
> +    base_offset: u64,
> +    /// Cached chunk size (does not change after init).
> +    chunk_size: u64,
> +    /// Cached total size (does not change after init).
> +    size: u64,
> +}
> +
> +impl GpuBuddyInner {
> +    /// Create a pin-initializer for the buddy allocator.
> +    fn new(params: &GpuBuddyParams) -> impl PinInit<Self, Error> {

I think we can just pass them by value, they shouldn't be needed anymore after
the GpuBuddy instance has been constructed.

> +        let base_offset = params.base_offset_bytes;
> +        let size = params.physical_memory_size_bytes;
> +        let chunk_size = params.chunk_size_bytes;
> +
> +        try_pin_init!(Self {
> +            inner <- Opaque::try_ffi_init(|ptr| {
> +                // SAFETY: ptr points to valid uninitialized memory from the pin-init
> +                // infrastructure. gpu_buddy_init will initialize the structure.
> +                to_result(unsafe { bindings::gpu_buddy_init(ptr, size, chunk_size) })
> +            }),
> +            lock <- new_mutex!(()),
> +            base_offset: base_offset,
> +            chunk_size: chunk_size,
> +            size: size,
> +        })
> +    }

<snip>

> +/// GPU buddy allocator instance.
> +///
> +/// This structure wraps the C `gpu_buddy` allocator using reference counting.
> +/// The allocator is automatically cleaned up when all references are dropped.
> +///
> +/// # Invariants
> +///
> +/// The inner [`Arc`] points to a valid, initialized GPU buddy allocator.
> +pub struct GpuBuddy(Arc<GpuBuddyInner>);
> +
> +impl GpuBuddy {
> +    /// Create a new buddy allocator.
> +    ///
> +    /// Creates a buddy allocator that manages a contiguous address space of the given
> +    /// size, with the specified minimum allocation unit (chunk_size must be at least 4KB).
> +    pub fn new(params: &GpuBuddyParams) -> Result<Self> {

Same here, we should be able to take this by value.

> +        Ok(Self(Arc::pin_init(
> +            GpuBuddyInner::new(params),
> +            GFP_KERNEL,
> +        )?))
> +    }

<snip>

> +    /// Allocate blocks from the buddy allocator.
> +    ///
> +    /// Returns an [`Arc<AllocatedBlocks>`] structure that owns the allocated blocks
> +    /// and automatically frees them when all references are dropped.
> +    ///
> +    /// Takes `&self` instead of `&mut self` because the internal [`Mutex`] provides
> +    /// synchronization - no external `&mut` exclusivity needed.
> +    pub fn alloc_blocks(&self, params: &GpuBuddyAllocParams) -> Result<Arc<AllocatedBlocks>> {

Why do we force a reference count here? I think we should just return
impl PinInit<AllocatedBlocks, Error> and let the driver decide where to
initialize the object, no?

I.e. what if the driver wants to store additional data in a driver private
structure? Then we'd need two allocations otherwise and another reference count
in the worst case.

> +        let buddy_arc = Arc::clone(&self.0);
> +
> +        // Create pin-initializer that initializes list and allocates blocks.
> +        let init = try_pin_init!(AllocatedBlocks {
> +            buddy: Arc::clone(&buddy_arc),
> +            list <- CListHead::new(),
> +            flags: params.buddy_flags,
> +            _: {
> +                // Lock while allocating to serialize with concurrent frees.
> +                let guard = buddy.lock();
> +
> +                // SAFETY: `guard` provides exclusive access to the buddy allocator.
> +                to_result(unsafe {
> +                    bindings::gpu_buddy_alloc_blocks(
> +                        guard.as_raw(),
> +                        params.start_range_address,
> +                        params.end_range_address,
> +                        params.size_bytes,
> +                        params.min_block_size_bytes,
> +                        list.as_raw(),
> +                        params.buddy_flags.as_raw(),
> +                    )
> +                })?
> +            }
> +        });
> +
> +        Arc::pin_init(init, GFP_KERNEL)
> +    }
> +}

^ permalink raw reply

* Re: [PATCH -next v8 3/3] nova-core: mm: Select GPU_BUDDY for VRAM allocation
From: Danilo Krummrich @ 2026-02-10 10:10 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, 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, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260209214246.2783990-4-joelagnelf@nvidia.com>

On Mon Feb 9, 2026 at 10:42 PM CET, Joel Fernandes wrote:
> diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
> index 527920f9c4d3..c129764daa23 100644
> --- a/drivers/gpu/nova-core/Kconfig
> +++ b/drivers/gpu/nova-core/Kconfig
> @@ -3,6 +3,7 @@ config NOVA_CORE
>  	depends on 64BIT
>  	depends on PCI
>  	depends on RUST
> +	select GPU_BUDDY
>  	select RUST_FW_LOADER_ABSTRACTIONS
>  	select AUXILIARY_BUS
>  	default n

NIT: Let's get the 'select' list ordered. :)

^ permalink raw reply

* Re: [PATCH -next v8 1/3] rust: clist: Add support to interface with C linked lists
From: Danilo Krummrich @ 2026-02-10 10:07 UTC (permalink / raw)
  To: Joel Fernandes
  Cc: linux-kernel, 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, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <20260209214246.2783990-2-joelagnelf@nvidia.com>

On Mon Feb 9, 2026 at 10:42 PM CET, Joel Fernandes wrote:
>  rust/kernel/clist.rs   | 320 +++++++++++++++++++++++++++++++++++++++++

I think we should move this under rust/kernel/ffi/ to make it obvious that this
is FFI infrastructure.

> 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.

Here and in the struct documentation, I'd suggest to clearly point out the
use-cases, i.e. that this infrastructure is for FFI use-cases only and should
not be used otherwise in drivers, etc.

^ permalink raw reply

* Re: [PATCH] fbcon: Declare struct fb_info.fbcon_par as of type struct fbcon_par
From: Helge Deller @ 2026-02-10 10:01 UTC (permalink / raw)
  To: Thomas Zimmermann; +Cc: linux-fbdev, dri-devel
In-Reply-To: <20260210094356.23645-1-tzimmermann@suse.de>

On 2/10/26 10:43, Thomas Zimmermann wrote:
> The only correct type for the field fbcon_par in struct fb_info
> is struct fbcon_par. Declare is as such. The field is a pointer
> to fbcon-private data.
> 
> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> ---
>   include/linux/fb.h | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)

applied.
Thanks!
Helge

^ permalink raw reply

* [PATCH] fbcon: Declare struct fb_info.fbcon_par as of type struct fbcon_par
From: Thomas Zimmermann @ 2026-02-10  9:43 UTC (permalink / raw)
  To: deller; +Cc: linux-fbdev, dri-devel, Thomas Zimmermann

The only correct type for the field fbcon_par in struct fb_info
is struct fbcon_par. Declare is as such. The field is a pointer
to fbcon-private data.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
---
 include/linux/fb.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/fb.h b/include/linux/fb.h
index 65fb70382675..b8b6f54f3312 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -18,6 +18,7 @@ struct backlight_device;
 struct device;
 struct device_node;
 struct fb_info;
+struct fbcon_par;
 struct file;
 struct i2c_adapter;
 struct inode;
@@ -506,7 +507,7 @@ struct fb_info {
 #define FBINFO_STATE_RUNNING	0
 #define FBINFO_STATE_SUSPENDED	1
 	u32 state;			/* Hardware state i.e suspend */
-	void *fbcon_par;                /* fbcon use-only private area */
+	struct fbcon_par *fbcon_par;    /* fbcon use-only private area */
 	/* From here on everything is device dependent */
 	void *par;
 
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH] fbcon: Remove struct fbcon_display.inverse
From: Thomas Zimmermann @ 2026-02-10  9:06 UTC (permalink / raw)
  To: Helge Deller, geert; +Cc: linux-fbdev, dri-devel, stable
In-Reply-To: <3e70bea8-aa35-4cfd-9e54-eaeaa7b5267a@gmx.de>

Hi

Am 09.02.26 um 22:31 schrieb Helge Deller:
> On 2/9/26 17:15, Thomas Zimmermann wrote:
>> The field inverse in struct fbcon_display is unused. Remove it.
>
> Indeed, seems to be unused.
>
>> The field apparently never did anything. Commit c7ef5e285c84 ("video:
>> fbdev: atari: Fix inverse handling") converted its final user to call
>> fb_invert_cmaps() instead.
>
> That commit seems not to be related, as it touches a static
> inverse variable inside the atafb driver only.
> Commit e4fc27618b75 (from 2005) touched it last time, but it seems 
> even older.

Oh well. What a stupid mistake...

>
> Patch applied to fbdev, but I dropped the wrong commit reference in the
> commit message.

Thanks a lot.

Best regards,
Thomas

>
> Thanks!
> Helge
>
>> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
>> Fixes: c7ef5e285c84 ("video: fbdev: atari: Fix inverse handling")
>> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
>> Cc: Helge Deller <deller@gmx.de>
>> Cc: <stable@vger.kernel.org> # v6.0+
>> ---
>>   drivers/video/fbdev/core/fbcon.h | 1 -
>>   1 file changed, 1 deletion(-)
>>
>> diff --git a/drivers/video/fbdev/core/fbcon.h 
>> b/drivers/video/fbdev/core/fbcon.h
>> index 1cd10a7faab0..fca14e9b729b 100644
>> --- a/drivers/video/fbdev/core/fbcon.h
>> +++ b/drivers/video/fbdev/core/fbcon.h
>> @@ -30,7 +30,6 @@ struct fbcon_display {
>>   #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
>>       u_short scrollmode;             /* Scroll Method, use 
>> fb_scrollmode() */
>>   #endif
>> -    u_short inverse;                /* != 0 text black on white as 
>> default */
>>       short yscroll;                  /* Hardware scrolling */
>>       int vrows;                      /* number of virtual rows */
>>       int cursor_shape;
>
>

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)



^ permalink raw reply

* Re: [PATCH v7 1/4] dt-bindings: backlight: Add max25014 support
From: Maud Spierings @ 2026-02-10  8:51 UTC (permalink / raw)
  To: Rob Herring
  Cc: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek,
	Krzysztof Kozlowski, Conor Dooley, Helge Deller, Shawn Guo,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Liam Girdwood, Mark Brown, dri-devel, linux-leds, devicetree,
	linux-kernel, linux-fbdev, imx, linux-arm-kernel
In-Reply-To: <20260129160418.GA1100798-robh@kernel.org>

On 1/29/26 17:04, Rob Herring wrote:
> On Fri, Jan 23, 2026 at 12:31:30PM +0100, Maud Spierings wrote:
>> The Maxim MAX25014 is a 4-channel automotive grade backlight driver IC
>> with integrated boost controller.
>>
>> Signed-off-by: Maud Spierings <maudspierings@gocontroll.com>
>>
>> ---
>>
>> In the current implementation the control registers for channel 1,
>> control all channels. So only one led subnode with led-sources is
>> supported right now. If at some point the driver functionality is
>> expanded the bindings can be easily extended with it.
>> ---
>>   .../bindings/leds/backlight/maxim,max25014.yaml    | 91 ++++++++++++++++++++++
>>   MAINTAINERS                                        |  5 ++
>>   2 files changed, 96 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml b/Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml
>> new file mode 100644
>> index 000000000000..c499e6224a8f
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/leds/backlight/maxim,max25014.yaml
>> @@ -0,0 +1,91 @@
>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/leds/backlight/maxim,max25014.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Maxim max25014 backlight controller
>> +
>> +maintainers:
>> +  - Maud Spierings <maudspierings@gocontroll.com>
>> +
>> +properties:
>> +  compatible:
>> +    enum:
>> +      - maxim,max25014
>> +
>> +  reg:
>> +    maxItems: 1
>> +
> 
>> +  "#address-cells":
>> +    const: 1
>> +
>> +  "#size-cells":
>> +    const: 0
> 
> No child nodes (with addresses), so these should be dropped. And in the
> example.
> 
> With that,
> 
> Reviewed-by: Rob Herring (Arm) <robh@kernel.org>

And in the actual dtso's too, thanks for spotting this, this passed the 
dts check but indeed is not correct anymore.

kind regards,
Maud


^ permalink raw reply

* Re: [PATCH] arch: m68k: remove incomplete, unusable Apollo hardware support
From: Ethan Nelson-Moore @ 2026-02-09 22:59 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: linux-m68k, linux-fbdev, Helge Deller, Jiri Slaby (SUSE),
	Ilpo Järvinen, Greg Kroah-Hartman, Eric Biggers, Herbert Xu,
	Thomas Huth, Greg Ungerer, Finn Thain, Thorsten Blum,
	Jean-Michel Hautbois, Kees Cook, Thomas Zimmermann, Wei Liu,
	Prasanna Kumar T S M, Sukrut Heroorkar
In-Reply-To: <CAMuHMdUPX_ynhX_t8GtB7eRqF_6W4BwqC8w7SRpro-1Okxd70w@mail.gmail.com>

Hi, Geert,

On Mon, Feb 9, 2026 at 12:03 AM Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> Thanks for your patch!
You're welcome.

> I didn't know that is a requirement;  one of the advantages of Linux
> is that you never need to reboot ;-)
Funny. I was just using it as an example of how incomplete the support is.

> Seems like you missed https://github.com/geertu/m68k-bootinfo...
I'm not sure how that happened, given that I checked every page of
GitHub code search results. Maybe they had never indexed the repo.
Would you like me to send a new version with the UAPI header and
constants retained?

> Apart from dnfb, this only removes code under arch/m68k/.
> Is any of the removed code blocking further development for you?
No, but it's better if the kernel doesn't carry around this unusable
code for no reason. People have to touch it when they make tree-wide
or architecture-wide changes, which just wastes their time.

Ethan

^ permalink raw reply

* [PATCH -next v8 2/3] rust: gpu: Add GPU buddy allocator bindings
From: Joel Fernandes @ 2026-02-09 21:42 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, joel, nouveau, dri-devel,
	rust-for-linux, linux-doc, amd-gfx, intel-gfx, intel-xe,
	linux-fbdev, Joel Fernandes
In-Reply-To: <20260209214246.2783990-1-joelagnelf@nvidia.com>

Add safe Rust abstractions over the Linux kernel's GPU buddy
allocator for physical memory management. The GPU buddy allocator
implements a binary buddy system useful for GPU physical memory
allocation. nova-core will use it for physical memory allocation.

Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
 rust/bindings/bindings_helper.h |  11 +
 rust/helpers/gpu.c              |  23 ++
 rust/helpers/helpers.c          |   1 +
 rust/kernel/gpu/buddy.rs        | 530 ++++++++++++++++++++++++++++++++
 rust/kernel/gpu/mod.rs          |   5 +
 rust/kernel/lib.rs              |   2 +
 6 files changed, 572 insertions(+)
 create mode 100644 rust/helpers/gpu.c
 create mode 100644 rust/kernel/gpu/buddy.rs
 create mode 100644 rust/kernel/gpu/mod.rs

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 083cc44aa952..dbb765a9fdbd 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -29,6 +29,7 @@
 #include <linux/hrtimer_types.h>
 
 #include <linux/acpi.h>
+#include <linux/gpu_buddy.h>
 #include <drm/drm_device.h>
 #include <drm/drm_drv.h>
 #include <drm/drm_file.h>
@@ -146,6 +147,16 @@ const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP = VM_MIXEDMAP;
 const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE = VM_HUGEPAGE;
 const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE = VM_NOHUGEPAGE;
 
+#if IS_ENABLED(CONFIG_GPU_BUDDY)
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_RANGE_ALLOCATION = GPU_BUDDY_RANGE_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TOPDOWN_ALLOCATION = GPU_BUDDY_TOPDOWN_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CONTIGUOUS_ALLOCATION =
+								GPU_BUDDY_CONTIGUOUS_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CLEAR_ALLOCATION = GPU_BUDDY_CLEAR_ALLOCATION;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_CLEARED = GPU_BUDDY_CLEARED;
+const unsigned long RUST_CONST_HELPER_GPU_BUDDY_TRIM_DISABLE = GPU_BUDDY_TRIM_DISABLE;
+#endif
+
 #if IS_ENABLED(CONFIG_ANDROID_BINDER_IPC_RUST)
 #include "../../drivers/android/binder/rust_binder.h"
 #include "../../drivers/android/binder/rust_binder_events.h"
diff --git a/rust/helpers/gpu.c b/rust/helpers/gpu.c
new file mode 100644
index 000000000000..38b1a4e6bef8
--- /dev/null
+++ b/rust/helpers/gpu.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/gpu_buddy.h>
+
+#ifdef CONFIG_GPU_BUDDY
+
+__rust_helper u64 rust_helper_gpu_buddy_block_offset(const struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_offset(block);
+}
+
+__rust_helper unsigned int rust_helper_gpu_buddy_block_order(struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_order(block);
+}
+
+__rust_helper u64 rust_helper_gpu_buddy_block_size(struct gpu_buddy *mm,
+						   struct gpu_buddy_block *block)
+{
+	return gpu_buddy_block_size(mm, block);
+}
+
+#endif /* CONFIG_GPU_BUDDY */
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 724fcb8240ac..a53929ce52a3 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -32,6 +32,7 @@
 #include "err.c"
 #include "irq.c"
 #include "fs.c"
+#include "gpu.c"
 #include "io.c"
 #include "jump_label.c"
 #include "kunit.c"
diff --git a/rust/kernel/gpu/buddy.rs b/rust/kernel/gpu/buddy.rs
new file mode 100644
index 000000000000..00290ce53aeb
--- /dev/null
+++ b/rust/kernel/gpu/buddy.rs
@@ -0,0 +1,530 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! GPU buddy allocator bindings.
+//!
+//! C header: [`include/linux/gpu_buddy.h`](srctree/include/linux/gpu_buddy.h)
+//!
+//! This module provides Rust abstractions over the Linux kernel's GPU buddy
+//! allocator, which implements a binary buddy memory allocator.
+//!
+//! The buddy allocator manages a contiguous address space and allocates blocks
+//! in power-of-two sizes, useful for GPU physical memory management.
+//!
+//! # Examples
+//!
+//! ```
+//! use kernel::{
+//!     gpu::buddy::{BuddyFlags, GpuBuddy, GpuBuddyAllocParams, GpuBuddyParams},
+//!     prelude::*,
+//!     sizes::*, //
+//! };
+//!
+//! // Create a 1GB buddy allocator with 4KB minimum chunk size.
+//! let buddy = GpuBuddy::new(&GpuBuddyParams {
+//!     base_offset_bytes: 0,
+//!     physical_memory_size_bytes: SZ_1G as u64,
+//!     chunk_size_bytes: SZ_4K as u64,
+//! })?;
+//!
+//! // Verify initial state.
+//! assert_eq!(buddy.size(), SZ_1G as u64);
+//! assert_eq!(buddy.chunk_size(), SZ_4K as u64);
+//! let initial_free = buddy.free_memory_bytes();
+//!
+//! // Base allocation params - mutated between calls for field overrides.
+//! let mut params = GpuBuddyAllocParams {
+//!     start_range_address: 0,
+//!     end_range_address: 0,   // Entire range.
+//!     size_bytes: SZ_16M as u64,
+//!     min_block_size_bytes: SZ_16M as u64,
+//!     buddy_flags: BuddyFlags::try_new(BuddyFlags::RANGE_ALLOCATION)?,
+//! };
+//!
+//! // Test top-down allocation (allocates from highest addresses).
+//! params.buddy_flags = BuddyFlags::try_new(BuddyFlags::TOPDOWN_ALLOCATION)?;
+//! let topdown = buddy.alloc_blocks(&params)?;
+//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_16M as u64);
+//!
+//! for block in topdown.iter() {
+//!     assert_eq!(block.offset(), (SZ_1G - SZ_16M) as u64);
+//!     assert_eq!(block.order(), 12); // 2^12 pages
+//!     assert_eq!(block.size(), SZ_16M as u64);
+//! }
+//! drop(topdown);
+//! assert_eq!(buddy.free_memory_bytes(), initial_free);
+//!
+//! // Allocate 16MB - should result in a single 16MB block at offset 0.
+//! params.buddy_flags = BuddyFlags::try_new(BuddyFlags::RANGE_ALLOCATION)?;
+//! let allocated = buddy.alloc_blocks(&params)?;
+//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_16M as u64);
+//!
+//! for block in allocated.iter() {
+//!     assert_eq!(block.offset(), 0);
+//!     assert_eq!(block.order(), 12); // 2^12 pages
+//!     assert_eq!(block.size(), SZ_16M as u64);
+//! }
+//! drop(allocated);
+//! assert_eq!(buddy.free_memory_bytes(), initial_free);
+//!
+//! // Test non-contiguous allocation with fragmented memory.
+//! // Create fragmentation by allocating 4MB blocks at [0,4M) and [8M,12M).
+//! params.end_range_address = SZ_4M as u64;
+//! params.size_bytes = SZ_4M as u64;
+//! params.min_block_size_bytes = SZ_4M as u64;
+//! let frag1 = buddy.alloc_blocks(&params)?;
+//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_4M as u64);
+//!
+//! params.start_range_address = SZ_8M as u64;
+//! params.end_range_address = (SZ_8M + SZ_4M) as u64;
+//! let frag2 = buddy.alloc_blocks(&params)?;
+//! assert_eq!(buddy.free_memory_bytes(), initial_free - SZ_8M as u64);
+//!
+//! // Allocate 8MB without CONTIGUOUS - should return 2 blocks from the holes.
+//! params.start_range_address = 0;
+//! params.end_range_address = SZ_16M as u64;
+//! params.size_bytes = SZ_8M as u64;
+//! let fragmented = buddy.alloc_blocks(&params)?;
+//! assert_eq!(buddy.free_memory_bytes(), initial_free - (SZ_16M) as u64);
+//!
+//! let (mut count, mut total) = (0u32, 0u64);
+//! for block in fragmented.iter() {
+//!     // The 8MB allocation should return 2 blocks, each 4MB.
+//!     assert_eq!(block.size(), SZ_4M as u64);
+//!     total += block.size();
+//!     count += 1;
+//! }
+//! assert_eq!(total, SZ_8M as u64);
+//! assert_eq!(count, 2);
+//! drop(fragmented);
+//! drop(frag2);
+//! drop(frag1);
+//! assert_eq!(buddy.free_memory_bytes(), initial_free);
+//!
+//! // Test CONTIGUOUS failure when only fragmented space available.
+//! // Create a small buddy allocator with only 16MB of memory.
+//! let small = GpuBuddy::new(&GpuBuddyParams {
+//!     base_offset_bytes: 0,
+//!     physical_memory_size_bytes: SZ_16M as u64,
+//!     chunk_size_bytes: SZ_4K as u64,
+//! })?;
+//!
+//! // Allocate 4MB blocks at [0,4M) and [8M,12M) to create fragmented memory.
+//! params.start_range_address = 0;
+//! params.end_range_address = SZ_4M as u64;
+//! params.size_bytes = SZ_4M as u64;
+//! let hole1 = small.alloc_blocks(&params)?;
+//!
+//! params.start_range_address = SZ_8M as u64;
+//! params.end_range_address = (SZ_8M + SZ_4M) as u64;
+//! let hole2 = small.alloc_blocks(&params)?;
+//!
+//! // 8MB contiguous should fail - only two non-contiguous 4MB holes exist.
+//! params.start_range_address = 0;
+//! params.end_range_address = 0;
+//! params.size_bytes = SZ_8M as u64;
+//! params.buddy_flags = BuddyFlags::try_new(BuddyFlags::CONTIGUOUS_ALLOCATION)?;
+//! let result = small.alloc_blocks(&params);
+//! assert!(result.is_err());
+//! drop(hole2);
+//! drop(hole1);
+//!
+//! # Ok::<(), Error>(())
+//! ```
+
+use crate::{
+    bindings,
+    clist::CListHead,
+    clist_create,
+    error::to_result,
+    new_mutex,
+    prelude::*,
+    sync::{
+        lock::mutex::MutexGuard,
+        Arc,
+        Mutex, //
+    },
+    types::Opaque,
+};
+
+/// Flags for GPU buddy allocator operations.
+///
+/// These flags control the allocation behavior of the buddy allocator.
+#[derive(Clone, Copy, Default, PartialEq, Eq)]
+pub struct BuddyFlags(usize);
+
+impl BuddyFlags {
+    /// Range-based allocation from start to end addresses.
+    pub const RANGE_ALLOCATION: usize = bindings::GPU_BUDDY_RANGE_ALLOCATION;
+
+    /// Allocate from top of address space downward.
+    pub const TOPDOWN_ALLOCATION: usize = bindings::GPU_BUDDY_TOPDOWN_ALLOCATION;
+
+    /// Allocate physically contiguous blocks.
+    pub const CONTIGUOUS_ALLOCATION: usize = bindings::GPU_BUDDY_CONTIGUOUS_ALLOCATION;
+
+    /// Request allocation from the cleared (zeroed) memory. The zero'ing is not
+    /// done by the allocator, but by the caller before freeing old blocks.
+    pub const CLEAR_ALLOCATION: usize = bindings::GPU_BUDDY_CLEAR_ALLOCATION;
+
+    /// Disable trimming of partially used blocks.
+    pub const TRIM_DISABLE: usize = bindings::GPU_BUDDY_TRIM_DISABLE;
+
+    /// Mark blocks as cleared (zeroed) when freeing. When set during free,
+    /// indicates that the caller has already zeroed the memory.
+    pub const CLEARED: usize = bindings::GPU_BUDDY_CLEARED;
+
+    /// Create [`BuddyFlags`] from a raw value with validation.
+    ///
+    /// Use `|` operator to combine flags if needed, before calling this method.
+    pub fn try_new(flags: usize) -> Result<Self> {
+        // Flags must not exceed u32::MAX to satisfy the GPU buddy allocator C API.
+        if flags > u32::MAX as usize {
+            return Err(EINVAL);
+        }
+
+        // `TOPDOWN_ALLOCATION` only works without `RANGE_ALLOCATION`. When both are
+        // set, `TOPDOWN_ALLOCATION` is silently ignored by the allocator. Reject this.
+        if (flags & Self::RANGE_ALLOCATION) != 0 && (flags & Self::TOPDOWN_ALLOCATION) != 0 {
+            return Err(EINVAL);
+        }
+
+        Ok(Self(flags))
+    }
+
+    /// Get raw value of the flags.
+    pub(crate) fn as_raw(self) -> usize {
+        self.0
+    }
+}
+
+/// Parameters for creating a GPU buddy allocator.
+pub struct GpuBuddyParams {
+    /// Base offset in bytes where the managed memory region starts.
+    /// Allocations will be offset by this value.
+    pub base_offset_bytes: u64,
+    /// Total physical memory size managed by the allocator in bytes.
+    pub physical_memory_size_bytes: u64,
+    /// Minimum allocation unit / chunk size in bytes, must be >= 4KB.
+    pub chunk_size_bytes: u64,
+}
+
+/// Parameters for allocating blocks from a GPU buddy allocator.
+pub struct GpuBuddyAllocParams {
+    /// Start of allocation range in bytes. Use 0 for beginning.
+    pub start_range_address: u64,
+    /// End of allocation range in bytes. Use 0 for entire range.
+    pub end_range_address: u64,
+    /// Total size to allocate in bytes.
+    pub size_bytes: u64,
+    /// Minimum block size for fragmented allocations in bytes.
+    pub min_block_size_bytes: u64,
+    /// Buddy allocator behavior flags.
+    pub buddy_flags: BuddyFlags,
+}
+
+/// Inner structure holding the actual buddy allocator.
+///
+/// # Synchronization
+///
+/// The C `gpu_buddy` API requires synchronization (see `include/linux/gpu_buddy.h`).
+/// The internal [`GpuBuddyGuard`] ensures that the lock is held for all
+/// allocator and free operations, preventing races between concurrent allocations
+/// and the freeing that occurs when [`AllocatedBlocks`] is dropped.
+///
+/// # Invariants
+///
+/// The inner [`Opaque`] contains a valid, initialized buddy allocator.
+#[pin_data(PinnedDrop)]
+struct GpuBuddyInner {
+    #[pin]
+    inner: Opaque<bindings::gpu_buddy>,
+    #[pin]
+    lock: Mutex<()>,
+    /// Base offset for all allocations (does not change after init).
+    base_offset: u64,
+    /// Cached chunk size (does not change after init).
+    chunk_size: u64,
+    /// Cached total size (does not change after init).
+    size: u64,
+}
+
+impl GpuBuddyInner {
+    /// Create a pin-initializer for the buddy allocator.
+    fn new(params: &GpuBuddyParams) -> impl PinInit<Self, Error> {
+        let base_offset = params.base_offset_bytes;
+        let size = params.physical_memory_size_bytes;
+        let chunk_size = params.chunk_size_bytes;
+
+        try_pin_init!(Self {
+            inner <- Opaque::try_ffi_init(|ptr| {
+                // SAFETY: ptr points to valid uninitialized memory from the pin-init
+                // infrastructure. gpu_buddy_init will initialize the structure.
+                to_result(unsafe { bindings::gpu_buddy_init(ptr, size, chunk_size) })
+            }),
+            lock <- new_mutex!(()),
+            base_offset: base_offset,
+            chunk_size: chunk_size,
+            size: size,
+        })
+    }
+
+    /// Lock the mutex and return a guard for accessing the allocator.
+    fn lock(&self) -> GpuBuddyGuard<'_> {
+        GpuBuddyGuard {
+            inner: self,
+            _guard: self.lock.lock(),
+        }
+    }
+}
+
+#[pinned_drop]
+impl PinnedDrop for GpuBuddyInner {
+    fn drop(self: Pin<&mut Self>) {
+        let guard = self.lock();
+
+        // SAFETY: guard provides exclusive access to the allocator.
+        unsafe {
+            bindings::gpu_buddy_fini(guard.as_raw());
+        }
+    }
+}
+
+// SAFETY: [`GpuBuddyInner`] can be sent between threads.
+unsafe impl Send for GpuBuddyInner {}
+
+// SAFETY: [`GpuBuddyInner`] is `Sync` because the internal [`GpuBuddyGuard`]
+// serializes all access to the C allocator, preventing data races.
+unsafe impl Sync for GpuBuddyInner {}
+
+/// Guard that proves the lock is held, enabling access to the allocator.
+///
+/// # Invariants
+///
+/// The inner `_guard` holds the lock for the duration of this guard's lifetime.
+pub(crate) struct GpuBuddyGuard<'a> {
+    inner: &'a GpuBuddyInner,
+    _guard: MutexGuard<'a, ()>,
+}
+
+impl GpuBuddyGuard<'_> {
+    /// Get a raw pointer to the underlying C `gpu_buddy` structure.
+    fn as_raw(&self) -> *mut bindings::gpu_buddy {
+        self.inner.inner.get()
+    }
+}
+
+/// GPU buddy allocator instance.
+///
+/// This structure wraps the C `gpu_buddy` allocator using reference counting.
+/// The allocator is automatically cleaned up when all references are dropped.
+///
+/// # Invariants
+///
+/// The inner [`Arc`] points to a valid, initialized GPU buddy allocator.
+pub struct GpuBuddy(Arc<GpuBuddyInner>);
+
+impl GpuBuddy {
+    /// Create a new buddy allocator.
+    ///
+    /// Creates a buddy allocator that manages a contiguous address space of the given
+    /// size, with the specified minimum allocation unit (chunk_size must be at least 4KB).
+    pub fn new(params: &GpuBuddyParams) -> Result<Self> {
+        Ok(Self(Arc::pin_init(
+            GpuBuddyInner::new(params),
+            GFP_KERNEL,
+        )?))
+    }
+
+    /// Get the base offset for allocations.
+    pub fn base_offset(&self) -> u64 {
+        self.0.base_offset
+    }
+
+    /// Get the chunk size (minimum allocation unit).
+    pub fn chunk_size(&self) -> u64 {
+        self.0.chunk_size
+    }
+
+    /// Get the total managed size.
+    pub fn size(&self) -> u64 {
+        self.0.size
+    }
+
+    /// Get the available (free) memory in bytes.
+    pub fn free_memory_bytes(&self) -> u64 {
+        let guard = self.0.lock();
+        // SAFETY: guard provides exclusive access to the allocator.
+        unsafe { (*guard.as_raw()).avail }
+    }
+
+    /// Allocate blocks from the buddy allocator.
+    ///
+    /// Returns an [`Arc<AllocatedBlocks>`] structure that owns the allocated blocks
+    /// and automatically frees them when all references are dropped.
+    ///
+    /// Takes `&self` instead of `&mut self` because the internal [`Mutex`] provides
+    /// synchronization - no external `&mut` exclusivity needed.
+    pub fn alloc_blocks(&self, params: &GpuBuddyAllocParams) -> Result<Arc<AllocatedBlocks>> {
+        let buddy_arc = Arc::clone(&self.0);
+
+        // Create pin-initializer that initializes list and allocates blocks.
+        let init = try_pin_init!(AllocatedBlocks {
+            buddy: Arc::clone(&buddy_arc),
+            list <- CListHead::new(),
+            flags: params.buddy_flags,
+            _: {
+                // Lock while allocating to serialize with concurrent frees.
+                let guard = buddy.lock();
+
+                // SAFETY: `guard` provides exclusive access to the buddy allocator.
+                to_result(unsafe {
+                    bindings::gpu_buddy_alloc_blocks(
+                        guard.as_raw(),
+                        params.start_range_address,
+                        params.end_range_address,
+                        params.size_bytes,
+                        params.min_block_size_bytes,
+                        list.as_raw(),
+                        params.buddy_flags.as_raw(),
+                    )
+                })?
+            }
+        });
+
+        Arc::pin_init(init, GFP_KERNEL)
+    }
+}
+
+/// Allocated blocks from the buddy allocator with automatic cleanup.
+///
+/// This structure owns a list of allocated blocks and ensures they are
+/// automatically freed when dropped. Use `iter()` to iterate over all
+/// allocated [`Block`] structures.
+///
+/// # Invariants
+///
+/// - `list` is an initialized, valid list head containing allocated blocks.
+/// - `buddy` references a valid [`GpuBuddyInner`].
+#[pin_data(PinnedDrop)]
+pub struct AllocatedBlocks {
+    #[pin]
+    list: CListHead,
+    buddy: Arc<GpuBuddyInner>,
+    flags: BuddyFlags,
+}
+
+impl AllocatedBlocks {
+    /// Check if the block list is empty.
+    pub fn is_empty(&self) -> bool {
+        // An empty list head points to itself.
+        !self.list.is_linked()
+    }
+
+    /// Iterate over allocated blocks.
+    ///
+    /// Returns an iterator yielding [`AllocatedBlock`] references. The blocks
+    /// are only valid for the duration of the borrow of `self`.
+    pub fn iter(&self) -> impl Iterator<Item = AllocatedBlock<'_>> + '_ {
+        // SAFETY: list contains gpu_buddy_block items linked via __bindgen_anon_1.link.
+        let clist = unsafe {
+            clist_create!(
+                self.list.as_raw(),
+                Block,
+                bindings::gpu_buddy_block,
+                __bindgen_anon_1.link
+            )
+        };
+
+        clist
+            .iter()
+            .map(|block| AllocatedBlock { block, alloc: self })
+    }
+}
+
+#[pinned_drop]
+impl PinnedDrop for AllocatedBlocks {
+    fn drop(self: Pin<&mut Self>) {
+        let guard = self.buddy.lock();
+
+        // SAFETY:
+        // - list is valid per the type's invariants.
+        // - guard provides exclusive access to the allocator.
+        // CAST: BuddyFlags were validated to fit in u32 at construction.
+        unsafe {
+            bindings::gpu_buddy_free_list(
+                guard.as_raw(),
+                self.list.as_raw(),
+                self.flags.as_raw() as u32,
+            );
+        }
+    }
+}
+
+/// A GPU buddy block.
+///
+/// Transparent wrapper over C `gpu_buddy_block` structure. This type is returned
+/// as references from [`CListIter`] during iteration over [`AllocatedBlocks`].
+///
+/// # Invariants
+///
+/// The inner [`Opaque`] contains a valid, allocated `gpu_buddy_block`.
+#[repr(transparent)]
+pub struct Block(Opaque<bindings::gpu_buddy_block>);
+
+impl Block {
+    /// Get a raw pointer to the underlying C block.
+    fn as_raw(&self) -> *mut bindings::gpu_buddy_block {
+        self.0.get()
+    }
+
+    /// Get the block's offset in the address space.
+    pub(crate) fn offset(&self) -> u64 {
+        // SAFETY: self.as_raw() is valid per the type's invariants.
+        unsafe { bindings::gpu_buddy_block_offset(self.as_raw()) }
+    }
+
+    /// Get the block order.
+    pub(crate) fn order(&self) -> u32 {
+        // SAFETY: self.as_raw() is valid per the type's invariants.
+        unsafe { bindings::gpu_buddy_block_order(self.as_raw()) }
+    }
+}
+
+// SAFETY: `Block` is a transparent wrapper over `gpu_buddy_block` which is not
+// modified after allocation. It can be safely sent between threads.
+unsafe impl Send for Block {}
+
+// SAFETY: `Block` is a transparent wrapper over `gpu_buddy_block` which is not
+// modified after allocation. It can be safely shared among threads.
+unsafe impl Sync for Block {}
+
+/// An allocated block with access to the allocation list.
+///
+/// # Invariants
+///
+/// - `block` is a valid reference to an allocated [`Block`].
+/// - `alloc` is a valid reference to the [`AllocatedBlocks`] that owns this block.
+pub struct AllocatedBlock<'a> {
+    block: &'a Block,
+    alloc: &'a AllocatedBlocks,
+}
+
+impl AllocatedBlock<'_> {
+    /// Get the block's offset in the address space.
+    ///
+    /// Returns the absolute offset including the allocator's base offset.
+    /// This is the actual address to use for accessing the allocated memory.
+    pub fn offset(&self) -> u64 {
+        self.alloc.buddy.base_offset + self.block.offset()
+    }
+
+    /// Get the block order (size = chunk_size << order).
+    pub fn order(&self) -> u32 {
+        self.block.order()
+    }
+
+    /// Get the block's size in bytes.
+    pub fn size(&self) -> u64 {
+        self.alloc.buddy.chunk_size << self.block.order()
+    }
+}
diff --git a/rust/kernel/gpu/mod.rs b/rust/kernel/gpu/mod.rs
new file mode 100644
index 000000000000..8f25e6367edc
--- /dev/null
+++ b/rust/kernel/gpu/mod.rs
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! GPU subsystem abstractions.
+
+pub mod buddy;
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index fe711d34ca1e..02ec5b9b22c8 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -98,6 +98,8 @@
 pub mod firmware;
 pub mod fmt;
 pub mod fs;
+#[cfg(CONFIG_GPU_BUDDY)]
+pub mod gpu;
 #[cfg(CONFIG_I2C = "y")]
 pub mod i2c;
 pub mod id_pool;
-- 
2.34.1


^ permalink raw reply related

* [PATCH -next v8 3/3] nova-core: mm: Select GPU_BUDDY for VRAM allocation
From: Joel Fernandes @ 2026-02-09 21:42 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, joel, nouveau, dri-devel,
	rust-for-linux, linux-doc, amd-gfx, intel-gfx, intel-xe,
	linux-fbdev, Joel Fernandes
In-Reply-To: <20260209214246.2783990-1-joelagnelf@nvidia.com>

nova-core will use the GPU buddy allocator for physical VRAM management.
Enable it in Kconfig.

Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
---
 drivers/gpu/nova-core/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/nova-core/Kconfig b/drivers/gpu/nova-core/Kconfig
index 527920f9c4d3..c129764daa23 100644
--- a/drivers/gpu/nova-core/Kconfig
+++ b/drivers/gpu/nova-core/Kconfig
@@ -3,6 +3,7 @@ config NOVA_CORE
 	depends on 64BIT
 	depends on PCI
 	depends on RUST
+	select GPU_BUDDY
 	select RUST_FW_LOADER_ABSTRACTIONS
 	select AUXILIARY_BUS
 	default n
-- 
2.34.1


^ permalink raw reply related

* [PATCH -next v8 1/3] rust: clist: Add support to interface with C linked lists
From: Joel Fernandes @ 2026-02-09 21:42 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, joel, nouveau, dri-devel,
	rust-for-linux, linux-doc, amd-gfx, intel-gfx, intel-xe,
	linux-fbdev, Joel Fernandes
In-Reply-To: <20260209214246.2783990-1-joelagnelf@nvidia.com>

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.

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 900fc00b73e6..310bb479260c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -23204,6 +23204,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.
+ */
+
+#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);
+//! #     }
+//! # }
+//!
+//! // 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) };
+//!
+//! // 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.
+        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 }
+    }
+
+    /// 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 {}
+
+// 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> {}
+
+/// 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() }
+    }
+
+    /// 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> {
+        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)
+    }};
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 3da92f18f4ee..fe711d34ca1e 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -75,6 +75,7 @@
 pub mod bug;
 #[doc(hidden)]
 pub mod build_assert;
+pub mod clist;
 pub mod clk;
 #[cfg(CONFIG_CONFIGFS_FS)]
 pub mod configfs;
-- 
2.34.1


^ permalink raw reply related

* [PATCH -next v8 0/3] rust: Add CList and GPU buddy allocator bindings
From: Joel Fernandes @ 2026-02-09 21:42 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, joel, nouveau, dri-devel,
	rust-for-linux, linux-doc, amd-gfx, intel-gfx, intel-xe,
	linux-fbdev, Joel Fernandes

Changes from v7 to v8:

his series provides Rust infrastructure needed for nova-core memory management.
CList module for interfacing with linked lists, GPU buddy allocator bindings
for physical memory management in nova-core and nova-core Kconfig change to
select GPU_BUDDY.

The clist patch (patch 1) is independent and go through any tree. The other 2
patches depend on the DRM buddy code movement patch as a prerequisite, a
version of which is now in drm-misc-next:
https://lore.kernel.org/all/20260206003451.1914130-1-joelagnelf@nvidia.com/

Based on linux-next.

v7->v8:
Various changes suggested by Danilo, Gary, Daniel. Added tags.
Link to v7: https://lore.kernel.org/all/20260206004110.1914814-1-joelagnelf@nvidia.com/

Joel Fernandes (3):
  rust: clist: Add support to interface with C linked lists
  rust: gpu: Add GPU buddy allocator bindings
  nova-core: mm: Select GPU_BUDDY for VRAM allocation

 MAINTAINERS                     |   7 +
 drivers/gpu/nova-core/Kconfig   |   1 +
 rust/bindings/bindings_helper.h |  11 +
 rust/helpers/gpu.c              |  23 ++
 rust/helpers/helpers.c          |   2 +
 rust/helpers/list.c             |  17 +
 rust/kernel/clist.rs            | 320 +++++++++++++++++++
 rust/kernel/gpu/buddy.rs        | 530 ++++++++++++++++++++++++++++++++
 rust/kernel/gpu/mod.rs          |   5 +
 rust/kernel/lib.rs              |   3 +
 10 files changed, 919 insertions(+)
 create mode 100644 rust/helpers/gpu.c
 create mode 100644 rust/helpers/list.c
 create mode 100644 rust/kernel/clist.rs
 create mode 100644 rust/kernel/gpu/buddy.rs
 create mode 100644 rust/kernel/gpu/mod.rs

-- 
2.34.1


^ permalink raw reply

* Re: [PATCH] fbcon: Remove struct fbcon_display.inverse
From: Helge Deller @ 2026-02-09 21:31 UTC (permalink / raw)
  To: Thomas Zimmermann, geert; +Cc: linux-fbdev, dri-devel, stable
In-Reply-To: <20260209161609.251510-1-tzimmermann@suse.de>

On 2/9/26 17:15, Thomas Zimmermann wrote:
> The field inverse in struct fbcon_display is unused. Remove it.

Indeed, seems to be unused.
  
> The field apparently never did anything. Commit c7ef5e285c84 ("video:
> fbdev: atari: Fix inverse handling") converted its final user to call
> fb_invert_cmaps() instead.

That commit seems not to be related, as it touches a static
inverse variable inside the atafb driver only.
Commit e4fc27618b75 (from 2005) touched it last time, but it seems even older.

Patch applied to fbdev, but I dropped the wrong commit reference in the
commit message.

Thanks!
Helge

> Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
> Fixes: c7ef5e285c84 ("video: fbdev: atari: Fix inverse handling")
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Helge Deller <deller@gmx.de>
> Cc: <stable@vger.kernel.org> # v6.0+
> ---
>   drivers/video/fbdev/core/fbcon.h | 1 -
>   1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
> index 1cd10a7faab0..fca14e9b729b 100644
> --- a/drivers/video/fbdev/core/fbcon.h
> +++ b/drivers/video/fbdev/core/fbcon.h
> @@ -30,7 +30,6 @@ struct fbcon_display {
>   #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
>       u_short scrollmode;             /* Scroll Method, use fb_scrollmode() */
>   #endif
> -    u_short inverse;                /* != 0 text black on white as default */
>       short yscroll;                  /* Hardware scrolling */
>       int vrows;                      /* number of virtual rows */
>       int cursor_shape;


^ permalink raw reply

* Re: [PATCH -next v7 1/2] rust: clist: Add support to interface with C linked lists
From: Joel Fernandes @ 2026-02-09 19:42 UTC (permalink / raw)
  To: Daniel Almeida, Danilo Krummrich
  Cc: Gary Guo, linux-kernel, 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, Alice Ryhl, Miguel Ojeda, Alex Gaynor, Boqun Feng,
	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, joel,
	nouveau, dri-devel, rust-for-linux, linux-doc, amd-gfx, intel-gfx,
	intel-xe, linux-fbdev
In-Reply-To: <31AAAF36-093A-46CF-AEEA-709CB1DE1E81@collabora.com>



On 2/6/2026 4:30 PM, Daniel Almeida wrote:
> 
> 
>> On 6 Feb 2026, at 14:27, Danilo Krummrich <dakr@kernel.org> wrote:
>>
>> On Fri Feb 6, 2026 at 6:20 PM CET, Gary Guo wrote:
>>> I asked for this to be changed to `pub(crate)` because I think this isn't
>>> something that should be used by drivers.
>>>
>>> As you said, tt might be tricky to enforce that with new build system when
>>> subsystems are inside different crates. But until then I think it's better to
>>> limit visibility.
>>
>> It should *usually* not be used by drivers, but there are exceptions. For
>> instance, it is perfectly valid to be used by Rust drivers that interact with C
>> drivers.
> 
> I agree with what Danilo said here.
> 
> I don’t see a reason to forbid drivers from using this. If the reason is
> the unsafe bits, then isn’t it the same pattern used by impl_has_work!()
> anyways? i.e.: a macro that implements an unsafe trait so long as the driver
> gives it the right Work field. Seems equivalent in spirit to the clist_create macro
> introduced by this patch.
> 

Thank you for this suggestion. As I discussed on the other thread, I think the
consensus is to change the module level to "pub" and all the items in it to
"pub" as well. So I will do so.

-- 
Joel Fernandes


^ permalink raw reply

* Re: [PATCH -next v7 1/2] rust: clist: Add support to interface with C linked lists
From: Joel Fernandes @ 2026-02-09 19:41 UTC (permalink / raw)
  To: Gary Guo, 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, 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, joel, nouveau, dri-devel, rust-for-linux,
	linux-doc, amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <DG7ZF1UT98RQ.3F42J3ULGV2OC@garyguo.net>



On 2/6/2026 10:25 AM, Gary Guo wrote:
> On Fri Feb 6, 2026 at 12:41 AM GMT, 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.
>>
>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>> ---
>>  MAINTAINERS            |   7 +
>>  drivers/gpu/Kconfig    |   7 +
>>  rust/helpers/helpers.c |   1 +
>>  rust/helpers/list.c    |  21 +++
>>  rust/kernel/clist.rs   | 315 +++++++++++++++++++++++++++++++++++++++++
>>  rust/kernel/lib.rs     |   2 +
>>  6 files changed, 353 insertions(+)
>>  create mode 100644 rust/helpers/list.c
>>  create mode 100644 rust/kernel/clist.rs
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 900fc00b73e6..310bb479260c 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -23204,6 +23204,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
> 
> I still think we should try to work on a more powerful list infra that works for
> both C and Rust, but I reckon that is a longer term effort, and shouldn't
> prevent a simpler version from getting in and be used by abstractions that need
> it. So
> 
> Acked-by: Gary Guo <gary@garyguo.net>

Thanks! I also replied below.

> 
> Some nits below:
> 
>> +
>>  RXRPC SOCKETS (AF_RXRPC)
>>  M:	David Howells <dhowells@redhat.com>
>>  M:	Marc Dionne <marc.dionne@auristor.com>
>> diff --git a/drivers/gpu/Kconfig b/drivers/gpu/Kconfig
>> index 22dd29cd50b5..2c3dec070645 100644
>> --- a/drivers/gpu/Kconfig
>> +++ b/drivers/gpu/Kconfig
>> @@ -1,7 +1,14 @@
>>  # SPDX-License-Identifier: GPL-2.0
>>  
>> +config RUST_CLIST
>> +	bool
>> +	depends on RUST
>> +	help
>> +	  Rust abstraction for interfacing with C linked lists.
> 
> I am not sure if we need extra config entry. This is fully generic so shouldn't
> generate any code unless there is an user.

Yes, I am dropping it now. As per the other discussions, I will change the
module level and all the items in the module to pub. And then we will not need
this config.

> 
>> +
>>  config GPU_BUDDY
>>  	bool
>> +	select RUST_CLIST if RUST
>>  	help
>>  	  A page based buddy allocator for GPU memory.
>>  
>> 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..3390b154fa36
>> --- /dev/null
>> +++ b/rust/helpers/list.c
>> @@ -0,0 +1,21 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +/*
>> + * Helpers for C Circular doubly linked list implementation.
>> + */
>> +
>> +#include <linux/list.h>
>> +
>> +#ifndef __rust_helper
>> +#define __rust_helper
>> +#endif
> 
> This shouldn't be needed.

I had to add this because a patch was missing in the DRM tree it depended on. I
believe I should not need it anymore, so I will drop it. Thank you for pointing
that out.
>> +
>> +__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..1f6d4db13c1d
>> --- /dev/null
>> +++ b/rust/kernel/clist.rs
>> @@ -0,0 +1,315 @@
>> +// 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(crate) 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;
>> +//! #         // addr_of_mut!() computes address of link directly as link is uninitialized.
>> +//! #         bindings::INIT_LIST_HEAD(core::ptr::addr_of_mut!((*ptr).link));
>> +//! #         bindings::list_add_tail(&mut (*ptr).link, head);
>> +//! #     }
>> +//! # }
>> +//!
>> +//! // 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(crate) struct Item(Opaque<SampleItemC>);
>> +//!
>> +//! impl Item {
>> +//!     pub(crate) 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) };
>> +//!
>> +//! // 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::PinInit;
>> +
>> +/// Wraps a `list_head` object for use in intrusive linked lists.
>> +///
>> +/// # Invariants
>> +///
>> +/// - [`CListHead`] represents an allocated and valid `list_head` structure.
>> +/// - Once a [`CListHead`] is created in Rust, it will not be modified by non-Rust code.
>> +/// - All `list_head` for individual items are not modified for the lifetime of [`CListHead`].
>> +#[repr(transparent)]
>> +pub(crate) struct CListHead(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`.
>> +    #[inline]
>> +    pub(crate) 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.
>> +        unsafe { &*ptr.cast() }
>> +    }
>> +
>> +    /// Get the raw `list_head` pointer.
>> +    #[inline]
>> +    pub(crate) fn as_raw(&self) -> *mut bindings::list_head {
>> +        self.0.get()
>> +    }
>> +
>> +    /// Get the next [`CListHead`] in the list.
>> +    #[inline]
>> +    pub(crate) 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.
>> +        unsafe { Self::from_raw((*raw).next) }
>> +    }
>> +
>> +    /// Check if this node is linked in a list (not isolated).
>> +    #[inline]
>> +    pub(crate) 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 }
>> +    }
>> +
>> +    /// Pin-initializer that initializes the list head.
>> +    pub(crate) fn new() -> impl PinInit<Self> {
>> +        // SAFETY: `INIT_LIST_HEAD` initializes `slot` to a valid empty list.
>> +        unsafe {
>> +            pin_init::pin_init_from_closure(move |slot: *mut Self| {
> 
> pin_init::ffi_init should be used for this.
> 

Will do, thanks.

>> +                bindings::INIT_LIST_HEAD(slot.cast());
>> +                Ok(())
>> +            })
>> +        }
>> +    }
>> +}
>> +
>> +// SAFETY: [`CListHead`] can be sent to any thread.
>> +unsafe impl Send for CListHead {}
>> +
>> +// SAFETY: [`CListHead`] can be shared among threads as it is not modified
>> +// by non-Rust code per type invariants.
>> +unsafe impl Sync for CListHead {}
>> +
>> +impl PartialEq for CListHead {
> 
> #[inline]

Will do.

Thanks,
-- 
Joel Fernandes


^ permalink raw reply

* Re: [PATCH -next] gpu: Move DRM buddy allocator one level up
From: Joel Fernandes @ 2026-02-09 19:30 UTC (permalink / raw)
  To: Dave Airlie
  Cc: linux-kernel, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	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, Alexey Ivanov, Balbir Singh,
	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: <CAPM=9tw=jzQxGvVrsUSv14RxQtnaw2rH6K2b3Gxh_UUHnOGTkA@mail.gmail.com>



On 2/5/2026 8:48 PM, Dave Airlie wrote:
> On Fri, 6 Feb 2026 at 11:06, Joel Fernandes <joelagnelf@nvidia.com> wrote:
>>
>>
>>
>> On 2/5/2026 7:34 PM, 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.
>>>
>>> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
>>
>> I forgot to add Dave Airlie's review tag here from his other email. When you
>> apply, could you add it?
>>
>> Or, let me know if I should resend it. Thanks.
>>
> 
> This one was a bit messy, so I've taken this into drm-misc-next now,
> it doesn't quite end up in the same places as yours, but it looks the
> same, and I updated MAINTAINERS at the end.
> 
> Now you can just care about the rust side of it.

Nit: I think you used spaces instead of tabs in drivers/gpu/Kconfig? Suggest
changing to tabs to keep it consistent.

Otherwise it LGTM, thanks for adapting it to the tree!

-- 
Joel Fernandes


^ permalink raw reply

* Re: [PATCH -next v7 1/2] rust: clist: Add support to interface with C linked lists
From: Joel Fernandes @ 2026-02-09 17:02 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: linux-kernel, 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, joel, nouveau, dri-devel, rust-for-linux, linux-doc,
	amd-gfx, intel-gfx, intel-xe, linux-fbdev
In-Reply-To: <4A87E3FC-6A04-4A92-9230-4782D75FC05F@collabora.com>



On 2/6/2026 5:33 PM, Daniel Almeida wrote:
>>>
>>>
>>> Yeah, but my point being: is there a reason why the underlying list has to
>>> remain read-only? Is this a safety requirement or an invariant that is established
>>> by the code above?
>> I'm not fully sure if it's an invariant or a safety requirement, but anyone
>> creating a C list head on the rust side must guarantee that it is not modified.
>> Since rust has no visibility on the C side, I believe it is a Rust invariant
>> here that the existence of CListHead assumes that the list cannot be modified
>> once Rust has access over it.  That is up to the creator (user) of the CListHead
>> to guarantee. In the DRM buddy case, once the list is allocated and accessible
>> from Rust, C code will not modify it while the Rust object exists.
>>
>> Does that make sense, or is there a better way to document this?
>>
>> --
>> Joel Fernandes
> 
> 
> In which case, I recommend moving this to a safety requirement when
> creating the list.

Ok, will do.
> I assume the purpose of not modifying the list on the C side is to avoid
> corrupting the list in Rust somehow?

Yes.

Thanks,

-- 
Joel Fernandes


^ permalink raw reply

* [PATCH] fbcon: Remove struct fbcon_display.inverse
From: Thomas Zimmermann @ 2026-02-09 16:15 UTC (permalink / raw)
  To: deller, geert; +Cc: linux-fbdev, dri-devel, Thomas Zimmermann, stable

The field inverse in struct fbcon_display is unused. Remove it.

The field apparently never did anything. Commit c7ef5e285c84 ("video:
fbdev: atari: Fix inverse handling") converted its final user to call
fb_invert_cmaps() instead.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: c7ef5e285c84 ("video: fbdev: atari: Fix inverse handling")
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Helge Deller <deller@gmx.de>
Cc: <stable@vger.kernel.org> # v6.0+
---
 drivers/video/fbdev/core/fbcon.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index 1cd10a7faab0..fca14e9b729b 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -30,7 +30,6 @@ struct fbcon_display {
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
     u_short scrollmode;             /* Scroll Method, use fb_scrollmode() */
 #endif
-    u_short inverse;                /* != 0 text black on white as default */
     short yscroll;                  /* Hardware scrolling */
     int vrows;                      /* number of virtual rows */
     int cursor_shape;
-- 
2.52.0


^ permalink raw reply related

* Re: [PATCH v3 5/6] fbdev: au1100fb: Make driver compilable on non-mips platforms
From: kernel test robot @ 2026-02-09  9:16 UTC (permalink / raw)
  To: Uwe Kleine-König, Helge Deller
  Cc: oe-kbuild-all, Chen Ni, linux-fbdev, dri-devel
In-Reply-To: <67b7aa0157b9cf5de111ab6b2725d207ec98aae9.1770572936.git.u.kleine-koenig@baylibre.com>

Hi Uwe,

kernel test robot noticed the following build errors:

[auto build test ERROR on 0636e6205beed850d985276dc56fd73d785bea5c]

url:    https://github.com/intel-lab-lkp/linux/commits/Uwe-Kleine-K-nig/fbdev-au1100fb-Don-t-store-device-specific-data-in-global-variables/20260209-015956
base:   0636e6205beed850d985276dc56fd73d785bea5c
patch link:    https://lore.kernel.org/r/67b7aa0157b9cf5de111ab6b2725d207ec98aae9.1770572936.git.u.kleine-koenig%40baylibre.com
patch subject: [PATCH v3 5/6] fbdev: au1100fb: Make driver compilable on non-mips platforms
config: um-randconfig-r072-20260209 (https://download.01.org/0day-ci/archive/20260209/202602091743.HcmQ4SB4-lkp@intel.com/config)
compiler: gcc-13 (Debian 13.3.0-16) 13.3.0
smatch version: v0.5.0-8994-gd50c5a4c
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260209/202602091743.HcmQ4SB4-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/202602091743.HcmQ4SB4-lkp@intel.com/

All errors (new ones prefixed by >>):

   /usr/bin/ld: drivers/video/fbdev/au1100fb.o: in function `au1100fb_setup':
>> drivers/video/fbdev/au1100fb.c:371:(.text+0x1ff): undefined reference to `fb_get_options'
   /usr/bin/ld: drivers/video/fbdev/au1100fb.o: in function `au1100fb_drv_probe':
>> drivers/video/fbdev/au1100fb.c:499:(.text+0xa7e): undefined reference to `fb_alloc_cmap'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.c:509:(.text+0xac2): undefined reference to `register_framebuffer'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.c:522:(.text+0xb3e): undefined reference to `fb_dealloc_cmap'
   /usr/bin/ld: drivers/video/fbdev/au1100fb.o: in function `au1100fb_drv_remove':
>> drivers/video/fbdev/au1100fb.c:540:(.text+0xb73): undefined reference to `unregister_framebuffer'
   /usr/bin/ld: drivers/video/fbdev/au1100fb.c:542:(.text+0xb86): undefined reference to `fb_dealloc_cmap'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.o:(.rodata+0x18): undefined reference to `fb_io_read'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.o:(.rodata+0x20): undefined reference to `fb_io_write'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.o:(.rodata+0x58): undefined reference to `cfb_fillrect'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.o:(.rodata+0x60): undefined reference to `cfb_copyarea'
>> /usr/bin/ld: drivers/video/fbdev/au1100fb.o:(.rodata+0x68): undefined reference to `cfb_imageblit'
   collect2: error: ld returned 1 exit status


vim +371 drivers/video/fbdev/au1100fb.c

^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  360  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  361  static int au1100fb_setup(struct au1100fb_device *fbdev)
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  362  {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  363  	char *this_opt, *options;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  364  	int num_panels = ARRAY_SIZE(known_lcd_panels);
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  365  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  366  	if (num_panels <= 0) {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  367  		print_err("No LCD panels supported by driver!");
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  368  		return -ENODEV;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  369  	}
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  370  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30 @371  	if (fb_get_options(DRIVER_NAME, &options))
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  372  		return -ENODEV;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  373  	if (!options)
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  374  		return -ENODEV;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  375  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  376  	while ((this_opt = strsep(&options, ",")) != NULL) {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  377  		/* Panel option */
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  378  		if (!strncmp(this_opt, "panel:", 6)) {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  379  			int i;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  380  			this_opt += 6;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  381  			for (i = 0; i < num_panels; i++) {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  382  				if (!strncmp(this_opt, known_lcd_panels[i].name,
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  383  					     strlen(this_opt))) {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  384  					fbdev->panel = &known_lcd_panels[i];
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  385  					fbdev->panel_idx = i;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  386  					break;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  387  				}
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  388  			}
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  389  			if (i >= num_panels) {
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  390  				print_warn("Panel '%s' not supported!", this_opt);
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  391  				return -ENODEV;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  392  			}
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  393  		}
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  394  		/* Unsupported option */
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  395  		else
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  396  			print_warn("Unsupported option \"%s\"", this_opt);
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  397  	}
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  398  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  399  	print_info("Panel=%s", fbdev->panel->name);
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  400  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  401  	return 0;
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  402  }
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  403  
48c68c4f1b5424 drivers/video/au1100fb.c       Greg Kroah-Hartman 2012-12-21  404  static int au1100fb_drv_probe(struct platform_device *dev)
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  405  {
46953e6aab262d drivers/video/fbdev/au1100fb.c Markus Elfring     2018-03-28  406  	struct au1100fb_device *fbdev;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  407  	struct resource *regs_res;
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  408  	struct clk *c;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  409  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  410  	/* Allocate new device private */
db66f0252e2f17 drivers/video/fbdev/au1100fb.c Markus Elfring     2018-03-28  411  	fbdev = devm_kzalloc(&dev->dev, sizeof(*fbdev), GFP_KERNEL);
29914badc59b23 drivers/video/fbdev/au1100fb.c Markus Elfring     2018-03-28  412  	if (!fbdev)
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  413  		return -ENOMEM;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  414  
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  415  	if (au1100fb_setup(fbdev))
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  416  		goto failed;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  417  
7a192ec334cab9 drivers/video/au1100fb.c       Ming Lei           2009-02-06  418  	platform_set_drvdata(dev, (void *)fbdev);
67f30ad19c4b32 drivers/video/fbdev/au1100fb.c Christoph Hellwig  2019-04-28  419  	fbdev->dev = &dev->dev;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  420  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  421  	/* Allocate region for our registers and map them */
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  422  	regs_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
d121c3f3cedb84 drivers/video/au1100fb.c       Manuel Lauss       2011-09-30  423  	if (!regs_res) {
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  424  		print_err("fail to retrieve registers resource");
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  425  		return -EFAULT;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  426  	}
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  427  
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  428  	fbdev->info.fix = (struct fb_fix_screeninfo) {
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  429  		.mmio_start = regs_res->start,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  430  		.mmio_len = resource_size(regs_res),
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  431  		.id = "AU1100 FB",
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  432  		.xpanstep = 1,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  433  		.ypanstep = 1,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  434  		.type = FB_TYPE_PACKED_PIXELS,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  435  		.accel = FB_ACCEL_NONE,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  436  	};
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  437  
93019734555f8d drivers/video/au1100fb.c       Manuel Lauss       2012-03-24  438  	if (!devm_request_mem_region(&dev->dev,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  439  				     fbdev->info.fix.mmio_start,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  440  				     fbdev->info.fix.mmio_len,
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  441  				     DRIVER_NAME)) {
c05b7f3d12b945 drivers/video/au1100fb.c       Rodolfo Giometti   2006-05-30  442  		print_err("fail to lock memory region at 0x%08lx",
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  443  			  fbdev->info.fix.mmio_start);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  444  		return -EBUSY;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  445  	}
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  446  
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  447  	fbdev->regs = (struct au1100fb_regs*)KSEG1ADDR(fbdev->info.fix.mmio_start);
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  448  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  449  	print_dbg("Register memory map at %p", fbdev->regs);
deee40d267c04a drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  450  	print_dbg("phys=0x%08x, size=%zu", fbdev->regs_phys, fbdev->regs_len);
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  451  
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  452  	c = clk_get(NULL, "lcd_intclk");
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  453  	if (!IS_ERR(c)) {
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  454  		fbdev->lcdclk = c;
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  455  		clk_set_rate(c, 48000000);
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  456  		clk_prepare_enable(c);
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  457  	}
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  458  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  459  	/* Allocate the framebuffer to the maximum screen size * nbr of video buffers */
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  460  	fbdev->fb_len = fbdev->panel->xres * fbdev->panel->yres *
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  461  		  	(fbdev->panel->bpp >> 3) * AU1100FB_NBR_VIDEO_BUFFERS;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  462  
93019734555f8d drivers/video/au1100fb.c       Manuel Lauss       2012-03-24  463  	fbdev->fb_mem = dmam_alloc_coherent(&dev->dev,
1c16697bf9d5b2 drivers/video/au1100fb.c       Julia Lawall       2012-01-21  464  					    PAGE_ALIGN(fbdev->fb_len),
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  465  					    &fbdev->fb_phys, GFP_KERNEL);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  466  	if (!fbdev->fb_mem) {
deee40d267c04a drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  467  		print_err("fail to allocate framebuffer (size: %zuK))",
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  468  			  fbdev->fb_len / 1024);
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  469  		return -ENOMEM;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  470  	}
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  471  
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  472  	fbdev->info.fix.smem_start = fbdev->fb_phys;
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  473  	fbdev->info.fix.smem_len = fbdev->fb_len;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  474  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  475  	print_dbg("Framebuffer memory map at %p", fbdev->fb_mem);
8a19e8c9c05d78 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  476  	print_dbg("phys=0x%pad, size=%zuK", &fbdev->fb_phys, fbdev->fb_len / 1024);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  477  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  478  	/* load the panel info into the var struct */
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  479  	fbdev->info.var = (struct fb_var_screeninfo) {
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  480  		.activate = FB_ACTIVATE_NOW,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  481  		.height = -1,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  482  		.width = -1,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  483  		.vmode = FB_VMODE_NONINTERLACED,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  484  		.bits_per_pixel = fbdev->panel->bpp,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  485  		.xres = fbdev->panel->xres,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  486  		.xres_virtual = fbdev->panel->xres,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  487  		.yres = fbdev->panel->yres,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  488  		.yres_virtual = fbdev->panel->yres,
0938c7cf68c618 drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  489  	};
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  490  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  491  	fbdev->info.screen_base = fbdev->fb_mem;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  492  	fbdev->info.fbops = &au1100fb_ops;
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  493  
1c16697bf9d5b2 drivers/video/au1100fb.c       Julia Lawall       2012-01-21  494  	fbdev->info.pseudo_palette =
a86854d0c599b3 drivers/video/fbdev/au1100fb.c Kees Cook          2018-06-12  495  		devm_kcalloc(&dev->dev, 16, sizeof(u32), GFP_KERNEL);
1c16697bf9d5b2 drivers/video/au1100fb.c       Julia Lawall       2012-01-21  496  	if (!fbdev->info.pseudo_palette)
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  497  		return -ENOMEM;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  498  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04 @499  	if (fb_alloc_cmap(&fbdev->info.cmap, AU1100_LCD_NBR_PALETTE_ENTRIES, 0) < 0) {
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  500  		print_err("Fail to allocate colormap (%d entries)",
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  501  			   AU1100_LCD_NBR_PALETTE_ENTRIES);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  502  		return -EFAULT;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  503  	}
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  504  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  505  	/* Set h/w registers */
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  506  	au1100fb_setmode(fbdev);
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  507  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  508  	/* Register new framebuffer */
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04 @509  	if (register_framebuffer(&fbdev->info) < 0) {
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  510  		print_err("cannot register new framebuffer");
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  511  		goto failed;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  512  	}
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  513  
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  514  	return 0;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  515  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  516  failed:
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  517  	if (fbdev->lcdclk) {
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  518  		clk_disable_unprepare(fbdev->lcdclk);
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  519  		clk_put(fbdev->lcdclk);
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  520  	}
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  521  	if (fbdev->info.cmap.len != 0) {
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04 @522  		fb_dealloc_cmap(&fbdev->info.cmap);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  523  	}
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  524  
1c16697bf9d5b2 drivers/video/au1100fb.c       Julia Lawall       2012-01-21  525  	return -ENODEV;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  526  }
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  527  
65ead1cf1fc59b drivers/video/fbdev/au1100fb.c Uwe Kleine-König   2026-02-08  528  static void au1100fb_drv_remove(struct platform_device *dev)
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  529  {
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  530  	struct au1100fb_device *fbdev = NULL;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  531  
5a7bbe86b0b99b drivers/video/au1100fb.c       Jingoo Han         2013-09-09  532  	fbdev = platform_get_drvdata(dev);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  533  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  534  #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO)
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  535  	au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  536  #endif
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  537  	fbdev->regs->lcd_control &= ~LCD_CONTROL_GO;
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  538  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  539  	/* Clean up all probe data */
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04 @540  	unregister_framebuffer(&fbdev->info);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  541  
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  542  	fb_dealloc_cmap(&fbdev->info.cmap);
3b495f2bb749b8 drivers/video/au1100fb.c       Pete Popov         2005-04-04  543  
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  544  	if (fbdev->lcdclk) {
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  545  		clk_disable_unprepare(fbdev->lcdclk);
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  546  		clk_put(fbdev->lcdclk);
6b1889c14b4606 drivers/video/fbdev/au1100fb.c Manuel Lauss       2014-07-23  547  	}
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  548  }
^1da177e4c3f41 drivers/video/au1100fb.c       Linus Torvalds     2005-04-16  549  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [PATCH] arch: m68k: remove incomplete, unusable Apollo hardware support
From: Thomas Zimmermann @ 2026-02-09  8:14 UTC (permalink / raw)
  To: Ethan Nelson-Moore, linux-m68k, linux-fbdev
  Cc: Geert Uytterhoeven, Helge Deller, Jiri Slaby (SUSE),
	Ilpo Järvinen, Greg Kroah-Hartman, Eric Biggers, Herbert Xu,
	Thomas Huth, Greg Ungerer, Finn Thain, Thorsten Blum,
	Jean-Michel Hautbois, Kees Cook, Wei Liu, Prasanna Kumar T S M,
	Sukrut Heroorkar
In-Reply-To: <20260209005212.32370-1-enelsonmoore@gmail.com>



Am 09.02.26 um 01:51 schrieb Ethan Nelson-Moore:
> The m68k architecture contains very incomplete support for running on
> Apollo Domain hardware. There are only timer, console, and framebuffer
> drivers, and no storage or network drivers, so there is no way to
> practically use it. It is not even capable of rebooting by itself (see
> dn_dummy_reset() in arch/m68k/apollo/config.c).
>
> arch/m68k/apollo has only received tree-wide changes and fixes by
> inspection in the entire Git history (since Linux 2.6.12-rc2), so there
> is clearly no interest in completing support for Apollo hardware.
> Remove it to reduce future maintenance workload.
>
> There are no uses of the removed <asm/bootinfo-apollo.h> UAPI header or
> the constants removed from the <asm/bootinfo.h> UAPI header on GitHub
> or Debian Code Search.
>
> Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
> ---
>   arch/m68k/Kbuild                             |   1 -
>   arch/m68k/Kconfig.devices                    |   4 +-
>   arch/m68k/Kconfig.machine                    |   8 -
>   arch/m68k/apollo/Makefile                    |   6 -
>   arch/m68k/apollo/apollo.h                    |   4 -
>   arch/m68k/apollo/config.c                    | 240 --------
>   arch/m68k/apollo/dn_ints.c                   |  50 --
>   arch/m68k/configs/apollo_defconfig           | 595 -------------------
>   arch/m68k/configs/multi_defconfig            |   1 -
>   arch/m68k/include/asm/apollohw.h             |  90 ---
>   arch/m68k/include/asm/config.h               |   2 -
>   arch/m68k/include/asm/irq.h                  |   2 -
>   arch/m68k/include/asm/setup.h                |  32 +-
>   arch/m68k/include/uapi/asm/bootinfo-apollo.h |  29 -
>   arch/m68k/include/uapi/asm/bootinfo.h        |   5 +-
>   arch/m68k/kernel/head.S                      |  70 +--
>   arch/m68k/kernel/setup_mm.c                  |   9 -


>   drivers/video/fbdev/Kconfig                  |   8 -
>   drivers/video/fbdev/Makefile                 |   1 -
>   drivers/video/fbdev/dnfb.c                   | 307 ----------

For the framebuffer files:

Acked-by: Thomas Zimmermann <tzimmermann@suse.de>

>   20 files changed, 19 insertions(+), 1445 deletions(-)
>   delete mode 100644 arch/m68k/apollo/Makefile
>   delete mode 100644 arch/m68k/apollo/apollo.h
>   delete mode 100644 arch/m68k/apollo/config.c
>   delete mode 100644 arch/m68k/apollo/dn_ints.c
>   delete mode 100644 arch/m68k/configs/apollo_defconfig
>   delete mode 100644 arch/m68k/include/asm/apollohw.h
>   delete mode 100644 arch/m68k/include/uapi/asm/bootinfo-apollo.h
>   delete mode 100644 drivers/video/fbdev/dnfb.c
>
> diff --git a/arch/m68k/Kbuild b/arch/m68k/Kbuild
> index 7762af9f6def..421bad0780e1 100644
> --- a/arch/m68k/Kbuild
> +++ b/arch/m68k/Kbuild
> @@ -5,7 +5,6 @@ obj-$(CONFIG_AMIGA)		+= amiga/
>   obj-$(CONFIG_ATARI)		+= atari/
>   obj-$(CONFIG_MAC)		+= mac/
>   obj-$(CONFIG_HP300)		+= hp300/
> -obj-$(CONFIG_APOLLO)		+= apollo/
>   obj-$(CONFIG_MVME147)		+= mvme147/
>   obj-$(CONFIG_MVME16x)		+= mvme16x/
>   obj-$(CONFIG_BVME6000)		+= bvme6000/
> diff --git a/arch/m68k/Kconfig.devices b/arch/m68k/Kconfig.devices
> index e6e3efac1840..75370aadba6a 100644
> --- a/arch/m68k/Kconfig.devices
> +++ b/arch/m68k/Kconfig.devices
> @@ -9,8 +9,8 @@ config ARCH_MAY_HAVE_PC_FDC
>   menu "Platform devices"
>   
>   config HEARTBEAT
> -	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || Q40
> -	default y if !AMIGA && !APOLLO && !ATARI && !Q40 && HP300
> +	bool "Use power LED as a heartbeat" if AMIGA || ATARI || Q40
> +	default y if !AMIGA && !ATARI && !Q40 && HP300
>   	help
>   	  Use the power-on LED on your machine as a load meter.  The exact
>   	  behavior is platform-dependent, but normally the flash frequency is
> diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine
> index de39f23b180e..f67eb3d202c6 100644
> --- a/arch/m68k/Kconfig.machine
> +++ b/arch/m68k/Kconfig.machine
> @@ -38,14 +38,6 @@ config MAC
>   	  browse the documentation available at <http://www.mac.linux-m68k.org/>;
>   	  otherwise say N.
>   
> -config APOLLO
> -	bool "Apollo support"
> -	depends on MMU
> -	select LEGACY_TIMER_TICK
> -	help
> -	  Say Y here if you want to run Linux on an MC680x0-based Apollo
> -	  Domain workstation such as the DN3500.
> -
>   config VME
>   	bool "VME (Motorola and BVM) support"
>   	depends on MMU
> diff --git a/arch/m68k/apollo/Makefile b/arch/m68k/apollo/Makefile
> deleted file mode 100644
> index 676c74b26878..000000000000
> --- a/arch/m68k/apollo/Makefile
> +++ /dev/null
> @@ -1,6 +0,0 @@
> -# SPDX-License-Identifier: GPL-2.0-only
> -#
> -# Makefile for Linux arch/m68k/apollo source directory
> -#
> -
> -obj-y		:= config.o dn_ints.o
> diff --git a/arch/m68k/apollo/apollo.h b/arch/m68k/apollo/apollo.h
> deleted file mode 100644
> index 1fe9d856df30..000000000000
> --- a/arch/m68k/apollo/apollo.h
> +++ /dev/null
> @@ -1,4 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -
> -/* dn_ints.c */
> -void dn_init_IRQ(void);
> diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
> deleted file mode 100644
> index e324c5f671de..000000000000
> --- a/arch/m68k/apollo/config.c
> +++ /dev/null
> @@ -1,240 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -#include <linux/init.h>
> -#include <linux/types.h>
> -#include <linux/kernel.h>
> -#include <linux/mm.h>
> -#include <linux/rtc.h>
> -#include <linux/interrupt.h>
> -
> -#include <asm/setup.h>
> -#include <asm/bootinfo.h>
> -#include <asm/bootinfo-apollo.h>
> -#include <asm/byteorder.h>
> -#include <asm/apollohw.h>
> -#include <asm/irq.h>
> -#include <asm/machdep.h>
> -#include <asm/config.h>
> -
> -#include "apollo.h"
> -
> -u_long sio01_physaddr;
> -u_long sio23_physaddr;
> -u_long rtc_physaddr;
> -u_long pica_physaddr;
> -u_long picb_physaddr;
> -u_long cpuctrl_physaddr;
> -u_long timer_physaddr;
> -u_long apollo_model;
> -
> -extern void dn_sched_init(void);
> -extern int dn_dummy_hwclk(int, struct rtc_time *);
> -static void dn_dummy_reset(void);
> -#ifdef CONFIG_HEARTBEAT
> -static void dn_heartbeat(int on);
> -#endif
> -static irqreturn_t dn_timer_int(int irq,void *);
> -static void dn_get_model(char *model);
> -static const char *apollo_models[] = {
> -	[APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)",
> -	[APOLLO_DN3010-APOLLO_DN3000] = "DN3010 (Otter)",
> -	[APOLLO_DN3500-APOLLO_DN3000] = "DN3500 (Cougar II)",
> -	[APOLLO_DN4000-APOLLO_DN3000] = "DN4000 (Mink)",
> -	[APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)"
> -};
> -
> -int __init apollo_parse_bootinfo(const struct bi_record *record)
> -{
> -	int unknown = 0;
> -	const void *data = record->data;
> -
> -	switch (be16_to_cpu(record->tag)) {
> -	case BI_APOLLO_MODEL:
> -		apollo_model = be32_to_cpup(data);
> -		break;
> -
> -	default:
> -		 unknown=1;
> -	}
> -
> -	return unknown;
> -}
> -
> -static void __init dn_setup_model(void)
> -{
> -	pr_info("Apollo hardware found: [%s]\n",
> -		apollo_models[apollo_model - APOLLO_DN3000]);
> -
> -	switch(apollo_model) {
> -		case APOLLO_UNKNOWN:
> -			panic("Unknown apollo model");
> -			break;
> -		case APOLLO_DN3000:
> -		case APOLLO_DN3010:
> -			sio01_physaddr=SAU8_SIO01_PHYSADDR;
> -			rtc_physaddr=SAU8_RTC_PHYSADDR;
> -			pica_physaddr=SAU8_PICA;
> -			picb_physaddr=SAU8_PICB;
> -			cpuctrl_physaddr=SAU8_CPUCTRL;
> -			timer_physaddr=SAU8_TIMER;
> -			break;
> -		case APOLLO_DN4000:
> -			sio01_physaddr=SAU7_SIO01_PHYSADDR;
> -			sio23_physaddr=SAU7_SIO23_PHYSADDR;
> -			rtc_physaddr=SAU7_RTC_PHYSADDR;
> -			pica_physaddr=SAU7_PICA;
> -			picb_physaddr=SAU7_PICB;
> -			cpuctrl_physaddr=SAU7_CPUCTRL;
> -			timer_physaddr=SAU7_TIMER;
> -			break;
> -		case APOLLO_DN4500:
> -			panic("Apollo model not yet supported");
> -			break;
> -		case APOLLO_DN3500:
> -			sio01_physaddr=SAU7_SIO01_PHYSADDR;
> -			sio23_physaddr=SAU7_SIO23_PHYSADDR;
> -			rtc_physaddr=SAU7_RTC_PHYSADDR;
> -			pica_physaddr=SAU7_PICA;
> -			picb_physaddr=SAU7_PICB;
> -			cpuctrl_physaddr=SAU7_CPUCTRL;
> -			timer_physaddr=SAU7_TIMER;
> -			break;
> -		default:
> -			panic("Undefined apollo model");
> -			break;
> -	}
> -
> -
> -}
> -
> -static void dn_serial_print(const char *str)
> -{
> -    while (*str) {
> -        if (*str == '\n') {
> -            sio01.rhrb_thrb = (unsigned char)'\r';
> -            while (!(sio01.srb_csrb & 0x4))
> -                ;
> -        }
> -        sio01.rhrb_thrb = (unsigned char)*str++;
> -        while (!(sio01.srb_csrb & 0x4))
> -            ;
> -    }
> -}
> -
> -void __init config_apollo(void)
> -{
> -	int i;
> -
> -	dn_setup_model();
> -
> -	mach_sched_init=dn_sched_init; /* */
> -	mach_init_IRQ=dn_init_IRQ;
> -	mach_hwclk           = dn_dummy_hwclk; /* */
> -	mach_reset	     = dn_dummy_reset;  /* */
> -#ifdef CONFIG_HEARTBEAT
> -	mach_heartbeat = dn_heartbeat;
> -#endif
> -	mach_get_model       = dn_get_model;
> -
> -	cpuctrl=0xaa00;
> -
> -	/* clear DMA translation table */
> -	for(i=0;i<0x400;i++)
> -		addr_xlat_map[i]=0;
> -
> -}
> -
> -irqreturn_t dn_timer_int(int irq, void *dev_id)
> -{
> -	unsigned char *at = (unsigned char *)apollo_timer;
> -
> -	legacy_timer_tick(1);
> -	timer_heartbeat();
> -
> -	READ_ONCE(*(at + 3));
> -	READ_ONCE(*(at + 5));
> -
> -	return IRQ_HANDLED;
> -}
> -
> -void dn_sched_init(void)
> -{
> -	/* program timer 1 */
> -	*(volatile unsigned char *)(apollo_timer + 3) = 0x01;
> -	*(volatile unsigned char *)(apollo_timer + 1) = 0x40;
> -	*(volatile unsigned char *)(apollo_timer + 5) = 0x09;
> -	*(volatile unsigned char *)(apollo_timer + 7) = 0xc4;
> -
> -	/* enable IRQ of PIC B */
> -	*(volatile unsigned char *)(pica+1)&=(~8);
> -
> -#if 0
> -	pr_info("*(0x10803) %02x\n",
> -		*(volatile unsigned char *)(apollo_timer + 0x3));
> -	pr_info("*(0x10803) %02x\n",
> -		*(volatile unsigned char *)(apollo_timer + 0x3));
> -#endif
> -
> -	if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", NULL))
> -		pr_err("Couldn't register timer interrupt\n");
> -}
> -
> -int dn_dummy_hwclk(int op, struct rtc_time *t) {
> -
> -
> -  if(!op) { /* read */
> -    t->tm_sec=rtc->second;
> -    t->tm_min=rtc->minute;
> -    t->tm_hour=rtc->hours;
> -    t->tm_mday=rtc->day_of_month;
> -    t->tm_wday=rtc->day_of_week;
> -    t->tm_mon = rtc->month - 1;
> -    t->tm_year=rtc->year;
> -    if (t->tm_year < 70)
> -	t->tm_year += 100;
> -  } else {
> -    rtc->second=t->tm_sec;
> -    rtc->minute=t->tm_min;
> -    rtc->hours=t->tm_hour;
> -    rtc->day_of_month=t->tm_mday;
> -    if(t->tm_wday!=-1)
> -      rtc->day_of_week=t->tm_wday;
> -    rtc->month = t->tm_mon + 1;
> -    rtc->year = t->tm_year % 100;
> -  }
> -
> -  return 0;
> -
> -}
> -
> -static void dn_dummy_reset(void)
> -{
> -  dn_serial_print("The end !\n");
> -
> -  for(;;);
> -
> -}
> -
> -static void dn_get_model(char *model)
> -{
> -    strcpy(model, "Apollo ");
> -    if (apollo_model >= APOLLO_DN3000 && apollo_model <= APOLLO_DN4500)
> -        strcat(model, apollo_models[apollo_model - APOLLO_DN3000]);
> -}
> -
> -#ifdef CONFIG_HEARTBEAT
> -static int dn_cpuctrl=0xff00;
> -
> -static void dn_heartbeat(int on) {
> -
> -	if(on) {
> -		dn_cpuctrl&=~0x100;
> -		cpuctrl=dn_cpuctrl;
> -	}
> -	else {
> -		dn_cpuctrl&=~0x100;
> -		dn_cpuctrl|=0x100;
> -		cpuctrl=dn_cpuctrl;
> -	}
> -}
> -#endif
> -
> diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
> deleted file mode 100644
> index ba96a92f8f18..000000000000
> --- a/arch/m68k/apollo/dn_ints.c
> +++ /dev/null
> @@ -1,50 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -#include <linux/interrupt.h>
> -#include <linux/irq.h>
> -
> -#include <asm/traps.h>
> -#include <asm/apollohw.h>
> -
> -#include "apollo.h"
> -
> -static unsigned int apollo_irq_startup(struct irq_data *data)
> -{
> -	unsigned int irq = data->irq;
> -
> -	if (irq < 8)
> -		*(volatile unsigned char *)(pica+1) &= ~(1 << irq);
> -	else
> -		*(volatile unsigned char *)(picb+1) &= ~(1 << (irq - 8));
> -	return 0;
> -}
> -
> -static void apollo_irq_shutdown(struct irq_data *data)
> -{
> -	unsigned int irq = data->irq;
> -
> -	if (irq < 8)
> -		*(volatile unsigned char *)(pica+1) |= (1 << irq);
> -	else
> -		*(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
> -}
> -
> -static void apollo_irq_eoi(struct irq_data *data)
> -{
> -	*(volatile unsigned char *)(pica) = 0x20;
> -	*(volatile unsigned char *)(picb) = 0x20;
> -}
> -
> -static struct irq_chip apollo_irq_chip = {
> -	.name           = "apollo",
> -	.irq_startup    = apollo_irq_startup,
> -	.irq_shutdown   = apollo_irq_shutdown,
> -	.irq_eoi	= apollo_irq_eoi,
> -};
> -
> -
> -void __init dn_init_IRQ(void)
> -{
> -	m68k_setup_user_interrupt(VEC_USER + 96, 16);
> -	m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
> -				  IRQ_APOLLO, 16);
> -}
> diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
> deleted file mode 100644
> index d9d1f3c4c70d..000000000000
> --- a/arch/m68k/configs/apollo_defconfig
> +++ /dev/null
> @@ -1,595 +0,0 @@
> -CONFIG_LOCALVERSION="-apollo"
> -CONFIG_SYSVIPC=y
> -CONFIG_POSIX_MQUEUE=y
> -CONFIG_BSD_PROCESS_ACCT=y
> -CONFIG_BSD_PROCESS_ACCT_V3=y
> -CONFIG_LOG_BUF_SHIFT=16
> -# CONFIG_UTS_NS is not set
> -# CONFIG_IPC_NS is not set
> -# CONFIG_PID_NS is not set
> -# CONFIG_NET_NS is not set
> -CONFIG_BLK_DEV_INITRD=y
> -CONFIG_CC_OPTIMIZE_FOR_SIZE=y
> -CONFIG_KEXEC=y
> -CONFIG_BOOTINFO_PROC=y
> -CONFIG_M68020=y
> -CONFIG_M68030=y
> -CONFIG_M68040=y
> -CONFIG_M68060=y
> -CONFIG_APOLLO=y
> -CONFIG_HEARTBEAT=y
> -CONFIG_PROC_HARDWARE=y
> -CONFIG_MODULES=y
> -CONFIG_MODULE_UNLOAD=y
> -CONFIG_TRIM_UNUSED_KSYMS=y
> -CONFIG_PARTITION_ADVANCED=y
> -CONFIG_AMIGA_PARTITION=y
> -CONFIG_ATARI_PARTITION=y
> -CONFIG_MAC_PARTITION=y
> -CONFIG_BSD_DISKLABEL=y
> -CONFIG_MINIX_SUBPARTITION=y
> -CONFIG_SOLARIS_X86_PARTITION=y
> -CONFIG_UNIXWARE_DISKLABEL=y
> -CONFIG_SUN_PARTITION=y
> -# CONFIG_EFI_PARTITION is not set
> -CONFIG_SYSV68_PARTITION=y
> -CONFIG_MQ_IOSCHED_DEADLINE=m
> -CONFIG_MQ_IOSCHED_KYBER=m
> -CONFIG_IOSCHED_BFQ=m
> -# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
> -CONFIG_BINFMT_MISC=m
> -# CONFIG_COMPACTION is not set
> -CONFIG_DMAPOOL_TEST=m
> -CONFIG_USERFAULTFD=y
> -CONFIG_NET=y
> -CONFIG_PACKET=y
> -CONFIG_PACKET_DIAG=m
> -CONFIG_UNIX=y
> -CONFIG_UNIX_DIAG=m
> -CONFIG_TLS=m
> -CONFIG_XFRM_MIGRATE=y
> -CONFIG_NET_KEY=y
> -CONFIG_XDP_SOCKETS=y
> -CONFIG_XDP_SOCKETS_DIAG=m
> -CONFIG_INET=y
> -CONFIG_IP_PNP=y
> -CONFIG_IP_PNP_DHCP=y
> -CONFIG_IP_PNP_BOOTP=y
> -CONFIG_IP_PNP_RARP=y
> -CONFIG_NET_IPIP=m
> -CONFIG_NET_IPGRE_DEMUX=m
> -CONFIG_NET_IPGRE=m
> -CONFIG_NET_IPVTI=m
> -CONFIG_NET_FOU_IP_TUNNELS=y
> -CONFIG_INET_AH=m
> -CONFIG_INET_ESP=m
> -CONFIG_INET_ESP_OFFLOAD=m
> -CONFIG_INET_IPCOMP=m
> -CONFIG_INET_DIAG=m
> -CONFIG_INET_UDP_DIAG=m
> -CONFIG_INET_RAW_DIAG=m
> -CONFIG_IPV6=m
> -CONFIG_IPV6_ROUTER_PREF=y
> -CONFIG_INET6_AH=m
> -CONFIG_INET6_ESP=m
> -CONFIG_INET6_ESP_OFFLOAD=m
> -CONFIG_INET6_IPCOMP=m
> -CONFIG_IPV6_ILA=m
> -CONFIG_IPV6_VTI=m
> -CONFIG_IPV6_GRE=m
> -CONFIG_NETFILTER=y
> -CONFIG_NETFILTER_NETLINK_HOOK=m
> -CONFIG_NF_CONNTRACK=m
> -CONFIG_NF_CONNTRACK_ZONES=y
> -CONFIG_NF_CONNTRACK_AMANDA=m
> -CONFIG_NF_CONNTRACK_FTP=m
> -CONFIG_NF_CONNTRACK_H323=m
> -CONFIG_NF_CONNTRACK_IRC=m
> -CONFIG_NF_CONNTRACK_NETBIOS_NS=m
> -CONFIG_NF_CONNTRACK_SNMP=m
> -CONFIG_NF_CONNTRACK_PPTP=m
> -CONFIG_NF_CONNTRACK_SANE=m
> -CONFIG_NF_CONNTRACK_SIP=m
> -CONFIG_NF_CONNTRACK_TFTP=m
> -CONFIG_NF_TABLES=m
> -CONFIG_NF_TABLES_INET=y
> -CONFIG_NF_TABLES_NETDEV=y
> -CONFIG_NFT_NUMGEN=m
> -CONFIG_NFT_CT=m
> -CONFIG_NFT_FLOW_OFFLOAD=m
> -CONFIG_NFT_CONNLIMIT=m
> -CONFIG_NFT_LOG=m
> -CONFIG_NFT_LIMIT=m
> -CONFIG_NFT_MASQ=m
> -CONFIG_NFT_REDIR=m
> -CONFIG_NFT_NAT=m
> -CONFIG_NFT_TUNNEL=m
> -CONFIG_NFT_QUEUE=m
> -CONFIG_NFT_QUOTA=m
> -CONFIG_NFT_REJECT=m
> -CONFIG_NFT_COMPAT=m
> -CONFIG_NFT_HASH=m
> -CONFIG_NFT_FIB_INET=m
> -CONFIG_NFT_XFRM=m
> -CONFIG_NFT_SOCKET=m
> -CONFIG_NFT_OSF=m
> -CONFIG_NFT_TPROXY=m
> -CONFIG_NFT_SYNPROXY=m
> -CONFIG_NFT_DUP_NETDEV=m
> -CONFIG_NFT_FWD_NETDEV=m
> -CONFIG_NFT_FIB_NETDEV=m
> -CONFIG_NFT_REJECT_NETDEV=m
> -CONFIG_NF_FLOW_TABLE_INET=m
> -CONFIG_NF_FLOW_TABLE=m
> -CONFIG_NETFILTER_XTABLES_LEGACY=y
> -CONFIG_NETFILTER_XT_SET=m
> -CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
> -CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
> -CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
> -CONFIG_NETFILTER_XT_TARGET_DSCP=m
> -CONFIG_NETFILTER_XT_TARGET_HMARK=m
> -CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
> -CONFIG_NETFILTER_XT_TARGET_LOG=m
> -CONFIG_NETFILTER_XT_TARGET_MARK=m
> -CONFIG_NETFILTER_XT_TARGET_NFLOG=m
> -CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
> -CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
> -CONFIG_NETFILTER_XT_TARGET_TEE=m
> -CONFIG_NETFILTER_XT_TARGET_TPROXY=m
> -CONFIG_NETFILTER_XT_TARGET_TRACE=m
> -CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
> -CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
> -CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
> -CONFIG_NETFILTER_XT_MATCH_BPF=m
> -CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
> -CONFIG_NETFILTER_XT_MATCH_COMMENT=m
> -CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
> -CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
> -CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
> -CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
> -CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
> -CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
> -CONFIG_NETFILTER_XT_MATCH_DSCP=m
> -CONFIG_NETFILTER_XT_MATCH_ESP=m
> -CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
> -CONFIG_NETFILTER_XT_MATCH_HELPER=m
> -CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
> -CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
> -CONFIG_NETFILTER_XT_MATCH_LENGTH=m
> -CONFIG_NETFILTER_XT_MATCH_LIMIT=m
> -CONFIG_NETFILTER_XT_MATCH_MAC=m
> -CONFIG_NETFILTER_XT_MATCH_MARK=m
> -CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
> -CONFIG_NETFILTER_XT_MATCH_NFACCT=m
> -CONFIG_NETFILTER_XT_MATCH_OSF=m
> -CONFIG_NETFILTER_XT_MATCH_OWNER=m
> -CONFIG_NETFILTER_XT_MATCH_POLICY=m
> -CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
> -CONFIG_NETFILTER_XT_MATCH_QUOTA=m
> -CONFIG_NETFILTER_XT_MATCH_RATEEST=m
> -CONFIG_NETFILTER_XT_MATCH_REALM=m
> -CONFIG_NETFILTER_XT_MATCH_RECENT=m
> -CONFIG_NETFILTER_XT_MATCH_SOCKET=m
> -CONFIG_NETFILTER_XT_MATCH_STATE=m
> -CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
> -CONFIG_NETFILTER_XT_MATCH_STRING=m
> -CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
> -CONFIG_NETFILTER_XT_MATCH_TIME=m
> -CONFIG_NETFILTER_XT_MATCH_U32=m
> -CONFIG_IP_SET=m
> -CONFIG_IP_SET_BITMAP_IP=m
> -CONFIG_IP_SET_BITMAP_IPMAC=m
> -CONFIG_IP_SET_BITMAP_PORT=m
> -CONFIG_IP_SET_HASH_IP=m
> -CONFIG_IP_SET_HASH_IPMARK=m
> -CONFIG_IP_SET_HASH_IPPORT=m
> -CONFIG_IP_SET_HASH_IPPORTIP=m
> -CONFIG_IP_SET_HASH_IPPORTNET=m
> -CONFIG_IP_SET_HASH_IPMAC=m
> -CONFIG_IP_SET_HASH_MAC=m
> -CONFIG_IP_SET_HASH_NETPORTNET=m
> -CONFIG_IP_SET_HASH_NET=m
> -CONFIG_IP_SET_HASH_NETNET=m
> -CONFIG_IP_SET_HASH_NETPORT=m
> -CONFIG_IP_SET_HASH_NETIFACE=m
> -CONFIG_IP_SET_LIST_SET=m
> -CONFIG_NFT_DUP_IPV4=m
> -CONFIG_NFT_FIB_IPV4=m
> -CONFIG_NF_TABLES_ARP=y
> -CONFIG_NF_LOG_ARP=m
> -CONFIG_NF_LOG_IPV4=m
> -CONFIG_IP_NF_IPTABLES=m
> -CONFIG_IP_NF_MATCH_AH=m
> -CONFIG_IP_NF_MATCH_ECN=m
> -CONFIG_IP_NF_MATCH_RPFILTER=m
> -CONFIG_IP_NF_MATCH_TTL=m
> -CONFIG_IP_NF_TARGET_REJECT=m
> -CONFIG_IP_NF_TARGET_SYNPROXY=m
> -CONFIG_IP_NF_NAT=m
> -CONFIG_IP_NF_TARGET_MASQUERADE=m
> -CONFIG_IP_NF_TARGET_NETMAP=m
> -CONFIG_IP_NF_TARGET_REDIRECT=m
> -CONFIG_IP_NF_TARGET_ECN=m
> -CONFIG_IP_NF_TARGET_TTL=m
> -CONFIG_IP_NF_RAW=m
> -CONFIG_IP_NF_ARPFILTER=m
> -CONFIG_IP_NF_ARP_MANGLE=m
> -CONFIG_NFT_DUP_IPV6=m
> -CONFIG_NFT_FIB_IPV6=m
> -CONFIG_IP6_NF_IPTABLES=m
> -CONFIG_IP6_NF_MATCH_AH=m
> -CONFIG_IP6_NF_MATCH_EUI64=m
> -CONFIG_IP6_NF_MATCH_FRAG=m
> -CONFIG_IP6_NF_MATCH_OPTS=m
> -CONFIG_IP6_NF_MATCH_HL=m
> -CONFIG_IP6_NF_MATCH_IPV6HEADER=m
> -CONFIG_IP6_NF_MATCH_MH=m
> -CONFIG_IP6_NF_MATCH_RPFILTER=m
> -CONFIG_IP6_NF_MATCH_RT=m
> -CONFIG_IP6_NF_MATCH_SRH=m
> -CONFIG_IP6_NF_TARGET_HL=m
> -CONFIG_IP6_NF_TARGET_REJECT=m
> -CONFIG_IP6_NF_TARGET_SYNPROXY=m
> -CONFIG_IP6_NF_RAW=m
> -CONFIG_IP6_NF_NAT=m
> -CONFIG_IP6_NF_TARGET_MASQUERADE=m
> -CONFIG_IP6_NF_TARGET_NPT=m
> -CONFIG_NF_TABLES_BRIDGE=m
> -CONFIG_NFT_BRIDGE_META=m
> -CONFIG_NFT_BRIDGE_REJECT=m
> -CONFIG_NF_CONNTRACK_BRIDGE=m
> -CONFIG_BRIDGE_NF_EBTABLES_LEGACY=m
> -CONFIG_BRIDGE_NF_EBTABLES=m
> -CONFIG_BRIDGE_EBT_BROUTE=m
> -CONFIG_BRIDGE_EBT_T_FILTER=m
> -CONFIG_BRIDGE_EBT_T_NAT=m
> -CONFIG_BRIDGE_EBT_802_3=m
> -CONFIG_BRIDGE_EBT_AMONG=m
> -CONFIG_BRIDGE_EBT_ARP=m
> -CONFIG_BRIDGE_EBT_IP=m
> -CONFIG_BRIDGE_EBT_IP6=m
> -CONFIG_BRIDGE_EBT_LIMIT=m
> -CONFIG_BRIDGE_EBT_MARK=m
> -CONFIG_BRIDGE_EBT_PKTTYPE=m
> -CONFIG_BRIDGE_EBT_STP=m
> -CONFIG_BRIDGE_EBT_VLAN=m
> -CONFIG_BRIDGE_EBT_ARPREPLY=m
> -CONFIG_BRIDGE_EBT_DNAT=m
> -CONFIG_BRIDGE_EBT_MARK_T=m
> -CONFIG_BRIDGE_EBT_REDIRECT=m
> -CONFIG_BRIDGE_EBT_SNAT=m
> -CONFIG_BRIDGE_EBT_LOG=m
> -CONFIG_BRIDGE_EBT_NFLOG=m
> -CONFIG_IP_SCTP=m
> -CONFIG_RDS=m
> -CONFIG_RDS_TCP=m
> -CONFIG_L2TP=m
> -CONFIG_BRIDGE=m
> -CONFIG_ATALK=m
> -CONFIG_6LOWPAN=m
> -CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
> -CONFIG_6LOWPAN_GHC_UDP=m
> -CONFIG_6LOWPAN_GHC_ICMPV6=m
> -CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
> -CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
> -CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
> -CONFIG_DNS_RESOLVER=y
> -CONFIG_BATMAN_ADV=m
> -# CONFIG_BATMAN_ADV_BATMAN_V is not set
> -CONFIG_NETLINK_DIAG=m
> -CONFIG_MPLS=y
> -CONFIG_NET_MPLS_GSO=m
> -CONFIG_MPLS_ROUTING=m
> -CONFIG_MPLS_IPTUNNEL=m
> -CONFIG_NET_NSH=m
> -CONFIG_AF_KCM=m
> -# CONFIG_WIRELESS is not set
> -CONFIG_PSAMPLE=m
> -CONFIG_NET_IFE=m
> -CONFIG_DEVTMPFS=y
> -CONFIG_DEVTMPFS_MOUNT=y
> -CONFIG_TEST_ASYNC_DRIVER_PROBE=m
> -CONFIG_CONNECTOR=m
> -CONFIG_ZRAM=m
> -CONFIG_BLK_DEV_LOOP=y
> -CONFIG_BLK_DEV_DRBD=m
> -CONFIG_BLK_DEV_NBD=m
> -CONFIG_BLK_DEV_RAM=y
> -CONFIG_ATA_OVER_ETH=m
> -CONFIG_DUMMY_IRQ=m
> -CONFIG_RAID_ATTRS=m
> -CONFIG_SCSI=y
> -CONFIG_BLK_DEV_SD=y
> -CONFIG_CHR_DEV_ST=m
> -CONFIG_BLK_DEV_SR=y
> -CONFIG_CHR_DEV_SG=m
> -CONFIG_SCSI_CONSTANTS=y
> -CONFIG_SCSI_SAS_ATTRS=m
> -CONFIG_ISCSI_TCP=m
> -CONFIG_ISCSI_BOOT_SYSFS=m
> -CONFIG_MD=y
> -CONFIG_MD_LINEAR=m
> -CONFIG_BLK_DEV_DM=m
> -CONFIG_DM_UNSTRIPED=m
> -CONFIG_DM_CRYPT=m
> -CONFIG_DM_SNAPSHOT=m
> -CONFIG_DM_THIN_PROVISIONING=m
> -CONFIG_DM_WRITECACHE=m
> -CONFIG_DM_ERA=m
> -CONFIG_DM_CLONE=m
> -CONFIG_DM_MIRROR=m
> -CONFIG_DM_RAID=m
> -CONFIG_DM_ZERO=m
> -CONFIG_DM_MULTIPATH=m
> -CONFIG_DM_UEVENT=y
> -CONFIG_DM_LOG_WRITES=m
> -CONFIG_DM_INTEGRITY=m
> -CONFIG_TARGET_CORE=m
> -CONFIG_TCM_IBLOCK=m
> -CONFIG_TCM_FILEIO=m
> -CONFIG_TCM_PSCSI=m
> -CONFIG_NETDEVICES=y
> -CONFIG_DUMMY=m
> -CONFIG_WIREGUARD=m
> -CONFIG_OVPN=m
> -CONFIG_EQUALIZER=m
> -CONFIG_NET_TEAM=m
> -CONFIG_NET_TEAM_MODE_BROADCAST=m
> -CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
> -CONFIG_NET_TEAM_MODE_RANDOM=m
> -CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
> -CONFIG_NET_TEAM_MODE_LOADBALANCE=m
> -CONFIG_MACVLAN=m
> -CONFIG_MACVTAP=m
> -CONFIG_IPVLAN=m
> -CONFIG_IPVTAP=m
> -CONFIG_VXLAN=m
> -CONFIG_GENEVE=m
> -CONFIG_BAREUDP=m
> -CONFIG_GTP=m
> -CONFIG_PFCP=m
> -CONFIG_MACSEC=m
> -CONFIG_NETCONSOLE=m
> -CONFIG_NETCONSOLE_DYNAMIC=y
> -CONFIG_TUN=m
> -CONFIG_VETH=m
> -CONFIG_PPP=m
> -CONFIG_PPP_BSDCOMP=m
> -CONFIG_PPP_DEFLATE=m
> -CONFIG_PPP_FILTER=y
> -CONFIG_PPP_MPPE=m
> -CONFIG_PPPOE=m
> -CONFIG_PPTP=m
> -CONFIG_PPPOL2TP=m
> -CONFIG_PPP_ASYNC=m
> -CONFIG_PPP_SYNC_TTY=m
> -CONFIG_SLIP=m
> -CONFIG_SLIP_COMPRESSED=y
> -CONFIG_SLIP_SMART=y
> -CONFIG_SLIP_MODE_SLIP6=y
> -# CONFIG_WLAN is not set
> -CONFIG_INPUT_EVDEV=m
> -# CONFIG_KEYBOARD_ATKBD is not set
> -# CONFIG_MOUSE_PS2 is not set
> -CONFIG_MOUSE_SERIAL=m
> -CONFIG_SERIO=m
> -CONFIG_USERIO=m
> -# CONFIG_LEGACY_PTYS is not set
> -# CONFIG_HW_RANDOM is not set
> -CONFIG_NTP_PPS=y
> -CONFIG_PPS_CLIENT_LDISC=m
> -CONFIG_PTP_1588_CLOCK=m
> -# CONFIG_HWMON is not set
> -CONFIG_FB=y
> -CONFIG_FRAMEBUFFER_CONSOLE=y
> -CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y
> -CONFIG_LOGO=y
> -# CONFIG_LOGO_LINUX_VGA16 is not set
> -# CONFIG_LOGO_LINUX_CLUT224 is not set
> -CONFIG_HID=m
> -CONFIG_HIDRAW=y
> -CONFIG_UHID=m
> -# CONFIG_HID_GENERIC is not set
> -# CONFIG_HID_ITE is not set
> -# CONFIG_HID_REDRAGON is not set
> -# CONFIG_USB_SUPPORT is not set
> -CONFIG_RTC_CLASS=y
> -# CONFIG_RTC_NVMEM is not set
> -CONFIG_RTC_DRV_GENERIC=m
> -# CONFIG_VIRTIO_MENU is not set
> -# CONFIG_VHOST_MENU is not set
> -# CONFIG_IOMMU_SUPPORT is not set
> -CONFIG_DAX=m
> -CONFIG_EXT4_FS=y
> -CONFIG_JFS_FS=m
> -CONFIG_XFS_FS=m
> -CONFIG_OCFS2_FS=m
> -# CONFIG_OCFS2_DEBUG_MASKLOG is not set
> -CONFIG_BTRFS_FS=m
> -CONFIG_FANOTIFY=y
> -CONFIG_QUOTA_NETLINK_INTERFACE=y
> -CONFIG_AUTOFS_FS=m
> -CONFIG_FUSE_FS=m
> -CONFIG_CUSE=m
> -CONFIG_OVERLAY_FS=m
> -CONFIG_ISO9660_FS=y
> -CONFIG_JOLIET=y
> -CONFIG_ZISOFS=y
> -CONFIG_UDF_FS=m
> -CONFIG_MSDOS_FS=m
> -CONFIG_VFAT_FS=m
> -CONFIG_EXFAT_FS=m
> -CONFIG_NTFS3_FS=m
> -CONFIG_NTFS3_LZX_XPRESS=y
> -CONFIG_PROC_KCORE=y
> -CONFIG_PROC_CHILDREN=y
> -CONFIG_TMPFS=y
> -CONFIG_ORANGEFS_FS=m
> -CONFIG_AFFS_FS=m
> -CONFIG_ECRYPT_FS=m
> -CONFIG_ECRYPT_FS_MESSAGING=y
> -CONFIG_HFS_FS=m
> -CONFIG_HFSPLUS_FS=m
> -CONFIG_CRAMFS=m
> -CONFIG_SQUASHFS=m
> -CONFIG_SQUASHFS_LZ4=y
> -CONFIG_SQUASHFS_LZO=y
> -CONFIG_MINIX_FS=m
> -CONFIG_OMFS_FS=m
> -CONFIG_HPFS_FS=m
> -CONFIG_QNX4FS_FS=m
> -CONFIG_QNX6FS_FS=m
> -CONFIG_UFS_FS=m
> -CONFIG_EROFS_FS=m
> -CONFIG_NFS_FS=y
> -CONFIG_NFS_V4=m
> -CONFIG_NFS_SWAP=y
> -CONFIG_ROOT_NFS=y
> -CONFIG_NFSD=m
> -CONFIG_RPCSEC_GSS_KRB5=m
> -CONFIG_CIFS=m
> -# CONFIG_CIFS_STATS2 is not set
> -# CONFIG_CIFS_DEBUG is not set
> -CONFIG_CODA_FS=m
> -CONFIG_NLS_CODEPAGE_437=y
> -CONFIG_NLS_CODEPAGE_737=m
> -CONFIG_NLS_CODEPAGE_775=m
> -CONFIG_NLS_CODEPAGE_850=m
> -CONFIG_NLS_CODEPAGE_852=m
> -CONFIG_NLS_CODEPAGE_855=m
> -CONFIG_NLS_CODEPAGE_857=m
> -CONFIG_NLS_CODEPAGE_860=m
> -CONFIG_NLS_CODEPAGE_861=m
> -CONFIG_NLS_CODEPAGE_862=m
> -CONFIG_NLS_CODEPAGE_863=m
> -CONFIG_NLS_CODEPAGE_864=m
> -CONFIG_NLS_CODEPAGE_865=m
> -CONFIG_NLS_CODEPAGE_866=m
> -CONFIG_NLS_CODEPAGE_869=m
> -CONFIG_NLS_CODEPAGE_936=m
> -CONFIG_NLS_CODEPAGE_950=m
> -CONFIG_NLS_CODEPAGE_932=m
> -CONFIG_NLS_CODEPAGE_949=m
> -CONFIG_NLS_CODEPAGE_874=m
> -CONFIG_NLS_ISO8859_8=m
> -CONFIG_NLS_CODEPAGE_1250=m
> -CONFIG_NLS_CODEPAGE_1251=m
> -CONFIG_NLS_ASCII=m
> -CONFIG_NLS_ISO8859_1=y
> -CONFIG_NLS_ISO8859_2=m
> -CONFIG_NLS_ISO8859_3=m
> -CONFIG_NLS_ISO8859_4=m
> -CONFIG_NLS_ISO8859_5=m
> -CONFIG_NLS_ISO8859_6=m
> -CONFIG_NLS_ISO8859_7=m
> -CONFIG_NLS_ISO8859_9=m
> -CONFIG_NLS_ISO8859_13=m
> -CONFIG_NLS_ISO8859_14=m
> -CONFIG_NLS_ISO8859_15=m
> -CONFIG_NLS_KOI8_R=m
> -CONFIG_NLS_KOI8_U=m
> -CONFIG_NLS_MAC_ROMAN=m
> -CONFIG_NLS_MAC_CELTIC=m
> -CONFIG_NLS_MAC_CENTEURO=m
> -CONFIG_NLS_MAC_CROATIAN=m
> -CONFIG_NLS_MAC_CYRILLIC=m
> -CONFIG_NLS_MAC_GAELIC=m
> -CONFIG_NLS_MAC_GREEK=m
> -CONFIG_NLS_MAC_ICELAND=m
> -CONFIG_NLS_MAC_INUIT=m
> -CONFIG_NLS_MAC_ROMANIAN=m
> -CONFIG_NLS_MAC_TURKISH=m
> -CONFIG_DLM=m
> -CONFIG_ENCRYPTED_KEYS=m
> -CONFIG_HARDENED_USERCOPY=y
> -CONFIG_CRYPTO_USER=m
> -CONFIG_CRYPTO_NULL=m
> -CONFIG_CRYPTO_CRYPTD=m
> -CONFIG_CRYPTO_BENCHMARK=m
> -CONFIG_CRYPTO_RSA=m
> -CONFIG_CRYPTO_DH=m
> -CONFIG_CRYPTO_ECDH=m
> -CONFIG_CRYPTO_ECDSA=m
> -CONFIG_CRYPTO_ECRDSA=m
> -CONFIG_CRYPTO_AES=y
> -CONFIG_CRYPTO_AES_TI=m
> -CONFIG_CRYPTO_ANUBIS=m
> -CONFIG_CRYPTO_ARIA=m
> -CONFIG_CRYPTO_BLOWFISH=m
> -CONFIG_CRYPTO_CAMELLIA=m
> -CONFIG_CRYPTO_CAST5=m
> -CONFIG_CRYPTO_CAST6=m
> -CONFIG_CRYPTO_DES=m
> -CONFIG_CRYPTO_FCRYPT=m
> -CONFIG_CRYPTO_KHAZAD=m
> -CONFIG_CRYPTO_SEED=m
> -CONFIG_CRYPTO_SERPENT=m
> -CONFIG_CRYPTO_SM4_GENERIC=m
> -CONFIG_CRYPTO_TEA=m
> -CONFIG_CRYPTO_TWOFISH=m
> -CONFIG_CRYPTO_ADIANTUM=m
> -CONFIG_CRYPTO_ARC4=m
> -CONFIG_CRYPTO_CTS=m
> -CONFIG_CRYPTO_HCTR2=m
> -CONFIG_CRYPTO_LRW=m
> -CONFIG_CRYPTO_PCBC=m
> -CONFIG_CRYPTO_XTS=m
> -CONFIG_CRYPTO_AEGIS128=m
> -CONFIG_CRYPTO_MD4=m
> -CONFIG_CRYPTO_MICHAEL_MIC=m
> -CONFIG_CRYPTO_RMD160=m
> -CONFIG_CRYPTO_SHA1=m
> -CONFIG_CRYPTO_SM3_GENERIC=m
> -CONFIG_CRYPTO_WP512=m
> -CONFIG_CRYPTO_XCBC=m
> -CONFIG_CRYPTO_LZO=m
> -CONFIG_CRYPTO_842=m
> -CONFIG_CRYPTO_LZ4=m
> -CONFIG_CRYPTO_LZ4HC=m
> -CONFIG_CRYPTO_ZSTD=m
> -CONFIG_CRYPTO_DRBG_HASH=y
> -CONFIG_CRYPTO_DRBG_CTR=y
> -CONFIG_CRYPTO_USER_API_HASH=m
> -CONFIG_CRYPTO_USER_API_SKCIPHER=m
> -CONFIG_CRYPTO_USER_API_RNG=m
> -CONFIG_CRYPTO_USER_API_AEAD=m
> -# CONFIG_CRYPTO_HW is not set
> -CONFIG_PRIME_NUMBERS=m
> -CONFIG_CRC_BENCHMARK=y
> -CONFIG_XZ_DEC_TEST=m
> -CONFIG_GLOB_SELFTEST=m
> -# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set
> -CONFIG_MAGIC_SYSRQ=y
> -CONFIG_TEST_LOCKUP=m
> -CONFIG_WW_MUTEX_SELFTEST=m
> -CONFIG_EARLY_PRINTK=y
> -CONFIG_KUNIT=m
> -CONFIG_KUNIT_ALL_TESTS=m
> -CONFIG_TEST_DHRY=m
> -CONFIG_TEST_MIN_HEAP=m
> -CONFIG_TEST_DIV64=m
> -CONFIG_TEST_MULDIV64=m
> -CONFIG_REED_SOLOMON_TEST=m
> -CONFIG_ATOMIC64_SELFTEST=m
> -CONFIG_ASYNC_RAID6_TEST=m
> -CONFIG_TEST_HEXDUMP=m
> -CONFIG_TEST_KSTRTOX=m
> -CONFIG_TEST_BITMAP=m
> -CONFIG_TEST_UUID=m
> -CONFIG_TEST_XARRAY=m
> -CONFIG_TEST_MAPLE_TREE=m
> -CONFIG_TEST_RHASHTABLE=m
> -CONFIG_TEST_IDA=m
> -CONFIG_TEST_BITOPS=m
> -CONFIG_TEST_VMALLOC=m
> -CONFIG_TEST_BPF=m
> -CONFIG_FIND_BIT_BENCHMARK=m
> -CONFIG_TEST_FIRMWARE=m
> -CONFIG_TEST_SYSCTL=m
> -CONFIG_LINEAR_RANGES_TEST=m
> -CONFIG_TEST_UDELAY=m
> -CONFIG_TEST_STATIC_KEYS=m
> -CONFIG_TEST_KMOD=m
> -CONFIG_TEST_MEMCAT_P=m
> -CONFIG_TEST_MEMINIT=m
> -CONFIG_TEST_FREE_PAGES=m
> diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
> index 74f0a1f6d871..b06de259c697 100644
> --- a/arch/m68k/configs/multi_defconfig
> +++ b/arch/m68k/configs/multi_defconfig
> @@ -19,7 +19,6 @@ CONFIG_M68KFPU_EMU=y
>   CONFIG_AMIGA=y
>   CONFIG_ATARI=y
>   CONFIG_MAC=y
> -CONFIG_APOLLO=y
>   CONFIG_VME=y
>   CONFIG_MVME147=y
>   CONFIG_MVME16x=y
> diff --git a/arch/m68k/include/asm/apollohw.h b/arch/m68k/include/asm/apollohw.h
> deleted file mode 100644
> index 52066f3b8658..000000000000
> --- a/arch/m68k/include/asm/apollohw.h
> +++ /dev/null
> @@ -1,90 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 */
> -/* apollohw.h : some structures to access apollo HW */
> -
> -#ifndef _ASMm68k_APOLLOHW_H_
> -#define _ASMm68k_APOLLOHW_H_
> -
> -#include <linux/types.h>
> -
> -#include <asm/bootinfo-apollo.h>
> -
> -
> -extern u_long apollo_model;
> -
> -
> -/*
> -   see scn2681 data sheet for more info.
> -   member names are read_write.
> -*/
> -
> -#define DECLARE_2681_FIELD(x) unsigned char x; unsigned char dummy##x
> -
> -struct SCN2681 {
> -
> -	DECLARE_2681_FIELD(mra);
> -	DECLARE_2681_FIELD(sra_csra);
> -	DECLARE_2681_FIELD(BRGtest_cra);
> -	DECLARE_2681_FIELD(rhra_thra);
> -	DECLARE_2681_FIELD(ipcr_acr);
> -	DECLARE_2681_FIELD(isr_imr);
> -	DECLARE_2681_FIELD(ctu_ctur);
> -	DECLARE_2681_FIELD(ctl_ctlr);
> -	DECLARE_2681_FIELD(mrb);
> -	DECLARE_2681_FIELD(srb_csrb);
> -	DECLARE_2681_FIELD(tst_crb);
> -	DECLARE_2681_FIELD(rhrb_thrb);
> -	DECLARE_2681_FIELD(reserved);
> -	DECLARE_2681_FIELD(ip_opcr);
> -	DECLARE_2681_FIELD(startCnt_setOutBit);
> -	DECLARE_2681_FIELD(stopCnt_resetOutBit);
> -
> -};
> -
> -struct mc146818 {
> -        unsigned char second, alarm_second;
> -        unsigned char minute, alarm_minute;
> -        unsigned char hours, alarm_hours;
> -        unsigned char day_of_week, day_of_month;
> -        unsigned char month, year;
> -};
> -
> -
> -#define IO_BASE 0x80000000
> -
> -extern u_long sio01_physaddr;
> -extern u_long sio23_physaddr;
> -extern u_long rtc_physaddr;
> -extern u_long pica_physaddr;
> -extern u_long picb_physaddr;
> -extern u_long cpuctrl_physaddr;
> -extern u_long timer_physaddr;
> -
> -#define SAU7_SIO01_PHYSADDR 0x10400
> -#define SAU7_SIO23_PHYSADDR 0x10500
> -#define SAU7_RTC_PHYSADDR 0x10900
> -#define SAU7_PICA 0x11000
> -#define SAU7_PICB 0x11100
> -#define SAU7_CPUCTRL 0x10100
> -#define SAU7_TIMER 0x010800
> -
> -#define SAU8_SIO01_PHYSADDR 0x8400
> -#define SAU8_RTC_PHYSADDR 0x8900
> -#define SAU8_PICA 0x9400
> -#define SAU8_PICB 0x9500
> -#define SAU8_CPUCTRL 0x8100
> -#define SAU8_TIMER 0x8800
> -
> -#define sio01 ((*(volatile struct SCN2681 *)(IO_BASE + sio01_physaddr)))
> -#define sio23 ((*(volatile struct SCN2681 *)(IO_BASE + sio23_physaddr)))
> -#define rtc (((volatile struct mc146818 *)(IO_BASE + rtc_physaddr)))
> -#define cpuctrl (*(volatile unsigned int *)(IO_BASE + cpuctrl_physaddr))
> -#define pica (IO_BASE + pica_physaddr)
> -#define picb (IO_BASE + picb_physaddr)
> -#define apollo_timer (IO_BASE + timer_physaddr)
> -#define addr_xlat_map ((unsigned short *)(IO_BASE + 0x17000))
> -
> -#define isaIO2mem(x) (((((x) & 0x3f8)  << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE)
> -
> -#define IRQ_APOLLO	IRQ_USER
> -
> -#endif
> diff --git a/arch/m68k/include/asm/config.h b/arch/m68k/include/asm/config.h
> index 9bb888ab5009..9c73a73a7b3c 100644
> --- a/arch/m68k/include/asm/config.h
> +++ b/arch/m68k/include/asm/config.h
> @@ -9,7 +9,6 @@
>   #define _M68K_CONFIG_H
>   
>   extern int amiga_parse_bootinfo(const struct bi_record *record);
> -extern int apollo_parse_bootinfo(const struct bi_record *record);
>   extern int atari_parse_bootinfo(const struct bi_record *record);
>   extern int bvme6000_parse_bootinfo(const struct bi_record *record);
>   extern int hp300_parse_bootinfo(const struct bi_record *record);
> @@ -20,7 +19,6 @@ extern int q40_parse_bootinfo(const struct bi_record *record);
>   extern int virt_parse_bootinfo(const struct bi_record *record);
>   
>   extern void config_amiga(void);
> -extern void config_apollo(void);
>   extern void config_atari(void);
>   extern void config_bvme6000(void);
>   extern void config_hp300(void);
> diff --git a/arch/m68k/include/asm/irq.h b/arch/m68k/include/asm/irq.h
> index 2263e92d418a..51cd970b0778 100644
> --- a/arch/m68k/include/asm/irq.h
> +++ b/arch/m68k/include/asm/irq.h
> @@ -26,8 +26,6 @@
>   #define NR_IRQS	43
>   #elif defined(CONFIG_AMIGA) || !defined(CONFIG_MMU)
>   #define NR_IRQS	32
> -#elif defined(CONFIG_APOLLO)
> -#define NR_IRQS	24
>   #else /* CONFIG_HP300 etc. */
>   #define NR_IRQS	8
>   #endif
> diff --git a/arch/m68k/include/asm/setup.h b/arch/m68k/include/asm/setup.h
> index e4ec169f5c7d..1719d0ee59ea 100644
> --- a/arch/m68k/include/asm/setup.h
> +++ b/arch/m68k/include/asm/setup.h
> @@ -34,7 +34,7 @@ extern unsigned long m68k_machtype;
>   
>   #if !defined(CONFIG_AMIGA)
>   #  define MACH_IS_AMIGA (0)
> -#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
> +#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)                           \
>   	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
>   	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                  \
> @@ -48,7 +48,7 @@ extern unsigned long m68k_machtype;
>   
>   #if !defined(CONFIG_ATARI)
>   #  define MACH_IS_ATARI (0)
> -#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_APOLLO) \
> +#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC)                           \
>   	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)               \
>   	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                      \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                  \
> @@ -62,7 +62,7 @@ extern unsigned long m68k_machtype;
>   
>   #if !defined(CONFIG_MAC)
>   #  define MACH_IS_MAC (0)
> -#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI) || defined(CONFIG_APOLLO) \
> +#elif defined(CONFIG_AMIGA) || defined(CONFIG_ATARI)                           \
>   	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)                 \
>   	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                        \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                    \
> @@ -82,24 +82,10 @@ extern unsigned long m68k_machtype;
>   #define MACH_IS_SUN3 (0)
>   #endif
>   
> -#if !defined (CONFIG_APOLLO)
> -#  define MACH_IS_APOLLO (0)
> -#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)              \
> -	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
> -	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
> -	|| defined(CONFIG_VIRT)
> -#  define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO)
> -#else
> -#  define MACH_APOLLO_ONLY
> -#  define MACH_IS_APOLLO (1)
> -#  define MACH_TYPE (MACH_APOLLO)
> -#endif
> -
>   #if !defined (CONFIG_MVME147)
>   #  define MACH_IS_MVME147 (0)
>   #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
> +	|| defined(CONFIG_BVME6000)                                         \
>   	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME16x)                 \
>   	|| defined(CONFIG_VIRT)
> @@ -113,7 +99,7 @@ extern unsigned long m68k_machtype;
>   #if !defined (CONFIG_MVME16x)
>   #  define MACH_IS_MVME16x (0)
>   #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000)               \
> +	|| defined(CONFIG_BVME6000)                                         \
>   	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
>   	|| defined(CONFIG_VIRT)
> @@ -127,7 +113,7 @@ extern unsigned long m68k_machtype;
>   #if !defined (CONFIG_BVME6000)
>   #  define MACH_IS_BVME6000 (0)
>   #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
> +	|| defined(CONFIG_MVME16x)                                          \
>   	|| defined(CONFIG_HP300) || defined(CONFIG_Q40)                     \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147)                 \
>   	|| defined(CONFIG_VIRT)
> @@ -141,7 +127,7 @@ extern unsigned long m68k_machtype;
>   #if !defined (CONFIG_HP300)
>   #  define MACH_IS_HP300 (0)
>   #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) \
> +	|| defined(CONFIG_MVME16x) \
>   	|| defined(CONFIG_BVME6000) || defined(CONFIG_Q40) \
>   	|| defined(CONFIG_SUN3X) || defined(CONFIG_MVME147) \
>   	|| defined(CONFIG_VIRT)
> @@ -169,7 +155,7 @@ extern unsigned long m68k_machtype;
>   #if !defined (CONFIG_SUN3X)
>   #  define MACH_IS_SUN3X (0)
>   #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
> +	|| defined(CONFIG_MVME16x)                                          \
>   	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
>   	|| defined(CONFIG_Q40) || defined(CONFIG_MVME147)                   \
>   	|| defined(CONFIG_VIRT)
> @@ -183,7 +169,7 @@ extern unsigned long m68k_machtype;
>   #if !defined(CONFIG_VIRT)
>   #  define MACH_IS_VIRT (0)
>   #elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC) || defined(CONFIG_ATARI) \
> -	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x)                \
> +	|| defined(CONFIG_MVME16x)                                          \
>   	|| defined(CONFIG_BVME6000) || defined(CONFIG_HP300)                \
>   	|| defined(CONFIG_Q40) || defined(CONFIG_SUN3X)                     \
>   	|| defined(CONFIG_MVME147)
> diff --git a/arch/m68k/include/uapi/asm/bootinfo-apollo.h b/arch/m68k/include/uapi/asm/bootinfo-apollo.h
> deleted file mode 100644
> index c226f7957938..000000000000
> --- a/arch/m68k/include/uapi/asm/bootinfo-apollo.h
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
> -/*
> -** asm/bootinfo-apollo.h -- Apollo-specific boot information definitions
> -*/
> -
> -#ifndef _UAPI_ASM_M68K_BOOTINFO_APOLLO_H
> -#define _UAPI_ASM_M68K_BOOTINFO_APOLLO_H
> -
> -
> -    /*
> -     *  Apollo-specific tags
> -     */
> -
> -#define BI_APOLLO_MODEL		0x8000	/* model (__be32) */
> -
> -
> -    /*
> -     *  Apollo models (BI_APOLLO_MODEL)
> -     */
> -
> -#define APOLLO_UNKNOWN		0
> -#define APOLLO_DN3000		1
> -#define APOLLO_DN3010		2
> -#define APOLLO_DN3500		3
> -#define APOLLO_DN4000		4
> -#define APOLLO_DN4500		5
> -
> -
> -#endif /* _UAPI_ASM_M68K_BOOTINFO_APOLLO_H */
> diff --git a/arch/m68k/include/uapi/asm/bootinfo.h b/arch/m68k/include/uapi/asm/bootinfo.h
> index 28d2d44c08d0..a199a7ecd3cd 100644
> --- a/arch/m68k/include/uapi/asm/bootinfo.h
> +++ b/arch/m68k/include/uapi/asm/bootinfo.h
> @@ -80,7 +80,7 @@ struct mem_info {
>   #define MACH_AMIGA		1
>   #define MACH_ATARI		2
>   #define MACH_MAC		3
> -#define MACH_APOLLO		4
> +/* 4 was MACH_APOLLO */
>   #define MACH_SUN3		5
>   #define MACH_MVME147		6
>   #define MACH_MVME16x		7
> @@ -134,7 +134,7 @@ struct mem_info {
>   #define MMUB_68030		1	/* Internal MMU */
>   #define MMUB_68040		2	/* Internal MMU */
>   #define MMUB_68060		3	/* Internal MMU */
> -#define MMUB_APOLLO		4	/* Custom Apollo */
> +/* 4 was MMUB_APOLLO */
>   #define MMUB_SUN3		5	/* Custom Sun-3 */
>   #define MMUB_COLDFIRE		6	/* Internal MMU */
>   
> @@ -143,7 +143,6 @@ struct mem_info {
>   #define MMU_68040		(1 << MMUB_68040)
>   #define MMU_68060		(1 << MMUB_68060)
>   #define MMU_SUN3		(1 << MMUB_SUN3)
> -#define MMU_APOLLO		(1 << MMUB_APOLLO)
>   #define MMU_COLDFIRE		(1 << MMUB_COLDFIRE)
>   
>   
> diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S
> index 2e4ef0358887..573b30100679 100644
> --- a/arch/m68k/kernel/head.S
> +++ b/arch/m68k/kernel/head.S
> @@ -449,7 +449,7 @@ func_define	mmu_get_ptr_table_entry,2
>   func_define	mmu_get_page_table_entry,2
>   func_define	mmu_print
>   func_define	get_new_page
> -#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
> +#ifdef CONFIG_HP300
>   func_define	set_leds
>   #endif
>   
> @@ -528,17 +528,10 @@ func_define	putn,1
>   #define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab
>   #define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab
>   #define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
> -#define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab
>   #define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab
>   #define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab
>   #define is_not_virt(lab) cmpl &MACH_VIRT,%pc@(m68k_machtype); jne lab
>   
> -#define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \
> -			jeq 42f; \
> -			cmpl &MACH_APOLLO,%pc@(m68k_machtype); \
> -			jne lab ;\
> -		42:\
> -
>   #define is_040_or_060(lab)	btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
>   #define is_not_040_or_060(lab)	btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
>   #define is_040(lab)		btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab
> @@ -551,8 +544,8 @@ func_define	putn,1
>      the console is running.  Writing a 1 bit turns the corresponding LED
>      _off_ - on the 340 bit 7 is towards the back panel of the machine.  */
>   .macro	leds	mask
> -#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
> -	hasnt_leds(.Lled\@)
> +#ifdef CONFIG_HP300
> +	is_not_hp300(.Lled\@)
>   	pea	\mask
>   	func_call	set_leds
>   	addql	#4,%sp
> @@ -1250,16 +1243,6 @@ L(notsun3x):
>   L(novirt):
>   #endif
>   
> -#ifdef CONFIG_APOLLO
> -	is_not_apollo(L(notapollo))
> -
> -	putc	'P'
> -	mmu_map         #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
> -
> -L(notapollo):
> -	jbra	L(mmu_init_done)
> -#endif
> -
>   L(mmu_init_done):
>   
>   	putc	'G'
> @@ -1445,16 +1428,6 @@ L(mmu_fixup_done):
>   	/* enable copro */
>   	oriw	#0x4000,0x61000000
>   1:
> -#endif
> -
> -#ifdef CONFIG_APOLLO
> -	is_not_apollo(1f)
> -
> -	/*
> -	 * Fix up the iobase before printing
> -	 */
> -	movel	#0x80000000,L(iobase)
> -1:
>   #endif
>   
>   	putc	'I'
> @@ -2982,10 +2955,6 @@ L(serial_init_not_mac):
>   L(serial_init_not_mvme16x):
>   #endif
>   
> -#ifdef CONFIG_APOLLO
> -/* We count on the PROM initializing SIO1 */
> -#endif
> -
>   #ifdef CONFIG_HP300
>   /* We count on the boot loader initialising the UART */
>   #endif
> @@ -3167,17 +3136,6 @@ func_start	serial_putc,%d0/%d1/%a0/%a1
>   2:
>   #endif
>   
> -#ifdef CONFIG_APOLLO
> -	is_not_apollo(2f)
> -	movl    %pc@(L(iobase)),%a1
> -	moveb	%d0,%a1@(LTHRB0)
> -1:      moveb   %a1@(LSRB0),%d0
> -	andb	#0x4,%d0
> -	beq	1b
> -	jbra	L(serial_putc_done)
> -2:
> -#endif
> -
>   #ifdef CONFIG_HP300
>   	is_not_hp300(3f)
>   	movl    %pc@(L(iobase)),%a1
> @@ -3293,23 +3251,14 @@ ENTRY(debug_cons_nputs)
>   	rts
>   #endif /* CONFIG_EARLY_PRINTK */
>   
> -#if defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
> +#ifdef CONFIG_HP300
>   func_start	set_leds,%d0/%a0
>   	movel	ARG1,%d0
> -#ifdef CONFIG_HP300
>   	is_not_hp300(1f)
>   	movel	%pc@(L(iobase)),%a0
>   	moveb	%d0,%a0@(0x1ffff)
> -	jra	2f
> -#endif
> +	jra	1f
>   1:
> -#ifdef CONFIG_APOLLO
> -	movel   %pc@(L(iobase)),%a0
> -	lsll    #8,%d0
> -	eorw    #0xff00,%d0
> -	moveb	%d0,%a0@(LCPUCTRL)
> -#endif
> -2:
>   func_return	set_leds
>   #endif
>   
> @@ -3768,8 +3717,7 @@ __INITDATA
>   m68k_init_mapped_size:
>   	.long	0
>   
> -#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \
> -    defined(CONFIG_HP300) || defined(CONFIG_APOLLO)
> +#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || defined(CONFIG_HP300)
>   L(custom):
>   L(iobase):
>   	.long 0
> @@ -3850,12 +3798,6 @@ L(mac_sccbase):
>   	.long	0
>   #endif /* CONFIG_MAC */
>   
> -#if defined (CONFIG_APOLLO)
> -LSRB0        = 0x10412
> -LTHRB0       = 0x10416
> -LCPUCTRL     = 0x10100
> -#endif
> -
>   #if defined(CONFIG_HP300)
>   DCADATA	     = 0x11
>   DCALSR	     = 0x1b
> diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
> index c7e8de0d34bb..2451dda2f701 100644
> --- a/arch/m68k/kernel/setup_mm.c
> +++ b/arch/m68k/kernel/setup_mm.c
> @@ -178,8 +178,6 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
>   				unknown = mvme147_parse_bootinfo(record);
>   			else if (MACH_IS_HP300)
>   				unknown = hp300_parse_bootinfo(record);
> -			else if (MACH_IS_APOLLO)
> -				unknown = apollo_parse_bootinfo(record);
>   			else if (MACH_IS_VIRT)
>   				unknown = virt_parse_bootinfo(record);
>   			else
> @@ -275,11 +273,6 @@ void __init setup_arch(char **cmdline_p)
>   		config_sun3();
>   		break;
>   #endif
> -#ifdef CONFIG_APOLLO
> -	case MACH_APOLLO:
> -		config_apollo();
> -		break;
> -#endif
>   #ifdef CONFIG_MVME147
>   	case MACH_MVME147:
>   		config_mvme147();
> @@ -433,8 +426,6 @@ static int show_cpuinfo(struct seq_file *m, void *v)
>   		mmu = "68060";
>   	else if (m68k_mmutype & MMU_SUN3)
>   		mmu = "Sun-3";
> -	else if (m68k_mmutype & MMU_APOLLO)
> -		mmu = "Apollo";
>   	else if (m68k_mmutype & MMU_COLDFIRE)
>   		mmu = "ColdFire";
>   	else
> diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
> index a733f90eca55..2796e3dd7eaa 100644
> --- a/drivers/video/fbdev/Kconfig
> +++ b/drivers/video/fbdev/Kconfig
> @@ -184,14 +184,6 @@ config FB_CYBER2000_I2C
>   	  Integraphics CyberPro 20x0 and 5000 VGA chips.  This is used
>   	  on the Netwinder machines for the SAA7111 video capture.
>   
> -config FB_APOLLO
> -	bool
> -	depends on (FB = y) && APOLLO
> -	default y
> -	select FB_CFB_FILLRECT
> -	select FB_CFB_IMAGEBLIT
> -	select FB_IOMEM_FOPS
> -
>   config FB_Q40
>   	bool
>   	depends on (FB = y) && Q40
> diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
> index b3d12f977c06..bc2e45da30d6 100644
> --- a/drivers/video/fbdev/Makefile
> +++ b/drivers/video/fbdev/Makefile
> @@ -63,7 +63,6 @@ obj-$(CONFIG_FB_HGA)              += hgafb.o
>   obj-$(CONFIG_FB_XVR500)           += sunxvr500.o
>   obj-$(CONFIG_FB_XVR2500)          += sunxvr2500.o
>   obj-$(CONFIG_FB_XVR1000)          += sunxvr1000.o
> -obj-$(CONFIG_FB_APOLLO)           += dnfb.o
>   obj-$(CONFIG_FB_Q40)              += q40fb.o
>   obj-$(CONFIG_FB_TGA)              += tgafb.o
>   obj-$(CONFIG_FB_HP300)            += hpfb.o
> diff --git a/drivers/video/fbdev/dnfb.c b/drivers/video/fbdev/dnfb.c
> deleted file mode 100644
> index c4d24540d9ef..000000000000
> --- a/drivers/video/fbdev/dnfb.c
> +++ /dev/null
> @@ -1,307 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0-only
> -#include <linux/kernel.h>
> -#include <linux/errno.h>
> -#include <linux/string.h>
> -#include <linux/mm.h>
> -#include <linux/delay.h>
> -#include <linux/interrupt.h>
> -#include <linux/platform_device.h>
> -
> -#include <asm/setup.h>
> -#include <asm/irq.h>
> -#include <asm/amigahw.h>
> -#include <asm/amigaints.h>
> -#include <asm/apollohw.h>
> -#include <linux/fb.h>
> -#include <linux/module.h>
> -
> -/* apollo video HW definitions */
> -
> -/*
> - * Control Registers.   IOBASE + $x
> - *
> - * Note: these are the Memory/IO BASE definitions for a mono card set to the
> - * alternate address
> - *
> - * Control 3A and 3B serve identical functions except that 3A
> - * deals with control 1 and 3b deals with Color LUT reg.
> - */
> -
> -#define AP_IOBASE       0x3b0	/* Base address of 1 plane board. */
> -#define AP_STATUS       isaIO2mem(AP_IOBASE+0)	/* Status register.  Read */
> -#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0)	/* Write Enable Register Write */
> -#define AP_DEVICE_ID    isaIO2mem(AP_IOBASE+1)	/* Device ID Register. Read */
> -#define AP_ROP_1        isaIO2mem(AP_IOBASE+2)	/* Raster Operation reg. Write Word */
> -#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4)	/* Diagnostic Memory Request. Write Word */
> -#define AP_CONTROL_0    isaIO2mem(AP_IOBASE+8)	/* Control Register 0.  Read/Write */
> -#define AP_CONTROL_1    isaIO2mem(AP_IOBASE+0xa)	/* Control Register 1.  Read/Write */
> -#define AP_CONTROL_3A   isaIO2mem(AP_IOBASE+0xe)	/* Control Register 3a. Read/Write */
> -#define AP_CONTROL_2    isaIO2mem(AP_IOBASE+0xc)	/* Control Register 2. Read/Write */
> -
> -
> -#define FRAME_BUFFER_START 0x0FA0000
> -#define FRAME_BUFFER_LEN 0x40000
> -
> -/* CREG 0 */
> -#define VECTOR_MODE 0x40	/* 010x.xxxx */
> -#define DBLT_MODE   0x80	/* 100x.xxxx */
> -#define NORMAL_MODE 0xE0	/* 111x.xxxx */
> -#define SHIFT_BITS  0x1F	/* xxx1.1111 */
> -	/* other bits are Shift value */
> -
> -/* CREG 1 */
> -#define AD_BLT      0x80	/* 1xxx.xxxx */
> -#define NORMAL      0x80 /* 1xxx.xxxx */	/* What is happening here ?? */
> -#define INVERSE     0x00 /* 0xxx.xxxx */	/* Clearing this reverses the screen */
> -#define PIX_BLT     0x00	/* 0xxx.xxxx */
> -
> -#define AD_HIBIT        0x40	/* xIxx.xxxx */
> -
> -#define ROP_EN          0x10	/* xxx1.xxxx */
> -#define DST_EQ_SRC      0x00	/* xxx0.xxxx */
> -#define nRESET_SYNC     0x08	/* xxxx.1xxx */
> -#define SYNC_ENAB       0x02	/* xxxx.xx1x */
> -
> -#define BLANK_DISP      0x00	/* xxxx.xxx0 */
> -#define ENAB_DISP       0x01	/* xxxx.xxx1 */
> -
> -#define NORM_CREG1      (nRESET_SYNC | SYNC_ENAB | ENAB_DISP)	/* no reset sync */
> -
> -/* CREG 2 */
> -
> -/*
> - * Following 3 defines are common to 1, 4 and 8 plane.
> - */
> -
> -#define S_DATA_1s   0x00 /* 00xx.xxxx */	/* set source to all 1's -- vector drawing */
> -#define S_DATA_PIX  0x40 /* 01xx.xxxx */	/* takes source from ls-bits and replicates over 16 bits */
> -#define S_DATA_PLN  0xC0 /* 11xx.xxxx */	/* normal, each data access =16-bits in
> -						   one plane of image mem */
> -
> -/* CREG 3A/CREG 3B */
> -#       define RESET_CREG 0x80	/* 1000.0000 */
> -
> -/* ROP REG  -  all one nibble */
> -/*      ********* NOTE : this is used r0,r1,r2,r3 *********** */
> -#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
> -#define DEST_ZERO               0x0
> -#define SRC_AND_DEST    0x1
> -#define SRC_AND_nDEST   0x2
> -#define SRC                             0x3
> -#define nSRC_AND_DEST   0x4
> -#define DEST                    0x5
> -#define SRC_XOR_DEST    0x6
> -#define SRC_OR_DEST             0x7
> -#define SRC_NOR_DEST    0x8
> -#define SRC_XNOR_DEST   0x9
> -#define nDEST                   0xA
> -#define SRC_OR_nDEST    0xB
> -#define nSRC                    0xC
> -#define nSRC_OR_DEST    0xD
> -#define SRC_NAND_DEST   0xE
> -#define DEST_ONE                0xF
> -
> -#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
> -
> -/* frame buffer operations */
> -
> -static int dnfb_blank(int blank, struct fb_info *info);
> -static void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
> -
> -static const struct fb_ops dn_fb_ops = {
> -	.owner		= THIS_MODULE,
> -	__FB_DEFAULT_IOMEM_OPS_RDWR,
> -	.fb_blank	= dnfb_blank,
> -	.fb_fillrect	= cfb_fillrect,
> -	.fb_copyarea	= dnfb_copyarea,
> -	.fb_imageblit	= cfb_imageblit,
> -	__FB_DEFAULT_IOMEM_OPS_MMAP,
> -};
> -
> -static const struct fb_var_screeninfo dnfb_var = {
> -	.xres		= 1280,
> -	.yres		= 1024,
> -	.xres_virtual	= 2048,
> -	.yres_virtual	= 1024,
> -	.bits_per_pixel	= 1,
> -	.height		= -1,
> -	.width		= -1,
> -	.vmode		= FB_VMODE_NONINTERLACED,
> -};
> -
> -static const struct fb_fix_screeninfo dnfb_fix = {
> -	.id		= "Apollo Mono",
> -	.smem_start	= (FRAME_BUFFER_START + IO_BASE),
> -	.smem_len	= FRAME_BUFFER_LEN,
> -	.type		= FB_TYPE_PACKED_PIXELS,
> -	.visual		= FB_VISUAL_MONO10,
> -	.line_length	= 256,
> -};
> -
> -static int dnfb_blank(int blank, struct fb_info *info)
> -{
> -	if (blank)
> -		out_8(AP_CONTROL_3A, 0x0);
> -	else
> -		out_8(AP_CONTROL_3A, 0x1);
> -	return 0;
> -}
> -
> -static
> -void dnfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
> -{
> -
> -	int incr, y_delta, pre_read = 0, x_end, x_word_count;
> -	uint start_mask, end_mask, dest;
> -	ushort *src, dummy;
> -	short i, j;
> -
> -	incr = (area->dy <= area->sy) ? 1 : -1;
> -
> -	src = (ushort *)(info->screen_base + area->sy * info->fix.line_length +
> -			(area->sx >> 4));
> -	dest = area->dy * (info->fix.line_length >> 1) + (area->dx >> 4);
> -
> -	if (incr > 0) {
> -		y_delta = (info->fix.line_length * 8) - area->sx - area->width;
> -		x_end = area->dx + area->width - 1;
> -		x_word_count = (x_end >> 4) - (area->dx >> 4) + 1;
> -		start_mask = 0xffff0000 >> (area->dx & 0xf);
> -		end_mask = 0x7ffff >> (x_end & 0xf);
> -		out_8(AP_CONTROL_0,
> -		     (((area->dx & 0xf) - (area->sx & 0xf)) % 16) | (0x4 << 5));
> -		if ((area->dx & 0xf) < (area->sx & 0xf))
> -			pre_read = 1;
> -	} else {
> -		y_delta = -((info->fix.line_length * 8) - area->sx - area->width);
> -		x_end = area->dx - area->width + 1;
> -		x_word_count = (area->dx >> 4) - (x_end >> 4) + 1;
> -		start_mask = 0x7ffff >> (area->dx & 0xf);
> -		end_mask = 0xffff0000 >> (x_end & 0xf);
> -		out_8(AP_CONTROL_0,
> -		     ((-((area->sx & 0xf) - (area->dx & 0xf))) % 16) |
> -		     (0x4 << 5));
> -		if ((area->dx & 0xf) > (area->sx & 0xf))
> -			pre_read = 1;
> -	}
> -
> -	for (i = 0; i < area->height; i++) {
> -
> -		out_8(AP_CONTROL_3A, 0xc | (dest >> 16));
> -
> -		if (pre_read) {
> -			dummy = *src;
> -			src += incr;
> -		}
> -
> -		if (x_word_count) {
> -			out_8(AP_WRITE_ENABLE, start_mask);
> -			*src = dest;
> -			src += incr;
> -			dest += incr;
> -			out_8(AP_WRITE_ENABLE, 0);
> -
> -			for (j = 1; j < (x_word_count - 1); j++) {
> -				*src = dest;
> -				src += incr;
> -				dest += incr;
> -			}
> -
> -			out_8(AP_WRITE_ENABLE, start_mask);
> -			*src = dest;
> -			dest += incr;
> -			src += incr;
> -		} else {
> -			out_8(AP_WRITE_ENABLE, start_mask | end_mask);
> -			*src = dest;
> -			dest += incr;
> -			src += incr;
> -		}
> -		src += (y_delta / 16);
> -		dest += (y_delta / 16);
> -	}
> -	out_8(AP_CONTROL_0, NORMAL_MODE);
> -}
> -
> -/*
> - * Initialization
> - */
> -
> -static int dnfb_probe(struct platform_device *dev)
> -{
> -	struct fb_info *info;
> -	int err = 0;
> -
> -	info = framebuffer_alloc(0, &dev->dev);
> -	if (!info)
> -		return -ENOMEM;
> -
> -	info->fbops = &dn_fb_ops;
> -	info->fix = dnfb_fix;
> -	info->var = dnfb_var;
> -	info->var.red.length = 1;
> -	info->var.red.offset = 0;
> -	info->var.green = info->var.blue = info->var.red;
> -	info->screen_base = (u_char *) info->fix.smem_start;
> -
> -	err = fb_alloc_cmap(&info->cmap, 2, 0);
> -	if (err < 0)
> -		goto release_framebuffer;
> -
> -	err = register_framebuffer(info);
> -	if (err < 0) {
> -		fb_dealloc_cmap(&info->cmap);
> -		goto release_framebuffer;
> -	}
> -	platform_set_drvdata(dev, info);
> -
> -	/* now we have registered we can safely setup the hardware */
> -	out_8(AP_CONTROL_3A, RESET_CREG);
> -	out_be16(AP_WRITE_ENABLE, 0x0);
> -	out_8(AP_CONTROL_0, NORMAL_MODE);
> -	out_8(AP_CONTROL_1, (AD_BLT | DST_EQ_SRC | NORM_CREG1));
> -	out_8(AP_CONTROL_2, S_DATA_PLN);
> -	out_be16(AP_ROP_1, SWAP(0x3));
> -
> -	printk("apollo frame buffer alive and kicking !\n");
> -	return err;
> -
> -release_framebuffer:
> -	framebuffer_release(info);
> -	return err;
> -}
> -
> -static struct platform_driver dnfb_driver = {
> -	.probe	= dnfb_probe,
> -	.driver	= {
> -		.name	= "dnfb",
> -	},
> -};
> -
> -static struct platform_device dnfb_device = {
> -	.name	= "dnfb",
> -};
> -
> -static int __init dnfb_init(void)
> -{
> -	int ret;
> -
> -	if (!MACH_IS_APOLLO)
> -		return -ENODEV;
> -
> -	if (fb_get_options("dnfb", NULL))
> -		return -ENODEV;
> -
> -	ret = platform_driver_register(&dnfb_driver);
> -
> -	if (!ret) {
> -		ret = platform_device_register(&dnfb_device);
> -		if (ret)
> -			platform_driver_unregister(&dnfb_driver);
> -	}
> -	return ret;
> -}
> -
> -module_init(dnfb_init);
> -
> -MODULE_LICENSE("GPL");

-- 
--
Thomas Zimmermann
Graphics Driver Developer
SUSE Software Solutions Germany GmbH
Frankenstr. 146, 90461 Nürnberg, Germany, www.suse.com
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich, (HRB 36809, AG Nürnberg)



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox