Commit a33e7136 authored by Ben Dooks's avatar Ben Dooks Committed by Greg Kroah-Hartman

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: default avatarBen Dooks <ben-linux@fluff.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent b05ca580
...@@ -1383,6 +1383,9 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) ...@@ -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; read_ptr = hs_req->req.actual;
max_req = hs_req->req.length - read_ptr; 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) { if (to_read > max_req) {
/* more data appeared than we where willing /* more data appeared than we where willing
* to deal with in this request. * 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,9 +1395,6 @@ static void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size)
WARN_ON_ONCE(1); 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_ep->total_data += to_read;
hs_req->req.actual += to_read; hs_req->req.actual += to_read;
to_read = DIV_ROUND_UP(to_read, 4); to_read = DIV_ROUND_UP(to_read, 4);
...@@ -1463,9 +1463,11 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, ...@@ -1463,9 +1463,11 @@ static void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg,
static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
int epnum, bool was_setup) 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_ep *hs_ep = &hsotg->eps[epnum];
struct s3c_hsotg_req *hs_req = hs_ep->req; struct s3c_hsotg_req *hs_req = hs_ep->req;
struct usb_request *req = &hs_req->req; struct usb_request *req = &hs_req->req;
unsigned size_left = S3C_DxEPTSIZ_XferSize_GET(epsize);
int result = 0; int result = 0;
if (!hs_req) { if (!hs_req) {
...@@ -1474,9 +1476,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, ...@@ -1474,9 +1476,7 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
} }
if (using_dma(hsotg)) { if (using_dma(hsotg)) {
u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum));
unsigned size_done; unsigned size_done;
unsigned size_left;
/* Calculate the size of the transfer by checking how much /* Calculate the size of the transfer by checking how much
* is left in the endpoint size register and then working it * 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,14 +1486,18 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
* so may overshoot/undershoot the transfer. * 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->size_loaded - size_left;
size_done += hs_ep->last_load; size_done += hs_ep->last_load;
req->actual = size_done; 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) { if (req->actual < req->length && req->short_not_ok) {
dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n",
__func__, req->actual, req->length); __func__, req->actual, req->length);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment