forked from Minki/linux
usb:hsotg:samsung: Sending ZLP packet for IN EP0 transfers
This commit targets following scenarios for IN requests: 1. HOST requests e.g. 256B (which is a multiple of MPS = 64B). Then NO ZLP shall be sent, since host expects exact number of bytes. 2. HOST requested 4096B, but our data for sending is 256B. In this situation ZLP shall be send to tell HOST that no more data is available and it shall not wait for more data. This prevents HOST from hanging. Tested with: - DFU gadget (various size of the sent data - also packet = MPS) - Ethernet gadget (CDC and RNDIS) - Multi Function Gadget (g_multi) HW: - Samsung's C210 Universal rev.0 - Samsung's C110 GONI Signed-off-by: Lukasz Majewski <l.majewski@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
71225beeeb
commit
d3ca0259c5
@ -1555,6 +1555,10 @@ static void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg,
|
||||
}
|
||||
|
||||
if (epnum == 0) {
|
||||
/*
|
||||
* Condition req->complete != s3c_hsotg_complete_setup says:
|
||||
* send ZLP when we have an asynchronous request from gadget
|
||||
*/
|
||||
if (!was_setup && req->complete != s3c_hsotg_complete_setup)
|
||||
s3c_hsotg_send_zlp(hsotg, hs_req);
|
||||
}
|
||||
@ -1809,6 +1813,13 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finish ZLP handling for IN EP0 transactions */
|
||||
if (hsotg->eps[0].sent_zlp) {
|
||||
dev_dbg(hsotg->dev, "zlp packet received\n");
|
||||
s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate the size of the transfer by checking how much is left
|
||||
* in the endpoint size register and then working it out from
|
||||
* the amount we loaded for the transfer.
|
||||
@ -1828,9 +1839,28 @@ static void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg,
|
||||
__func__, hs_req->req.actual, size_done);
|
||||
|
||||
hs_req->req.actual = size_done;
|
||||
dev_dbg(hsotg->dev, "req->length:%d req->actual:%d req->zero:%d\n",
|
||||
hs_req->req.length, hs_req->req.actual, hs_req->req.zero);
|
||||
|
||||
/* if we did all of the transfer, and there is more data left
|
||||
* around, then try restarting the rest of the request */
|
||||
/*
|
||||
* Check if dealing with Maximum Packet Size(MPS) IN transfer at EP0
|
||||
* When sent data is a multiple MPS size (e.g. 64B ,128B ,192B
|
||||
* ,256B ... ), after last MPS sized packet send IN ZLP packet to
|
||||
* inform the host that no more data is available.
|
||||
* The state of req.zero member is checked to be sure that the value to
|
||||
* send is smaller than wValue expected from host.
|
||||
* Check req.length to NOT send another ZLP when the current one is
|
||||
* under completion (the one for which this completion has been called).
|
||||
*/
|
||||
if (hs_req->req.length && hs_ep->index == 0 && hs_req->req.zero &&
|
||||
hs_req->req.length == hs_req->req.actual &&
|
||||
!(hs_req->req.length % hs_ep->ep.maxpacket)) {
|
||||
|
||||
dev_dbg(hsotg->dev, "ep0 zlp IN packet sent\n");
|
||||
s3c_hsotg_send_zlp(hsotg, hs_req);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!size_left && hs_req->req.actual < hs_req->req.length) {
|
||||
dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__);
|
||||
|
Loading…
Reference in New Issue
Block a user