aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2010-07-19 04:40:49 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-10 17:35:43 -0400
commita33e7136e9652374f7d54ded3cff8062d8e1e84f (patch)
treed6f77178c4546293a4d2c09a87106e881243da44 /drivers
parentb05ca580c39314c8527e2e1c36a823970cc01683 (diff)
USB: s3c-hsotg: Fix OUT packet request retry
If there is more data in the request than we could fit into a single hardware request, then check when the OutDone event is received if we have more data, and if so, schedule the new data instead of trying to complete the request (and in the case of EP0, sending a 0 packet in the middle of a transfer). Also, move the debug message about the current transfer state before the warning about a bad transfer. Signed-off-by: Ben Dooks <ben-linux@fluff.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/s3c-hsotg.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 552ec899500..825b6ca6294 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -1383,6 +1383,9 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
1383 read_ptr = hs_req->req.actual; 1383 read_ptr = hs_req->req.actual;
1384 max_req = hs_req->req.length - read_ptr; 1384 max_req = hs_req->req.length - read_ptr;
1385 1385
1386 dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
1387 __func__, to_read, max_req, read_ptr, hs_req->req.length);
1388
1386 if (to_read > max_req) { 1389 if (to_read > max_req) {
1387 /* more data appeared than we where willing 1390 /* more data appeared than we where willing
1388 * to deal with in this request. 1391 * to deal with in this request.
@@ -1392,9 +1395,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
1392 WARN_ON_ONCE(1); 1395 WARN_ON_ONCE(1);
1393 } 1396 }
1394 1397
1395 dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
1396 __func__, to_read, max_req, read_ptr, hs_req->req.length);
1397
1398 hs_ep->total_data += to_read; 1398 hs_ep->total_data += to_read;
1399 hs_req->req.actual += to_read; 1399 hs_req->req.actual += to_read;
1400 to_read = DIV_ROUND_UP(to_read, 4); 1400 to_read = DIV_ROUND_UP(to_read, 4);
@@ -1463,9 +1463,11 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
1463static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, 1463static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
1464 int epnum, bool was_setup) 1464 int epnum, bool was_setup)
1465{ 1465{
1466 u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
1466 struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; 1467 struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
1467 struct s3c_hsotg_req *hs_req = hs_ep->req; 1468 struct s3c_hsotg_req *hs_req = hs_ep->req;
1468 struct usb_request *req = &hs_req->req; 1469 struct usb_request *req = &hs_req->req;
1470 unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
1469 int result = 0; 1471 int result = 0;
1470 1472
1471 if (!hs_req) { 1473 if (!hs_req) {
@@ -1474,9 +1476,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
1474 } 1476 }
1475 1477
1476 if (using_dma(hsotg)) { 1478 if (using_dma(hsotg)) {
1477 u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
1478 unsigned size_done; 1479 unsigned size_done;
1479 unsigned size_left;
1480 1480
1481 /* Calculate the size of the transfer by checking how much 1481 /* Calculate the size of the transfer by checking how much
1482 * is left in the endpoint size register and then working it 1482 * is left in the endpoint size register and then working it
@@ -1486,14 +1486,18 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
1486 * so may overshoot/undershoot the transfer. 1486 * so may overshoot/undershoot the transfer.
1487 */ 1487 */
1488 1488
1489 size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
1490
1491 size_done = hs_ep->size_loaded - size_left; 1489 size_done = hs_ep->size_loaded - size_left;
1492 size_done += hs_ep->last_load; 1490 size_done += hs_ep->last_load;
1493 1491
1494 req->actual = size_done; 1492 req->actual = size_done;
1495 } 1493 }
1496 1494
1495 /* if there is more request to do, schedule new transfer */
1496 if (req->actual < req->length && size_left == 0) {
1497 s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
1498 return;
1499 }
1500
1497 if (req->actual < req->length && req->short_not_ok) { 1501 if (req->actual < req->length && req->short_not_ok) {
1498 dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", 1502 dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
1499 __func__, req->actual, req->length); 1503 __func__, req->actual, req->length);