Merge "USB: dwc3: otg: Fix stop endpoint command timeout issue"
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 8a034d6..e373b9b 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -93,6 +93,17 @@
return 0;
}
+static void dwc3_otg_set_hsphy_auto_suspend(struct dwc3_otg *dotg, bool susp);
+static int dwc3_otg_set_autosuspend(struct usb_phy *phy, int enable_autosuspend)
+{
+ struct usb_otg *otg = phy->otg;
+ struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
+
+ dwc3_otg_set_hsphy_auto_suspend(dotg, enable_autosuspend);
+
+ return 0;
+}
+
static void dwc3_otg_set_hsphy_auto_suspend(struct dwc3_otg *dotg, bool susp)
{
struct dwc3 *dwc = dotg->dwc;
@@ -998,6 +1009,7 @@
dotg->otg.phy->dev = dwc->dev;
dotg->otg.phy->set_power = dwc3_otg_set_power;
dotg->otg.phy->set_suspend = dwc3_otg_set_suspend;
+ dotg->otg.phy->set_phy_autosuspend = dwc3_otg_set_autosuspend;
ret = usb_set_transceiver(dotg->otg.phy);
if (ret) {
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index cc0c1e0..1634fcf 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -51,6 +51,17 @@
return xhci_gen_setup(hcd, xhci_plat_quirks);
}
+static void xhci_plat_phy_autosuspend(struct usb_hcd *hcd,
+ int enable_autosuspend)
+{
+ if (!phy || !phy->set_phy_autosuspend)
+ return;
+
+ usb_phy_set_autosuspend(phy, enable_autosuspend);
+
+ return;
+}
+
static const struct hc_driver xhci_plat_xhci_driver = {
.description = "xhci-hcd",
.product_desc = "xHCI Host Controller",
@@ -98,6 +109,7 @@
.hub_status_data = xhci_hub_status_data,
.bus_suspend = xhci_bus_suspend,
.bus_resume = xhci_bus_resume,
+ .set_autosuspend = xhci_plat_phy_autosuspend,
};
static int xhci_plat_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b3f3fa8..e1c0096 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -647,6 +647,8 @@
struct xhci_dequeue_state deq_state;
+ if (xhci->main_hcd->driver->set_autosuspend)
+ xhci->main_hcd->driver->set_autosuspend(xhci->main_hcd, 1);
if (unlikely(TRB_TO_SUSPEND_PORT(
le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])))) {
slot_id = TRB_TO_SLOT_ID(
@@ -800,6 +802,8 @@
spin_lock_irqsave(&xhci->lock, flags);
+ if (xhci->main_hcd->driver->set_autosuspend)
+ xhci->main_hcd->driver->set_autosuspend(xhci->main_hcd, 1);
ep->stop_cmds_pending--;
if (xhci->xhc_state & XHCI_STATE_DYING) {
xhci_dbg(xhci, "Stop EP timer ran, but another timer marked "
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 0a82e58..f8bc1c5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1386,6 +1386,8 @@
ep->stop_cmd_timer.expires = jiffies +
XHCI_STOP_EP_CMD_TIMEOUT * HZ;
add_timer(&ep->stop_cmd_timer);
+ if (hcd->driver->set_autosuspend)
+ hcd->driver->set_autosuspend(hcd, 0);
xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index, 0);
xhci_ring_cmd_db(xhci);
}
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index f9dec0b..ac0428d 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -352,6 +352,7 @@
void (*dump_regs)(struct usb_hcd *);
void (*set_autosuspend_delay)(struct usb_device *);
void (*reset_sof_bug_handler)(struct usb_hcd *hcd, u32 val);
+ void (*set_autosuspend)(struct usb_hcd *hcd, int enable_autosuspend);
};
extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index ae3ffe4..7c82579 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -149,6 +149,9 @@
int (*set_suspend)(struct usb_phy *x,
int suspend);
+ /* To enable/disable phy autosuspend feature */
+ int (*set_phy_autosuspend)(struct usb_phy *x,
+ int enable_autosuspend);
};
@@ -288,6 +291,15 @@
}
static inline int
+usb_phy_set_autosuspend(struct usb_phy *x, int enable_autosuspend)
+{
+ if (x && x->set_phy_autosuspend != NULL)
+ return x->set_phy_autosuspend(x, enable_autosuspend);
+ else
+ return 0;
+}
+
+static inline int
otg_start_srp(struct usb_otg *otg)
{
if (otg && otg->start_srp)