drivers/gpu/nova-core/gsp/cmdq/continuation.rs

Source file repositories/reference/linux-study-clean/drivers/gpu/nova-core/gsp/cmdq/continuation.rs

File Facts

System
Linux kernel
Corpus path
drivers/gpu/nova-core/gsp/cmdq/continuation.rs
Extension
.rs
Size
9271 bytes
Lines
308
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct TestPayload {
        data: KVVec<u8>,
    }

    impl TestPayload {
        fn generate_pattern(len: usize) -> Result<KVVec<u8>> {
            let mut data = KVVec::with_capacity(len, GFP_KERNEL)?;
            for i in 0..len {
                // Mix in higher bits so the pattern does not repeat every 256 bytes.
                data.push((i ^ (i >> 8)) as u8, GFP_KERNEL)?;
            }
            Ok(data)
        }

        fn new(len: usize) -> Result<Self> {
            Ok(Self {
                data: Self::generate_pattern(len)?,
            })
        }
    }

    impl CommandToGsp for TestPayload {
        const FUNCTION: MsgFunction = MsgFunction::Nop;
        type Command = TestHeader;
        type Reply = NoReply;
        type InitError = Infallible;

        fn init(&self) -> impl Init<Self::Command, Self::InitError> {
            TestHeader::init_zeroed()
        }

        fn variable_payload_len(&self) -> usize {
            self.data.len()
        }

        fn init_variable_payload(
            &self,
            dst: &mut SBufferIter<core::array::IntoIter<&mut [u8], 2>>,
        ) -> Result {
            dst.write_all(self.data.as_slice())
        }
    }

    /// Maximum variable payload size that fits in the first command alongside the header.
    const MAX_FIRST_PAYLOAD: usize = SplitState::<TestPayload>::MAX_FIRST_PAYLOAD;

    fn read_payload(cmd: impl CommandToGsp) -> Result<KVVec<u8>> {
        let len = cmd.variable_payload_len();
        let mut buf = KVVec::from_elem(0u8, len, GFP_KERNEL)?;
        let mut sbuf = SBufferIter::new_writer([buf.as_mut_slice(), &mut []]);
        cmd.init_variable_payload(&mut sbuf)?;
        drop(sbuf);
        Ok(buf)
    }

    struct SplitTest {
        payload_size: usize,
        num_continuations: usize,
    }

    fn check_split(t: SplitTest) -> Result {
        let payload = TestPayload::new(t.payload_size)?;
        let mut num_continuations = 0;

        let buf = match SplitState::new(payload)? {
            SplitState::Single(cmd) => read_payload(cmd)?,
            SplitState::Split(cmd, mut continuations) => {
                let mut buf = read_payload(cmd)?;
                assert!(size_of::<TestHeader>() + buf.len() <= MAX_CMD_SIZE);

                while let Some(cont) = continuations.next() {
                    let payload = read_payload(cont)?;
                    assert!(payload.len() <= MAX_CMD_SIZE);
                    buf.extend_from_slice(&payload, GFP_KERNEL)?;
                    num_continuations += 1;
                }

                buf
            }
        };

        assert_eq!(num_continuations, t.num_continuations);
        assert_eq!(
            buf.as_slice(),
            TestPayload::generate_pattern(t.payload_size)?.as_slice()
        );
        Ok(())
    }

    #[test]

Annotation

Implementation Notes