On Thu, Sep 28, 2023 at 11:06:03PM +0200, Michał Mirosław wrote: > The USB host on Tegra3 works with 32-bit alignment. Previous code tried > to align the buffer, but it did align the wrapper struct instead, so > the buffer was at a constant offset of 8 bytes (two pointers) from > expected alignment. Since kmalloc() guarantees at least 8-byte > alignment already, the alignment-extending is removed. > > Fixes: fc53d5279094 ("usb: chipidea: tegra: Support host mode") > Signed-off-by: Michał Mirosław <mirq-linux@xxxxxxxxxxxx> > --- > drivers/usb/chipidea/host.c | 45 +++++++++++++++---------------------- > 1 file changed, 18 insertions(+), 27 deletions(-) > > diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c > index abddd39d1ff1..0cce19208370 100644 > --- a/drivers/usb/chipidea/host.c > +++ b/drivers/usb/chipidea/host.c > @@ -30,8 +30,7 @@ struct ehci_ci_priv { > }; > > struct ci_hdrc_dma_aligned_buffer { > - void *kmalloc_ptr; > - void *old_xfer_buffer; > + void *original_buffer; > u8 data[]; > }; > > @@ -380,60 +379,52 @@ static int ci_ehci_bus_suspend(struct usb_hcd *hcd) > return 0; > } > > -static void ci_hdrc_free_dma_aligned_buffer(struct urb *urb) > +static void ci_hdrc_free_dma_aligned_buffer(struct urb *urb, bool copy_back) > { > struct ci_hdrc_dma_aligned_buffer *temp; > - size_t length; > > if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER)) > return; > + urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; This threw me off a bit until I realized it was already there previously, just in a different place. Is there a particular reason why this is moved? Regardless, this looks fine, so: Acked-by: Thierry Reding <treding@xxxxxxxxxx> > > temp = container_of(urb->transfer_buffer, > struct ci_hdrc_dma_aligned_buffer, data); > + urb->transfer_buffer = temp->original_buffer; > + > + if (copy_back && usb_urb_dir_in(urb)) { > + size_t length; > > - if (usb_urb_dir_in(urb)) { > if (usb_pipeisoc(urb->pipe)) > length = urb->transfer_buffer_length; > else > length = urb->actual_length; > > - memcpy(temp->old_xfer_buffer, temp->data, length); > + memcpy(temp->original_buffer, temp->data, length); > } > - urb->transfer_buffer = temp->old_xfer_buffer; > - kfree(temp->kmalloc_ptr); > > - urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER; > + kfree(temp); > } > > static int ci_hdrc_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) > { > - struct ci_hdrc_dma_aligned_buffer *temp, *kmalloc_ptr; > - const unsigned int ci_hdrc_usb_dma_align = 32; > - size_t kmalloc_size; > + struct ci_hdrc_dma_aligned_buffer *temp; > > if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0) > return 0; > - if (!((uintptr_t)urb->transfer_buffer & (ci_hdrc_usb_dma_align - 1)) && !(urb->transfer_buffer_length & 3)) > + if (IS_ALIGNED((uintptr_t)urb->transfer_buffer, 4) > + && IS_ALIGNED(urb->transfer_buffer_length, 4)) > return 0; > > - /* Allocate a buffer with enough padding for alignment */ > - kmalloc_size = ALIGN(urb->transfer_buffer_length, 4) + > - sizeof(struct ci_hdrc_dma_aligned_buffer) + > - ci_hdrc_usb_dma_align - 1; > - > - kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); > - if (!kmalloc_ptr) > + temp = kmalloc(sizeof(*temp) + ALIGN(urb->transfer_buffer_length, 4), mem_flags); > + if (!temp) > return -ENOMEM; > > - /* Position our struct dma_aligned_buffer such that data is aligned */ > - temp = PTR_ALIGN(kmalloc_ptr + 1, ci_hdrc_usb_dma_align) - 1; > - temp->kmalloc_ptr = kmalloc_ptr; > - temp->old_xfer_buffer = urb->transfer_buffer; > if (usb_urb_dir_out(urb)) > memcpy(temp->data, urb->transfer_buffer, > urb->transfer_buffer_length); > + > + temp->original_buffer = urb->transfer_buffer; > urb->transfer_buffer = temp->data; > - > urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER; > > return 0; > @@ -450,7 +441,7 @@ static int ci_hdrc_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, > > ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags); > if (ret) > - ci_hdrc_free_dma_aligned_buffer(urb); > + ci_hdrc_free_dma_aligned_buffer(urb, false); > > return ret; > } > @@ -458,7 +449,7 @@ static int ci_hdrc_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, > static void ci_hdrc_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb) > { > usb_hcd_unmap_urb_for_dma(hcd, urb); > - ci_hdrc_free_dma_aligned_buffer(urb); > + ci_hdrc_free_dma_aligned_buffer(urb, true); > } > > #ifdef CONFIG_PM_SLEEP > -- > 2.39.2 >
Attachment:
signature.asc
Description: PGP signature