> > USB controller may access a wrong address for the dTD (endpoint transfer > descriptor) and then hang. This happens a lot when doing tests with > g_ether module and iperf, a tool for measuring maximum TCP and UDP > bandwidth. > > This hardware bug is explained in detail by errata number 2858 for i.MX23: > http://cache.freescale.com/files/dsp/doc/errata/IMX23CE.pdf > > All (?) SOCs with an IP from chipidea suffer from this problem. > mv_udc_core fixes this bug by commit daec765. There still may be > unfixed drivers. > > Signed-off-by: Christoph Fritz <chf.fritz@xxxxxxxxxxxxxx> > Signed-off-by: Christian Hemp <c.hemp@xxxxxxxxx> > --- > drivers/usb/gadget/fsl_udc_core.c | 15 ++++++++++++++- > 1 files changed, 14 insertions(+), 1 deletions(-) > > diff --git a/drivers/usb/gadget/fsl_udc_core.c > b/drivers/usb/gadget/fsl_udc_core.c > index 55abfb6..72f2139 100644 > --- a/drivers/usb/gadget/fsl_udc_core.c > +++ b/drivers/usb/gadget/fsl_udc_core.c > @@ -65,6 +65,8 @@ static struct usb_sys_interface *usb_sys_regs; > /* it is initialized in probe() */ > static struct fsl_udc *udc_controller = NULL; > > +static struct ep_td_struct *last_free_td; > + > static const struct usb_endpoint_descriptor > fsl_ep0_desc = { > .bLength = USB_DT_ENDPOINT_SIZE, > @@ -180,8 +182,13 @@ static void done(struct fsl_ep *ep, struct fsl_req > *req, int status) > curr_td = next_td; > if (j != req->dtd_count - 1) { > next_td = curr_td->next_td_virt; > + dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma); > + } else { > + if (last_free_td != NULL) > + dma_pool_free(udc->td_pool, last_free_td, > + last_free_td->td_dma); > + last_free_td = curr_td; > } > - dma_pool_free(udc->td_pool, curr_td, curr_td->td_dma); > } > > if (req->mapped) { > @@ -2579,6 +2586,8 @@ static int __init fsl_udc_probe(struct > platform_device *pdev) > goto err_unregister; > } > > + last_free_td = NULL; > + > ret = usb_add_gadget_udc(&pdev->dev, &udc_controller->gadget); > if (ret) > goto err_del_udc; > @@ -2633,6 +2642,10 @@ static int __exit fsl_udc_remove(struct > platform_device *pdev) > kfree(udc_controller->status_req); > kfree(udc_controller->eps); > > + if (last_free_td != NULL) > + dma_pool_free(udc_controller->td_pool, last_free_td, > + last_free_td->td_dma); > + > dma_pool_destroy(udc_controller->td_pool); > free_irq(udc_controller->irq, udc_controller); > iounmap(dr_regs); Reviewed-by: Peter Chen <peter.chen@xxxxxxxxxxxxx> > -- > 1.7.2.5 > > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html