Patch "usb: dwc3: gadget: Add 1ms delay after end transfer command without IOC" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    usb: dwc3: gadget: Add 1ms delay after end transfer command without IOC

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     usb-dwc3-gadget-add-1ms-delay-after-end-transfer-com.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 3f3f379e577ca9f79ba9951a9d2e6b1193cd3d2a
Author: Wesley Cheng <quic_wcheng@xxxxxxxxxxx>
Date:   Mon Mar 6 12:05:57 2023 -0800

    usb: dwc3: gadget: Add 1ms delay after end transfer command without IOC
    
    [ Upstream commit d8a2bb4eb75866275b5cf7de2e593ac3449643e2 ]
    
    Previously, there was a 100uS delay inserted after issuing an end transfer
    command for specific controller revisions.  This was due to the fact that
    there was a GUCTL2 bit field which enabled synchronous completion of the
    end transfer command once the CMDACT bit was cleared in the DEPCMD
    register.  Since this bit does not exist for all controller revisions and
    the current implementation heavily relies on utizling the EndTransfer
    command completion interrupt, add the delay back in for uses where the
    interrupt on completion bit is not set, and increase the duration to 1ms
    for the controller to complete the command.
    
    An issue was seen where the USB request buffer was unmapped while the DWC3
    controller was still accessing the TRB.  However, it was confirmed that the
    end transfer command was successfully submitted. (no end transfer timeout)
    In situations, such as dwc3_gadget_soft_disconnect() and
    __dwc3_gadget_ep_disable(), the dwc3_remove_request() is utilized, which
    will issue the end transfer command, and follow up with
    dwc3_gadget_giveback().  At least for the USB ep disable path, it is
    required for any pending and started requests to be completed and returned
    to the function driver in the same context of the disable call.  Without
    the GUCTL2 bit, it is not ensured that the end transfer is completed before
    the buffers are unmapped.
    
    Fixes: cf2f8b63f7f1 ("usb: dwc3: gadget: Remove END_TRANSFER delay")
    Cc: stable <stable@xxxxxxxxxx>
    Signed-off-by: Wesley Cheng <quic_wcheng@xxxxxxxxxxx>
    Acked-by: Thinh Nguyen <Thinh.Nguyen@xxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230306200557.29387-1-quic_wcheng@xxxxxxxxxxx
    Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index ce5131ccd60a9..01cecde76140b 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1453,6 +1453,7 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
  */
 static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
 {
+	struct dwc3 *dwc = dep->dwc;
 	struct dwc3_gadget_ep_cmd_params params;
 	u32 cmd;
 	int ret;
@@ -1466,10 +1467,13 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
 	WARN_ON_ONCE(ret);
 	dep->resource_index = 0;
 
-	if (!interrupt)
+	if (!interrupt) {
+		if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A))
+			mdelay(1);
 		dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-	else if (!ret)
+	} else if (!ret) {
 		dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+	}
 
 	return ret;
 }
@@ -3299,7 +3303,11 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
 	 * enabled, the EndTransfer command will have completed upon
 	 * returning from this function.
 	 *
-	 * This mode is NOT available on the DWC_usb31 IP.
+	 * This mode is NOT available on the DWC_usb31 IP.  In this
+	 * case, if the IOC bit is not set, then delay by 1ms
+	 * after issuing the EndTransfer command.  This allows for the
+	 * controller to handle the command completely before DWC3
+	 * remove requests attempts to unmap USB request buffers.
 	 */
 
 	__dwc3_stop_active_transfer(dep, force, interrupt);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux