Received: by 2002:a05:6358:7058:b0:131:369:b2a3 with SMTP id 24csp603617rwp; Wed, 12 Jul 2023 20:04:17 -0700 (PDT) X-Google-Smtp-Source: APBJJlFswd4OcTiAIpVFu0Uz8G7O5SmXcMd2RsAvCVcQqythSHtGE30F4REGmbA3eUYbtu9eYN47 X-Received: by 2002:a19:2d42:0:b0:4f8:4512:c846 with SMTP id t2-20020a192d42000000b004f84512c846mr53042lft.49.1689217457246; Wed, 12 Jul 2023 20:04:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689217457; cv=none; d=google.com; s=arc-20160816; b=NRm5jFuePCV+TcG1OOsKskc4CzvTDeJqcdxI4+7n2WKE/W6s5Cs8wH/lD6GA/eE6Fs Bhuzc4QFl89Ouw16Q6KKwkc+BlvVXNnHaYDXn62Z0wkCS5fy1MiRZPml9nIscnnhbZqm uhxjYDYeFubqf912N1GS2tzfjeCLiXOjFDYnxjTRr1AN60cnx+53Bj3z6Tvumd2euhG1 2MVN6OnJt5Ts9SRfNe6ezkuKTFAr9M9DKk/AsKcC4YxMeF7Xw8Bsgr2uiIAL2j3Ly1n1 7sZkiJWsgZnMzQ5oBzWD/dPtJj90EVs8QCvdxCVJDSLACNM0BW5PUnSMRkudDRVt7RKd 9rLg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=GxjiqGIX3xzOu2qVMT/St3B5pwa8O3XMc7IVdlCGY64=; fh=nxLBg0IR1nJ63GICU1mbHOg1FowBoxVQngiNg+7g3eY=; b=Kt5+BetU6OjrZs3MF55+4nBW3QtmjjJsyW2NmN1oPQPQPUwKNfKZvg2hdE9PmwaMn7 n5w/UOGW+fJAneyg2ikiiDxfZWJHoaEdHiAJ1T5a7rPQefuHh7wwOmUwerxZNyARXiFj S6t/OrMDX2uV3H6wysqwn8hO8rV5NDzdirFkCL+fQBrOkNAl3Zbt1R1QTmFvr8gCwvEo XUo/9tuZKAlOvyQrA4qCgMLGcsbAHjxiHQ7NhLh80gKC9O+JTaOm6isn1709VfNfVBwa dutWaIaoR2DspddjjQVko8EpgH0iC2jQb1hANTh1XPUmQxrC0VXL29Ve5vToRpzVk4Y3 wQIQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=rock-chips.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id n22-20020a056402515600b0051e109a50a3si6134861edd.527.2023.07.12.20.03.52; Wed, 12 Jul 2023 20:04:17 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=rock-chips.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233303AbjGMC6L (ORCPT + 99 others); Wed, 12 Jul 2023 22:58:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34730 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232553AbjGMC6K (ORCPT ); Wed, 12 Jul 2023 22:58:10 -0400 X-Greylist: delayed 370 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Wed, 12 Jul 2023 19:58:08 PDT Received: from mail-m11874.qiye.163.com (mail-m11874.qiye.163.com [115.236.118.74]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A7C6B4; Wed, 12 Jul 2023 19:58:07 -0700 (PDT) Received: from localhost.localdomain (unknown [58.22.7.114]) by mail-m11874.qiye.163.com (Hmail) with ESMTPA id 65BD03C03B3; Thu, 13 Jul 2023 10:51:53 +0800 (CST) From: William Wu To: Thinh.Nguyen@synopsys.com, gregkh@linuxfoundation.org Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, william.wu@rock-chips.com, frank.wang@rock-chips.com, jianwei.zheng@rock-chips.com, yangbin@rock-chips.com Subject: [PATCH] usb: dwc3: gadget: Properly handle miss isoc event Date: Thu, 13 Jul 2023 10:51:49 +0800 Message-Id: <20230713025149.24276-1-william.wu@rock-chips.com> X-Mailer: git-send-email 2.17.1 X-HM-Spam-Status: e1kfGhgUHx5ZQUpXWQgPGg8OCBgUHx5ZQUlOS1dZFg8aDwILHllBWSg2Ly tZV1koWUFDSUNOT01LS0k3V1ktWUFJV1kPCRoVCBIfWUFZQkJLHlYfSRhMTExLShpIThlVEwETFh oSFyQUDg9ZV1kYEgtZQVlOQ1VJSVVMVUpKT1lXWRYaDxIVHRRZQVlPS0hVSkpLQ0hJVUpLS1VLWQ Y+ X-HM-Tid: 0a894d29837a2eb0kusn65bd03c03b3 X-HM-MType: 1 X-HM-Sender-Digest: e1kMHhlZQR0aFwgeV1kSHx4VD1lBWUc6PQg6Szo6SD1OOR5PQxkCOAoC NBAKCQpVSlVKTUNCSUpNTEpPSUxNVTMWGhIXVQwSFxcSGhZVDA47CRQYEFYYExILCFUYFBZFWVdZ EgtZQVlOQ1VJSVVMVUpKT1lXWQgBWUFOTkJMNwY+ X-Spam-Status: No, score=-0.4 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,RCVD_IN_SORBS_WEB,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org If miss isoc event happens, the current code just set the req status to -EXDEV and giveback the req to the usb gadget driver, and then stop the active transfer with the cmd DWC3_DEPCMD_ENDTRANSFER and wait for a XferNotReady event to restart a transfer again. However, for isoc ep in transfer, it cause to lost the isoc data of the req. This patch moves the miss isoc req to pending_list in order to restart transfer immediately instead of give back the req to the usb gadget driver. Signed-off-by: William Wu --- drivers/usb/dwc3/gadget.c | 47 +++++++++++++++++++++++++++++++++++++++ drivers/usb/dwc3/gadget.h | 16 +++++++++++++ 2 files changed, 63 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 5fd067151fbf..ef295746b241 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -3454,6 +3454,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, const struct dwc3_event_depevt *event, struct dwc3_request *req, int status) { + struct dwc3 *dwc = dep->dwc; int request_status; int ret; @@ -3475,6 +3476,28 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep, req->needs_extra_trb = false; } + /* + * If MISS ISOC happens, we need to move the req from started_list + * to cancelled_list, then unmap the req and clear the HWO of trb. + * Later in the dwc3_gadget_endpoint_trbs_complete(), it will move + * the req from the cancelled_list to the pending_list, and restart + * the req for isoc transfer. + */ + if (status == -EXDEV && usb_endpoint_xfer_isoc(dep->endpoint.desc)) { + req->remaining = 0; + req->needs_extra_trb = false; + dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_DEQUEUED); + if (req->trb) { + usb_gadget_unmap_request_by_dev(dwc->sysdev, + &req->request, + req->direction); + req->trb->ctrl &= ~DWC3_TRB_CTRL_HWO; + req->trb = NULL; + } + ret = 0; + goto out; + } + /* * 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 @@ -3564,6 +3587,7 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, const struct dwc3_event_depevt *event, int status) { struct dwc3 *dwc = dep->dwc; + struct dwc3_request *req, *tmp; bool no_started_trb = true; dwc3_gadget_ep_cleanup_completed_requests(dep, event, status); @@ -3574,6 +3598,29 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, if (!dep->endpoint.desc) return no_started_trb; + /* + * If MISS ISOC happens, we need to do the following three steps + * to restart the reqs in the cancelled_list and pending_list + * in order. + * Step1. Move all the reqs from pending_list to the tail of + * cancelled_list. + * Step2. Move all the reqs from cancelled_list to the tail + * of pending_list. + * Step3. Stop and restart an isoc transfer. + */ + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && status == -EXDEV && + !list_empty(&dep->cancelled_list) && + !list_empty(&dep->pending_list)) { + list_for_each_entry_safe(req, tmp, &dep->pending_list, list) + dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_DEQUEUED); + } + + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && status == -EXDEV && + !list_empty(&dep->cancelled_list)) { + list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) + dwc3_gadget_move_queued_request(req); + } + if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && list_empty(&dep->started_list) && (list_empty(&dep->pending_list) || status == -EXDEV)) diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index 55a56cf67d73..242426b67798 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -104,6 +104,22 @@ static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req, list_move_tail(&req->list, &dep->cancelled_list); } +/** + * dwc3_gadget_move_queued_request - move @req to the pending_list + * @req: the request to be moved + * + * Caller should take care of locking. This function will move @req from its + * current list to the endpoint's pending_list. + * + */ +static inline void dwc3_gadget_move_queued_request(struct dwc3_request *req) +{ + struct dwc3_ep *dep = req->dep; + + req->status = DWC3_REQUEST_STATUS_QUEUED; + list_move_tail(&req->list, &dep->pending_list); +} + void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, int status); -- 2.17.1