Sync Linux kernel dwc3 changes from v5.5 to v5.6.

The following files are preserved accross the import:
Makefile Kconfig dwc3-meson-g12a.c dwc3-meson-gxl.c dwc3-omap.c
dwc3-uniphier.c dwc3-generic.h dwc3-generic.c dwc3-generic-sti.c
dwc3-layerscape.c ti_usb_phy.c

Skipping unused files:
debugfs.c drd.c dwc3-exynos.c dwc3-haps.c dwc3-imx8mp.c dwc3-keystone.c
dwc3-octeon.c dwc3-of-simple.c dwc3-pci.c dwc3-qcom.c dwc3-qcom-legacy.c
dwc3-rtk.c dwc3-st.c dwc3-xilinx.c host.c trace.c trace.h ulpi.c

Note that this is a raw import and doesn't build.
A fixup commit at the end of the series fixes that.

List of commits: git log --oneline v5.5..v5.6
Commits imported:
dad2aff3e827 usb: dwc3: gadget: Update chain bit correctly when using sg list
42cd5ffe46c1 usb: dwc3: debug: fix string position formatting mixup with ret 
and len
5ee858975b13 usb: dwc3: gadget: Check for IOC/LST bit in TRB->ctrl fields
aac96626713f Merge tag 'usb-5.6-rc1' of 
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
85c009e8e5d2 Merge tag 'devprop-5.6-rc1' of 
git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
f5ae88690955 usb: dwc3: pci: add ID for the Intel Comet Lake -V variant
cf2f8b63f7f1 usb: dwc3: gadget: Remove END_TRANSFER delay
da10bcdd6f70 usb: dwc3: gadget: Delay starting transfer
c58d8bfc77a2 usb: dwc3: gadget: Check END_TRANSFER completion
09ed259fac62 usb: dwc3: turn off VBUS when leaving host mode
2e708fa3b898 usb: dwc3: gadget: Clear DCTL.ULSTCHNGREQ before set
1b6009ea88ec usb: dwc3: gadget: Set link state to RX_Detect on disconnect
5b738211fb59 usb: dwc3: gadget: Don't send unintended link state change
845f081002ee Merge 5.5-rc6 into usb-next
dea7b202bd9c usb: exynos: Rename Samsung and Exynos to lowercase
5eb5afb07853 usb: dwc3: use proper initializers for property entries
e880c3744b31 Merge 5.5-rc2 into usb-next

Signed-off-by: Jens Wiklander <[email protected]>
---
 drivers/usb/dwc3/core.c   |  3 ++
 drivers/usb/dwc3/core.h   |  2 ++
 drivers/usb/dwc3/debug.h  | 39 +++++++++-------------
 drivers/usb/dwc3/ep0.c    |  4 ++-
 drivers/usb/dwc3/gadget.c | 68 +++++++++++++++++++++++++--------------
 drivers/usb/dwc3/gadget.h | 14 ++++++++
 6 files changed, 80 insertions(+), 50 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f561c6c9e8a9..1d85c42b9c67 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1246,6 +1246,9 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
                /* do nothing */
                break;
        }
+
+       /* de-assert DRVVBUS for HOST and OTG mode */
+       dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
 }
 
 static void dwc3_get_properties(struct dwc3 *dwc)
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 1c8b349379af..77c4a9abe365 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -688,7 +688,9 @@ struct dwc3_ep {
 #define DWC3_EP_STALL          BIT(1)
 #define DWC3_EP_WEDGE          BIT(2)
 #define DWC3_EP_TRANSFER_STARTED BIT(3)
+#define DWC3_EP_END_TRANSFER_PENDING BIT(4)
 #define DWC3_EP_PENDING_REQUEST        BIT(5)
+#define DWC3_EP_DELAY_START    BIT(6)
 
        /* This last one is specific to EP0 */
 #define DWC3_EP0_DIR_IN                BIT(31)
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index e56beb9d1e36..4a13ceaf4093 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -256,86 +256,77 @@ static inline const char *dwc3_ep_event_string(char *str, 
size_t size,
        u8 epnum = event->endpoint_number;
        size_t len;
        int status;
-       int ret;
 
-       ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
+       len = scnprintf(str, size, "ep%d%s: ", epnum >> 1,
                        (epnum & 1) ? "in" : "out");
-       if (ret < 0)
-               return "UNKNOWN";
 
        status = event->status;
 
        switch (event->endpoint_event) {
        case DWC3_DEPEVT_XFERCOMPLETE:
-               len = strlen(str);
-               snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
+               len += scnprintf(str + len, size - len,
+                               "Transfer Complete (%c%c%c)",
                                status & DEPEVT_STATUS_SHORT ? 'S' : 's',
                                status & DEPEVT_STATUS_IOC ? 'I' : 'i',
                                status & DEPEVT_STATUS_LST ? 'L' : 'l');
 
-               len = strlen(str);
-
                if (epnum <= 1)
-                       snprintf(str + len, size - len, " [%s]",
+                       scnprintf(str + len, size - len, " [%s]",
                                        dwc3_ep0_state_string(ep0state));
                break;
        case DWC3_DEPEVT_XFERINPROGRESS:
-               len = strlen(str);
-
-               snprintf(str + len, size - len, "Transfer In Progress [%d] 
(%c%c%c)",
+               scnprintf(str + len, size - len,
+                               "Transfer In Progress [%d] (%c%c%c)",
                                event->parameters,
                                status & DEPEVT_STATUS_SHORT ? 'S' : 's',
                                status & DEPEVT_STATUS_IOC ? 'I' : 'i',
                                status & DEPEVT_STATUS_LST ? 'M' : 'm');
                break;
        case DWC3_DEPEVT_XFERNOTREADY:
-               len = strlen(str);
-
-               snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
+               len += scnprintf(str + len, size - len,
+                               "Transfer Not Ready [%d]%s",
                                event->parameters,
                                status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
                                " (Active)" : " (Not Active)");
 
-               len = strlen(str);
-
                /* Control Endpoints */
                if (epnum <= 1) {
                        int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
 
                        switch (phase) {
                        case DEPEVT_STATUS_CONTROL_DATA:
-                               snprintf(str + ret, size - ret,
+                               scnprintf(str + len, size - len,
                                                " [Data Phase]");
                                break;
                        case DEPEVT_STATUS_CONTROL_STATUS:
-                               snprintf(str + ret, size - ret,
+                               scnprintf(str + len, size - len,
                                                " [Status Phase]");
                        }
                }
                break;
        case DWC3_DEPEVT_RXTXFIFOEVT:
-               snprintf(str + ret, size - ret, "FIFO");
+               scnprintf(str + len, size - len, "FIFO");
                break;
        case DWC3_DEPEVT_STREAMEVT:
                status = event->status;
 
                switch (status) {
                case DEPEVT_STREAMEVT_FOUND:
-                       snprintf(str + ret, size - ret, " Stream %d Found",
+                       scnprintf(str + len, size - len, " Stream %d Found",
                                        event->parameters);
                        break;
                case DEPEVT_STREAMEVT_NOTFOUND:
                default:
-                       snprintf(str + ret, size - ret, " Stream Not Found");
+                       scnprintf(str + len, size - len, " Stream Not Found");
                        break;
                }
 
                break;
        case DWC3_DEPEVT_EPCMDCMPLT:
-               snprintf(str + ret, size - ret, "Endpoint Command Complete");
+               scnprintf(str + len, size - len, "Endpoint Command Complete");
                break;
        default:
-               snprintf(str, size, "UNKNOWN");
+               scnprintf(str + len, size - len, "UNKNOWN");
        }
 
        return str;
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index fd1b100d2927..6dee4dabc0a4 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -1136,8 +1136,10 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
        case DWC3_DEPEVT_EPCMDCMPLT:
                cmd = DEPEVT_PARAMETER_CMD(event->parameters);
 
-               if (cmd == DWC3_DEPCMD_ENDTRANSFER)
+               if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
+                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
                        dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+               }
                break;
        }
 }
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 154f3f3e8cff..1e00bf2d65a2 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -57,7 +57,7 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode)
                return -EINVAL;
        }
 
-       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+       dwc3_gadget_dctl_write_safe(dwc, reg);
 
        return 0;
 }
@@ -111,6 +111,9 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum 
dwc3_link_state state)
        reg = dwc3_readl(dwc->regs, DWC3_DCTL);
        reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
 
+       /* set no action before sending new link state change */
+       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+
        /* set requested state */
        reg |= DWC3_DCTL_ULSTCHNGREQ(state);
        dwc3_writel(dwc->regs, DWC3_DCTL, reg);
@@ -1068,7 +1071,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
                unsigned int rem = length % maxp;
                unsigned chain = true;
 
-               if (sg_is_last(s))
+               /*
+                * IOMMU driver is coalescing the list of sgs which shares a
+                * page boundary into one and giving it to USB driver. With
+                * this the number of sgs mapped is not equal to the number of
+                * sgs passed. So mark the chain bit to false if it isthe last
+                * mapped sg.
+                */
+               if (i == remaining - 1)
                        chain = false;
 
                if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) {
@@ -1447,6 +1457,12 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, 
struct dwc3_request *req)
        list_add_tail(&req->list, &dep->pending_list);
        req->status = DWC3_REQUEST_STATUS_QUEUED;
 
+       /* Start the transfer only after the END_TRANSFER is completed */
+       if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
+               dep->flags |= DWC3_EP_DELAY_START;
+               return 0;
+       }
+
        /*
         * NOTICE: Isochronous endpoints should NEVER be prestarted. We must
         * wait for a XferNotReady event so we will know what's the current
@@ -1828,7 +1844,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int 
is_on, int suspend)
                dwc->pullups_connected = false;
        }
 
-       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+       dwc3_gadget_dctl_write_safe(dwc, reg);
 
        do {
                reg = dwc3_readl(dwc->regs, DWC3_DSTS);
@@ -2420,7 +2436,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct 
dwc3_ep *dep,
        if (event->status & DEPEVT_STATUS_SHORT && !chain)
                return 1;
 
-       if (event->status & DEPEVT_STATUS_IOC)
+       if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
+           (trb->ctrl & DWC3_TRB_CTRL_LST))
                return 1;
 
        return 0;
@@ -2625,8 +2642,14 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
                cmd = DEPEVT_PARAMETER_CMD(event->parameters);
 
                if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
+                       dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
                        dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
                        dwc3_gadget_ep_cleanup_cancelled_requests(dep);
+                       if ((dep->flags & DWC3_EP_DELAY_START) &&
+                           !usb_endpoint_xfer_isoc(dep->endpoint.desc))
+                               __dwc3_gadget_kick_transfer(dep);
+
+                       dep->flags &= ~DWC3_EP_DELAY_START;
                }
                break;
        case DWC3_DEPEVT_STREAMEVT:
@@ -2678,12 +2701,12 @@ static void dwc3_reset_gadget(struct dwc3 *dwc)
 static void 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;
 
-       if (!(dep->flags & DWC3_EP_TRANSFER_STARTED))
+       if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) ||
+           (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
                return;
 
        /*
@@ -2693,16 +2716,13 @@ static void dwc3_stop_active_transfer(struct dwc3_ep 
*dep, bool force,
         * much trouble synchronizing between us and gadget driver.
         *
         * We have discussed this with the IP Provider and it was
-        * suggested to giveback all requests here, but give HW some
-        * extra time to synchronize with the interconnect. We're using
-        * an arbitrary 100us delay for that.
+        * suggested to giveback all requests here.
         *
         * Note also that a similar handling was tested by Synopsys
         * (thanks a lot Paul) and nothing bad has come out of it.
-        * In short, what we're doing is:
-        *
-        * - Issue EndTransfer WITH CMDIOC bit set
-        * - Wait 100us
+        * In short, what we're doing is issuing EndTransfer with
+        * CMDIOC bit set and delay kicking transfer until the
+        * EndTransfer command had completed.
         *
         * As of IP version 3.10a of the DWC_usb3 IP, the controller
         * supports a mode to work around the above limitation. The
@@ -2711,8 +2731,7 @@ static void dwc3_stop_active_transfer(struct dwc3_ep 
*dep, bool force,
         * by writing GUCTL2[14]. This polling is already done in the
         * dwc3_send_gadget_ep_cmd() function so if the mode is
         * enabled, the EndTransfer command will have completed upon
-        * returning from this function and we don't need to delay for
-        * 100us.
+        * returning from this function.
         *
         * This mode is NOT available on the DWC_usb31 IP.
         */
@@ -2728,9 +2747,8 @@ static void dwc3_stop_active_transfer(struct dwc3_ep 
*dep, bool force,
 
        if (!interrupt)
                dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
-
-       if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
-               udelay(100);
+       else
+               dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
 }
 
 static void dwc3_clear_stall_all_ep(struct dwc3 *dwc)
@@ -2759,12 +2777,12 @@ static void dwc3_gadget_disconnect_interrupt(struct 
dwc3 *dwc)
 {
        int                     reg;
 
+       dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET);
+
        reg = dwc3_readl(dwc->regs, DWC3_DCTL);
        reg &= ~DWC3_DCTL_INITU1ENA;
-       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
-
        reg &= ~DWC3_DCTL_INITU2ENA;
-       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+       dwc3_gadget_dctl_write_safe(dwc, reg);
 
        dwc3_disconnect_gadget(dwc);
 
@@ -2816,7 +2834,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
 
        reg = dwc3_readl(dwc->regs, DWC3_DCTL);
        reg &= ~DWC3_DCTL_TSTCTRL_MASK;
-       dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+       dwc3_gadget_dctl_write_safe(dwc, reg);
        dwc->test_mode = false;
        dwc3_clear_stall_all_ep(dwc);
 
@@ -2920,11 +2938,11 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 
*dwc)
                if (dwc->has_lpm_erratum && dwc->revision >= DWC3_REVISION_240A)
                        reg |= DWC3_DCTL_NYET_THRES(dwc->lpm_nyet_threshold);
 
-               dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+               dwc3_gadget_dctl_write_safe(dwc, reg);
        } else {
                reg = dwc3_readl(dwc->regs, DWC3_DCTL);
                reg &= ~DWC3_DCTL_HIRD_THRES_MASK;
-               dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+               dwc3_gadget_dctl_write_safe(dwc, reg);
        }
 
        dep = dwc->eps[0];
@@ -3033,7 +3051,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct 
dwc3 *dwc,
 
                                reg &= ~u1u2;
 
-                               dwc3_writel(dwc->regs, DWC3_DCTL, reg);
+                               dwc3_gadget_dctl_write_safe(dwc, reg);
                                break;
                        default:
                                /* do nothing */
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 5faf4d1249e0..fbc7d8013f0b 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -127,4 +127,18 @@ static inline void 
dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep)
        dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id);
 }
 
+/**
+ * dwc3_gadget_dctl_write_safe - write to DCTL safe from link state change
+ * @dwc: pointer to our context structure
+ * @value: value to write to DCTL
+ *
+ * Use this function when doing read-modify-write to DCTL. It will not
+ * send link state change request.
+ */
+static inline void dwc3_gadget_dctl_write_safe(struct dwc3 *dwc, u32 value)
+{
+       value &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+       dwc3_writel(dwc->regs, DWC3_DCTL, value);
+}
+
 #endif /* __DRIVERS_USB_DWC3_GADGET_H */
-- 
2.43.0

Reply via email to