On Wed, Apr 23, 2025 at 10:52:42AM -0400, Joel Fernandes wrote: > Hello, Danilo, > Thanks for all the feedback. Due to the volume of feedback, I will respond > incrementally in multiple emails so we can discuss as we go - hope that's Ok > but > let me know if that is annoying.
That's perfectly fine, whatever works best for you. :) > On 4/23/2025 10:06 AM, Danilo Krummrich wrote: > > >> +impl Vbios { > >> + /// Read bytes from the ROM at the current end of the data vector > >> + fn read_more(bar0: &Devres<Bar0>, data: &mut KVec<u8>, len: usize) -> > >> Result { > >> + let current_len = data.len(); > >> + let start = ROM_OFFSET + current_len; > >> + > >> + // Ensure length is a multiple of 4 for 32-bit reads > >> + if len % core::mem::size_of::<u32>() != 0 { > >> + pr_err!("VBIOS read length {} is not a multiple of 4\n", len); > > > > Please don't use any of the pr_*() print macros within a driver, use the > > dev_*() > > ones instead. > > Ok I'll switch to this. One slight complication is I've to retrieve the 'dev' > from the Bar0 and pass that along, but that should be doable. You can also pass the pci::Device reference to VBios::probe() directly. > > > > >> + return Err(EINVAL); > >> + } > >> + > >> + // Allocate and zero-initialize the required memory > > > > That's obvious from the code, if you feel this needs a comment, better > > explain > > what we need it for, why zero-initialize, etc. > > Sure, actually the extends_with() is a performance optimization as we want to > do > only a single allocation and then fill in the allocated data. It has nothing > to > do with 0-initializing per-se. I will adjust the comment, but: > > This code... > > >> + 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