On Thu, Apr 24, 2025 at 03:19:00PM -0400, Joel Fernandes wrote:
> 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))?;
>              }

Looks good to me, thanks!

Reply via email to