On Wed, Apr 23, 2025 at 05:02:58PM +0200, Danilo Krummrich wrote: [..]
> > >> + data.extend_with(len, 0, GFP_KERNEL)?; > > >> + with_bar!(?bar0, |bar0_ref| { > > >> + let dst = &mut data[current_len..current_len + len]; > > >> + for (idx, chunk) in dst > > >> + .chunks_exact_mut(core::mem::size_of::<u32>()) > > >> + .enumerate() > > >> + { > > >> + let addr = start + (idx * core::mem::size_of::<u32>()); > > >> + // Convert the u32 to a 4 byte array. We use the > > >> .to_ne_bytes() > > >> + // method out of convenience to convert the 32-bit > > >> integer as it > > >> + // is in memory into a byte array without any endianness > > >> + // conversion or byte-swapping. > > >> + > > >> chunk.copy_from_slice(&bar0_ref.try_read32(addr)?.to_ne_bytes()); > > >> + } > > >> + Ok(()) > > >> + })?; > > >> + > > >> + Ok(()) > > >> + } > > ..actually initially was: > > > > + with_bar!(self.bar0, |bar0| { > > + // Get current length > > + let current_len = self.data.len(); > > + > > + // Read ROM data bytes push directly to vector > > + for i in 0..bytes as usize { > > + // Read byte from the VBIOS ROM and push it to the data > > vector > > + let rom_addr = ROM_OFFSET + current_len + i; > > + let byte = bar0.try_readb(rom_addr)?; > > + self.data.push(byte, GFP_KERNEL)?; > > > > Where this bit could result in a lot of allocation. > > > > There was an unsafe() way of not having to do this but we settled with > > extends_with(). > > > > Thoughts? > > If I understand you correctly, you just want to make sure that subsequent > push() > calls don't re-allocate? If so, you can just use reserve() [1] and keep the > subsequent push() calls. > > [1] > https://rust.docs.kernel.org/kernel/alloc/kvec/struct.Vec.html#method.reserve Ok that does turn out to be cleaner! I replaced it with the following and it works. Let me know if it looks good now? Here's a preview: - data.extend_with(len, 0, GFP_KERNEL)?; + data.reserve(len, GFP_KERNEL)?; + with_bar_res!(bar0, |bar0_ref| { - let dst = &mut data[current_len..current_len + len]; - for (idx, chunk) in dst - .chunks_exact_mut(core::mem::size_of::<u32>()) - .enumerate() - { - let addr = start + (idx * core::mem::size_of::<u32>()); - // Convert the u32 to a 4 byte array. We use the .to_ne_bytes() - // method out of convenience to convert the 32-bit integer as it - // is in memory into a byte array without any endianness - // conversion or byte-swapping. - chunk.copy_from_slice(&bar0_ref.try_read32(addr)?.to_ne_bytes()); + // Read ROM data bytes and push directly to vector + for i in 0..len { + // Read 32-bit word from the VBIOS ROM + let rom_addr = start + i * core::mem::size_of::<u32>(); + let word = bar0_ref.try_read32(rom_addr)?; + + // Convert the u32 to a 4 byte array and push each byte + word.to_ne_bytes().iter().try_for_each(|&b| data.push(b, GFP_KERNEL))?; } Thanks.