aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2012-04-01 03:17:16 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-01 03:12:58 -0400
commitbaf4c528447b128512a26ed270604db362106005 (patch)
tree35486f5f6edb2a86a27c431ed937737789a7e4f5 /drivers/usb/gadget
parenta6d78a4766a733dd2618fe122b354ad536228941 (diff)
usb: gadget: fsl_udc_core: dTD's next dtd pointer need to be updated once written
commit 4d0947dec4db1224354e2f6f00ae22ce38e62a43 upstream. dTD's next dtd pointer need to be updated once CPU writes it, or this request may not be handled by controller, then host will get NAK from device forever. This problem occurs when there is a request is handling, we need to add a new request to dTD list, if this new request is added before the current one is finished, the new request is intended to added as next dtd pointer at current dTD, but without wmb(), the dTD's next dtd pointer may not be updated when the controller reads it. In that case, the controller will still get Terminate Bit is 1 at dTD's next dtd pointer, that means there is no next request, then this new request is missed by controller. Signed-off-by: Peter Chen <peter.chen@freescale.com> Acked-by: Li Yang <leoli@freescale.com> Signed-off-by: Felipe Balbi <balbi@ti.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 530838103d4..44d789d27cf 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -717,6 +717,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
717 lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); 717 lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
718 lastreq->tail->next_td_ptr = 718 lastreq->tail->next_td_ptr =
719 cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); 719 cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
720 /* Ensure dTD's next dtd pointer to be updated */
721 wmb();
720 /* Read prime bit, if 1 goto done */ 722 /* Read prime bit, if 1 goto done */
721 if (fsl_readl(&dr_regs->endpointprime) & bitmask) 723 if (fsl_readl(&dr_regs->endpointprime) & bitmask)
722 goto out; 724 goto out;