lkml.org 
[lkml]   [2020]   [Jun]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 164/477] usb: dwc3: gadget: Properly handle ClearFeature(halt)
    Date
    From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>

    [ Upstream commit cb11ea56f37a36288cdd0a4799a983ee3aa437dd ]

    DWC3 must not issue CLEAR_STALL command to control endpoints. The
    controller automatically clears the STALL when it receives the SETUP
    token. Also, when the driver receives ClearFeature(halt_ep), DWC3 must
    stop any active transfer from the endpoint and give back all the
    requests to the function drivers.

    Fixes: 72246da40f37 ("usb: Introduce DesignWare USB3 DRD Driver")
    Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
    Signed-off-by: Felipe Balbi <balbi@kernel.org>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/usb/dwc3/gadget.c | 36 +++++++++++++++++++++++++++++++++---
    1 file changed, 33 insertions(+), 3 deletions(-)

    diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
    index 585cb3deea7ad..ab6562c5b9279 100644
    --- a/drivers/usb/dwc3/gadget.c
    +++ b/drivers/usb/dwc3/gadget.c
    @@ -1508,6 +1508,10 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request *r
    {
    int i;

    + /* If req->trb is not set, then the request has not started */
    + if (!req->trb)
    + return;
    +
    /*
    * If request was already started, this means we had to
    * stop the transfer. With that we also need to ignore
    @@ -1598,6 +1602,8 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
    {
    struct dwc3_gadget_ep_cmd_params params;
    struct dwc3 *dwc = dep->dwc;
    + struct dwc3_request *req;
    + struct dwc3_request *tmp;
    int ret;

    if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
    @@ -1634,13 +1640,37 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
    else
    dep->flags |= DWC3_EP_STALL;
    } else {
    + /*
    + * Don't issue CLEAR_STALL command to control endpoints. The
    + * controller automatically clears the STALL when it receives
    + * the SETUP token.
    + */
    + if (dep->number <= 1) {
    + dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
    + return 0;
    + }

    ret = dwc3_send_clear_stall_ep_cmd(dep);
    - if (ret)
    + if (ret) {
    dev_err(dwc->dev, "failed to clear STALL on %s\n",
    dep->name);
    - else
    - dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
    + return ret;
    + }
    +
    + dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
    +
    + dwc3_stop_active_transfer(dep, true, true);
    +
    + list_for_each_entry_safe(req, tmp, &dep->started_list, list)
    + dwc3_gadget_move_cancelled_request(req);
    +
    + list_for_each_entry_safe(req, tmp, &dep->pending_list, list)
    + dwc3_gadget_move_cancelled_request(req);
    +
    + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) {
    + dep->flags &= ~DWC3_EP_DELAY_START;
    + dwc3_gadget_ep_cleanup_cancelled_requests(dep);
    + }
    }

    return ret;
    --
    2.25.1


    \
     
     \ /
      Last update: 2020-06-23 23:39    [W:2.389 / U:0.328 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site