]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/usb/gadget/s3c-hsotg.c
USB: s3c-hsotg: Fix OUT packet request retry
[net-next-2.6.git] / drivers / usb / gadget / s3c-hsotg.c
index 552ec899500acde89421392b8aa30c06e4ef4fe4..825b6ca62941b346ecc9729871900e2922659b5d 100644 (file)
@@ -1383,6 +1383,9 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
        read_ptr = hs_req->req.actual;
        max_req = hs_req->req.length - read_ptr;
 
+       dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
+               __func__, to_read, max_req, read_ptr, hs_req->req.length);
+
        if (to_read > max_req) {
                /* more data appeared than we where willing
                 * 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)
                WARN_ON_ONCE(1);
        }
 
-       dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n",
-               __func__, to_read, max_req, read_ptr, hs_req->req.length);
-
        hs_ep->total_data += to_read;
        hs_req->req.actual += to_read;
        to_read = DIV_ROUND_UP(to_read, 4);
@@ -1463,9 +1463,11 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
 static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
                                     int epnum, bool was_setup)
 {
+       u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
        struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum];
        struct s3c_hsotg_req *hs_req = hs_ep->req;
        struct usb_request *req = &hs_req->req;
+       unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
        int result = 0;
 
        if (!hs_req) {
@@ -1474,9 +1476,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
        }
 
        if (using_dma(hsotg)) {
-               u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
                unsigned size_done;
-               unsigned size_left;
 
                /* Calculate the size of the transfer by checking how much
                 * 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,
                 * so may overshoot/undershoot the transfer.
                 */
 
-               size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
-
                size_done = hs_ep->size_loaded - size_left;
                size_done += hs_ep->last_load;
 
                req->actual = size_done;
        }
 
+       /* if there is more request to do, schedule new transfer */
+       if (req->actual < req->length && size_left == 0) {
+               s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true);
+               return;
+       }
+
        if (req->actual < req->length && req->short_not_ok) {
                dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
                        __func__, req->actual, req->length);