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>
This commit is contained in:
parent
b05ca580c3
commit
a33e7136e9
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user