]>
Commit | Line | Data |
---|---|---|
a13f3828 GKH |
1 | From 4d0947dec4db1224354e2f6f00ae22ce38e62a43 Mon Sep 17 00:00:00 2001 |
2 | From: Peter Chen <peter.chen@freescale.com> | |
3 | Date: Sun, 1 Apr 2012 15:17:16 +0800 | |
4 | Subject: usb: gadget: fsl_udc_core: dTD's next dtd pointer need to be updated once written | |
5 | ||
6 | From: Peter Chen <peter.chen@freescale.com> | |
7 | ||
8 | commit 4d0947dec4db1224354e2f6f00ae22ce38e62a43 upstream. | |
9 | ||
10 | dTD's next dtd pointer need to be updated once CPU writes it, or this | |
11 | request may not be handled by controller, then host will get NAK from | |
12 | device forever. | |
13 | ||
14 | This problem occurs when there is a request is handling, we need to add | |
15 | a new request to dTD list, if this new request is added before the current | |
16 | one is finished, the new request is intended to added as next dtd pointer | |
17 | at current dTD, but without wmb(), the dTD's next dtd pointer may not be | |
18 | updated when the controller reads it. In that case, the controller will | |
19 | still get Terminate Bit is 1 at dTD's next dtd pointer, that means there is | |
20 | no next request, then this new request is missed by controller. | |
21 | ||
22 | Signed-off-by: Peter Chen <peter.chen@freescale.com> | |
23 | Acked-by: Li Yang <leoli@freescale.com> | |
24 | Signed-off-by: Felipe Balbi <balbi@ti.com> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | ||
27 | --- | |
28 | drivers/usb/gadget/fsl_udc_core.c | 2 ++ | |
29 | 1 file changed, 2 insertions(+) | |
30 | ||
31 | --- a/drivers/usb/gadget/fsl_udc_core.c | |
32 | +++ b/drivers/usb/gadget/fsl_udc_core.c | |
33 | @@ -717,6 +717,8 @@ static void fsl_queue_td(struct fsl_ep * | |
34 | lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); | |
35 | lastreq->tail->next_td_ptr = | |
36 | cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); | |
37 | + /* Ensure dTD's next dtd pointer to be updated */ | |
38 | + wmb(); | |
39 | /* Read prime bit, if 1 goto done */ | |
40 | if (fsl_readl(&dr_regs->endpointprime) & bitmask) | |
41 | goto out; |