From: Danilo Krummrich Date: Sun, 15 Mar 2026 20:55:47 +0000 (+0100) Subject: Merge tag 'v7.0-rc4' into drm-rust-next X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=76bce7ac51673640a4a46236ea723cf5543268d7;p=thirdparty%2Flinux.git Merge tag 'v7.0-rc4' into drm-rust-next We need the latest fixes from drm-rust-fixes in drm-rust-next as well to build on top of. Signed-off-by: Danilo Krummrich --- 76bce7ac51673640a4a46236ea723cf5543268d7 diff --cc drivers/gpu/nova-core/gsp/cmdq.rs index e0b096546d233,03a4f35998498..efa1aab1568f2 --- a/drivers/gpu/nova-core/gsp/cmdq.rs +++ b/drivers/gpu/nova-core/gsp/cmdq.rs @@@ -1,14 -1,9 +1,8 @@@ // SPDX-License-Identifier: GPL-2.0 -use core::{ - cmp, - mem, // -}; +mod continuation; + - use core::{ - mem, - sync::atomic::{ - fence, - Ordering, // - }, // - }; ++use core::mem; use kernel::{ device, @@@ -170,21 -154,24 +165,26 @@@ pub(super) struct Msgq /// Structure shared between the driver and the GSP and containing the command and message queues. #[repr(C)] - struct GspMem { + // TODO: Revert to private once `IoView` projections replace the `gsp_mem` module. + pub(super) struct GspMem { /// Self-mapping page table entries. - ptes: PteArray<{ GSP_PAGE_SIZE / size_of::() }>, + ptes: PteArray<{ Self::PTE_ARRAY_SIZE }>, /// CPU queue: the driver writes commands here, and the GSP reads them. It also contains the - /// write and read pointers that the CPU updates. + /// write and read pointers that the CPU updates. This means that the read pointer here is an + /// index into the GSP queue. /// /// This member is read-only for the GSP. - cpuq: Msgq, + pub(super) cpuq: Msgq, /// GSP queue: the GSP writes messages here, and the driver reads them. It also contains the - /// write and read pointers that the GSP updates. + /// write and read pointers that the GSP updates. This means that the read pointer here is an + /// index into the CPU queue. /// /// This member is read-only for the driver. - gspq: Msgq, + pub(super) gspq: Msgq, + } + + impl GspMem { + const PTE_ARRAY_SIZE: usize = GSP_PAGE_SIZE / size_of::(); } // SAFETY: These structs don't meet the no-padding requirements of AsBytes but @@@ -359,42 -327,27 +369,27 @@@ impl DmaGspMem // // # Invariants // - // - The returned value is between `0` and `MSGQ_NUM_PAGES`. + // - The returned value is within `0..MSGQ_NUM_PAGES`. fn gsp_write_ptr(&self) -> u32 { - let gsp_mem = self.0.start_ptr(); - - // SAFETY: - // - The 'CoherentAllocation' contains at least one object. - // - By the invariants of `CoherentAllocation` the pointer is valid. - (unsafe { (*gsp_mem).gspq.tx.write_ptr() } % MSGQ_NUM_PAGES) + super::fw::gsp_mem::gsp_write_ptr(&self.0) } // Returns the index of the memory page the GSP will read the next command from. // // # Invariants // - // - The returned value is between `0` and `MSGQ_NUM_PAGES`. + // - The returned value is within `0..MSGQ_NUM_PAGES`. fn gsp_read_ptr(&self) -> u32 { - let gsp_mem = self.0.start_ptr(); - - // SAFETY: - // - The 'CoherentAllocation' contains at least one object. - // - By the invariants of `CoherentAllocation` the pointer is valid. - (unsafe { (*gsp_mem).gspq.rx.read_ptr() } % MSGQ_NUM_PAGES) + super::fw::gsp_mem::gsp_read_ptr(&self.0) } // Returns the index of the memory page the CPU can read the next message from. // // # Invariants // - // - The returned value is between `0` and `MSGQ_NUM_PAGES`. + // - The returned value is within `0..MSGQ_NUM_PAGES`. fn cpu_read_ptr(&self) -> u32 { - let gsp_mem = self.0.start_ptr(); - - // SAFETY: - // - The ['CoherentAllocation'] contains at least one object. - // - By the invariants of CoherentAllocation the pointer is valid. - (unsafe { (*gsp_mem).cpuq.rx.read_ptr() } % MSGQ_NUM_PAGES) + super::fw::gsp_mem::cpu_read_ptr(&self.0) } // Informs the GSP that it can send `elem_count` new pages into the message queue. @@@ -416,14 -359,9 +401,9 @@@ // // # Invariants // - // - The returned value is between `0` and `MSGQ_NUM_PAGES`. + // - The returned value is within `0..MSGQ_NUM_PAGES`. fn cpu_write_ptr(&self) -> u32 { - let gsp_mem = self.0.start_ptr(); - - // SAFETY: - // - The 'CoherentAllocation' contains at least one object. - // - By the invariants of `CoherentAllocation` the pointer is valid. - (unsafe { (*gsp_mem).cpuq.tx.write_ptr() } % MSGQ_NUM_PAGES) + super::fw::gsp_mem::cpu_write_ptr(&self.0) } // Informs the GSP that it can process `elem_count` new pages from the command queue. diff --cc drivers/gpu/nova-core/gsp/fw.rs index 25fca1f6db2c8,040b30ec3089b..a061131b54125 --- a/drivers/gpu/nova-core/gsp/fw.rs +++ b/drivers/gpu/nova-core/gsp/fw.rs @@@ -39,10 -40,75 +39,79 @@@ use crate:: }, }; + // TODO: Replace with `IoView` projections once available; the `unwrap()` calls go away once we + // switch to the new `dma::Coherent` API. + pub(super) mod gsp_mem { + use core::sync::atomic::{ + fence, + Ordering, // + }; + + use kernel::{ + dma::CoherentAllocation, + dma_read, + dma_write, + prelude::*, // + }; + + use crate::gsp::cmdq::{ + GspMem, + MSGQ_NUM_PAGES, // + }; + + pub(in crate::gsp) fn gsp_write_ptr(qs: &CoherentAllocation) -> u32 { + // PANIC: A `dma::CoherentAllocation` always contains at least one element. + || -> Result { Ok(dma_read!(qs, [0]?.gspq.tx.0.writePtr) % MSGQ_NUM_PAGES) }().unwrap() + } + + pub(in crate::gsp) fn gsp_read_ptr(qs: &CoherentAllocation) -> u32 { + // PANIC: A `dma::CoherentAllocation` always contains at least one element. + || -> Result { Ok(dma_read!(qs, [0]?.gspq.rx.0.readPtr) % MSGQ_NUM_PAGES) }().unwrap() + } + + pub(in crate::gsp) fn cpu_read_ptr(qs: &CoherentAllocation) -> u32 { + // PANIC: A `dma::CoherentAllocation` always contains at least one element. + || -> Result { Ok(dma_read!(qs, [0]?.cpuq.rx.0.readPtr) % MSGQ_NUM_PAGES) }().unwrap() + } + + pub(in crate::gsp) fn advance_cpu_read_ptr(qs: &CoherentAllocation, count: u32) { + let rptr = cpu_read_ptr(qs).wrapping_add(count) % MSGQ_NUM_PAGES; + + // Ensure read pointer is properly ordered. + fence(Ordering::SeqCst); + + // PANIC: A `dma::CoherentAllocation` always contains at least one element. + || -> Result { + dma_write!(qs, [0]?.cpuq.rx.0.readPtr, rptr); + Ok(()) + }() + .unwrap() + } + + pub(in crate::gsp) fn cpu_write_ptr(qs: &CoherentAllocation) -> u32 { + // PANIC: A `dma::CoherentAllocation` always contains at least one element. + || -> Result { Ok(dma_read!(qs, [0]?.cpuq.tx.0.writePtr) % MSGQ_NUM_PAGES) }().unwrap() + } + + pub(in crate::gsp) fn advance_cpu_write_ptr(qs: &CoherentAllocation, count: u32) { + let wptr = cpu_write_ptr(qs).wrapping_add(count) % MSGQ_NUM_PAGES; + + // PANIC: A `dma::CoherentAllocation` always contains at least one element. + || -> Result { + dma_write!(qs, [0]?.cpuq.tx.0.writePtr, wptr); + Ok(()) + }() + .unwrap(); + + // Ensure all command data is visible before triggering the GSP read. + fence(Ordering::SeqCst); + } + } + +/// Maximum size of a single GSP message queue element in bytes. +pub(crate) const GSP_MSG_QUEUE_ELEMENT_SIZE_MAX: usize = + num::u32_as_usize(bindings::GSP_MSG_QUEUE_ELEMENT_SIZE_MAX); + /// Empty type to group methods related to heap parameters for running the GSP firmware. enum GspFwHeapParams {}