Hi Ricardo, Thank you for the patch. On Thu, Apr 04, 2024 at 05:56:18PM +0000, Ricardo Ribalda wrote: > Struct uvc_frame and interval (u32*) are packaged together on > streaming->formats on a single contiguous allocation. > > Right now they allocated right after uvc_format, without taking into s/they/they are/ > consideration their required alignment. > > This is working fine because both structures have a field with a > pointer, but it will stop working when the sizeof() of any of those > structs is not a multiple of the sizeof(void*). > > Enforce that alignment during the allocation. > > Signed-off-by: Ricardo Ribalda <ribalda@xxxxxxxxxxxx> > --- > This is better than 3 allocations, and do not have any performance > penalty. > > I have tried this patch printing the size and the address of the > pointers in the old and the new mode, and it looks the same. > > [ 2.235223] drivers/media/usb/uvc/uvc_driver.c:694 uvc_parse_streaming 432 > [ 2.235249] drivers/media/usb/uvc/uvc_driver.c:704 uvc_parse_streaming 432 > [ 2.235256] drivers/media/usb/uvc/uvc_driver.c:714 uvc_parse_streaming 00000000d32087cc 00000000d3803788 > [ 2.235265] drivers/media/usb/uvc/uvc_driver.c:720 uvc_parse_streaming 00000000d32087cc 00000000d3803788 > --- > Changes in v2: Thanks Laurent. > - Enforce alignment during allocation instead of using __aligned() > macros. > - Link to v1: https://lore.kernel.org/r/20230501-uvc-align-v1-1-0f713e4b84c3@xxxxxxxxxxxx > --- > drivers/media/usb/uvc/uvc_driver.c | 20 +++++++++++++++----- > 1 file changed, 15 insertions(+), 5 deletions(-) > > diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c > index 7aefa76a42b31..7d9844ba3b205 100644 > --- a/drivers/media/usb/uvc/uvc_driver.c > +++ b/drivers/media/usb/uvc/uvc_driver.c > @@ -663,16 +663,26 @@ static int uvc_parse_streaming(struct uvc_device *dev, > goto error; > } > > - size = nformats * sizeof(*format) + nframes * sizeof(*frame) > - + nintervals * sizeof(*interval); > + /* > + * Allocate memory for the formats, the frames and the intervals, > + * plus any required padding to guarantee that everything has the > + * correct alignment. > + */ > + size = nformats * sizeof(*format); > + size = ALIGN(size, __alignof__(*frame)) + nframes * sizeof(*frame); > + size = ALIGN(size, __alignof__(*interval)) > + + nintervals * sizeof(*interval); You have two extra spaces here. I'll fix when applying. Reviewed-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> > + > format = kzalloc(size, GFP_KERNEL); > - if (format == NULL) { > + if (!format) { > ret = -ENOMEM; > goto error; > } > > - frame = (struct uvc_frame *)&format[nformats]; > - interval = (u32 *)&frame[nframes]; > + frame = (void *)format + nformats * sizeof(*format); > + frame = PTR_ALIGN(frame, __alignof__(*frame)); > + interval = (void *)frame + nframes * sizeof(*frame); > + interval = PTR_ALIGN(interval, __alignof__(*interval)); > > streaming->format = format; > streaming->nformats = nformats; > > --- > base-commit: 58390c8ce1bddb6c623f62e7ed36383e7fa5c02f > change-id: 20230501-uvc-align-6ff202b68dab -- Regards, Laurent Pinchart