lkml.org 
[lkml]   [2022]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 16/88] usb: dwc3: gadget: Return proper request status
    Date
    From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>

    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: 6d8a019614f3 ("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>
    ---
    drivers/usb/dwc3/gadget.c | 31 ++++++++++++++++++++++++++++++-
    1 file changed, 30 insertions(+), 1 deletion(-)

    --- a/drivers/usb/dwc3/gadget.c
    +++ b/drivers/usb/dwc3/gadget.c
    @@ -2415,6 +2415,7 @@ static int dwc3_gadget_ep_cleanup_comple
    const struct dwc3_event_depevt *event,
    struct dwc3_request *req, int status)
    {
    + int request_status;
    int ret;

    if (req->request.num_mapped_sgs)
    @@ -2444,7 +2445,35 @@ static int dwc3_gadget_ep_cleanup_comple
    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:
    return ret;

    \
     
     \ /
      Last update: 2022-05-10 15:32    [W:4.032 / U:0.032 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site