forked from luck/tmp_suning_uos_patched
usb: dwc3: gadget: Return proper request status
commit c7428dbddcf4ea1919e1c8e15f715b94ca359268 upstream.
If the user sets the usb_request's no_interrupt, then there will be no
completion event for the request. Currently the driver incorrectly uses
the event status of a different request to report the status for a
request with no_interrupt. The dwc3 driver needs to check the TRB status
associated with the request when reporting its status.
Note: this is only applicable to missed_isoc TRB completion status, but
the other status are also listed for completeness/documentation.
Fixes: 6d8a019614
("usb: dwc3: gadget: check for Missed Isoc from event status")
Cc: <stable@vger.kernel.org>
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/db2c80108286cfd108adb05bad52138b78d7c3a7.1650673655.git.Thinh.Nguyen@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a633b8c341
commit
bd7f84708e
|
@ -2859,6 +2859,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
|
||||||
const struct dwc3_event_depevt *event,
|
const struct dwc3_event_depevt *event,
|
||||||
struct dwc3_request *req, int status)
|
struct dwc3_request *req, int status)
|
||||||
{
|
{
|
||||||
|
int request_status;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (req->request.num_mapped_sgs)
|
if (req->request.num_mapped_sgs)
|
||||||
|
@ -2879,7 +2880,35 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
|
||||||
req->needs_extra_trb = false;
|
req->needs_extra_trb = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwc3_gadget_giveback(dep, req, status);
|
/*
|
||||||
|
* The event status only reflects the status of the TRB with IOC set.
|
||||||
|
* For the requests that don't set interrupt on completion, the driver
|
||||||
|
* needs to check and return the status of the completed TRBs associated
|
||||||
|
* with the request. Use the status of the last TRB of the request.
|
||||||
|
*/
|
||||||
|
if (req->request.no_interrupt) {
|
||||||
|
struct dwc3_trb *trb;
|
||||||
|
|
||||||
|
trb = dwc3_ep_prev_trb(dep, dep->trb_dequeue);
|
||||||
|
switch (DWC3_TRB_SIZE_TRBSTS(trb->size)) {
|
||||||
|
case DWC3_TRBSTS_MISSED_ISOC:
|
||||||
|
/* Isoc endpoint only */
|
||||||
|
request_status = -EXDEV;
|
||||||
|
break;
|
||||||
|
case DWC3_TRB_STS_XFER_IN_PROG:
|
||||||
|
/* Applicable when End Transfer with ForceRM=0 */
|
||||||
|
case DWC3_TRBSTS_SETUP_PENDING:
|
||||||
|
/* Control endpoint only */
|
||||||
|
case DWC3_TRBSTS_OK:
|
||||||
|
default:
|
||||||
|
request_status = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
request_status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
dwc3_gadget_giveback(dep, req, request_status);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user