aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/mv_udc_core.c
diff options
context:
space:
mode:
authorNeil Zhang <zhangwm@marvell.com>2011-10-12 04:49:36 -0400
committerFelipe Balbi <balbi@ti.com>2011-10-13 13:42:06 -0400
commitdaec765da767e4a6a30e1298862b28f2cae9a73f (patch)
treeaf15335fc0121b7e9b36519c6dafa5976ea587d8 /drivers/usb/gadget/mv_udc_core.c
parent046b07ac0458fba8c5ca8d9ee04658c02066ee03 (diff)
usb: gadget: mv_udc: fix dtd dma confusion
The controller will prime failure sometimes when do the iperf test. Add delay to wait controller release dtd dma before we free it. Then the issue is gone. Signed-off-by: Neil Zhang <zhangwm@marvell.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/gadget/mv_udc_core.c')
-rw-r--r--drivers/usb/gadget/mv_udc_core.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index ffa6f3097a6..9d960f1f7c7 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -138,6 +138,7 @@ static int process_ep_req(struct mv_udc *udc, int index,
138 int i, direction; 138 int i, direction;
139 int retval = 0; 139 int retval = 0;
140 u32 errors; 140 u32 errors;
141 u32 bit_pos;
141 142
142 curr_dqh = &udc->ep_dqh[index]; 143 curr_dqh = &udc->ep_dqh[index];
143 direction = index % 2; 144 direction = index % 2;
@@ -155,10 +156,20 @@ static int process_ep_req(struct mv_udc *udc, int index,
155 156
156 errors = curr_dtd->size_ioc_sts & DTD_ERROR_MASK; 157 errors = curr_dtd->size_ioc_sts & DTD_ERROR_MASK;
157 if (!errors) { 158 if (!errors) {
158 remaining_length += 159 remaining_length =
159 (curr_dtd->size_ioc_sts & DTD_PACKET_SIZE) 160 (curr_dtd->size_ioc_sts & DTD_PACKET_SIZE)
160 >> DTD_LENGTH_BIT_POS; 161 >> DTD_LENGTH_BIT_POS;
161 actual -= remaining_length; 162 actual -= remaining_length;
163
164 if (remaining_length) {
165 if (direction) {
166 dev_dbg(&udc->dev->dev,
167 "TX dTD remains data\n");
168 retval = -EPROTO;
169 break;
170 } else
171 break;
172 }
162 } else { 173 } else {
163 dev_info(&udc->dev->dev, 174 dev_info(&udc->dev->dev,
164 "complete_tr error: ep=%d %s: error = 0x%x\n", 175 "complete_tr error: ep=%d %s: error = 0x%x\n",
@@ -180,6 +191,20 @@ static int process_ep_req(struct mv_udc *udc, int index,
180 if (retval) 191 if (retval)
181 return retval; 192 return retval;
182 193
194 if (direction == EP_DIR_OUT)
195 bit_pos = 1 << curr_req->ep->ep_num;
196 else
197 bit_pos = 1 << (16 + curr_req->ep->ep_num);
198
199 while ((curr_dqh->curr_dtd_ptr == curr_dtd->td_dma)) {
200 if (curr_dtd->dtd_next == EP_QUEUE_HEAD_NEXT_TERMINATE) {
201 while (readl(&udc->op_regs->epstatus) & bit_pos)
202 udelay(1);
203 break;
204 }
205 udelay(1);
206 }
207
183 curr_req->req.actual = actual; 208 curr_req->req.actual = actual;
184 209
185 return 0; 210 return 0;