Add a new function, hub_port_power_cycle() to power cycle port's power.
It'll be used by a following patch.

In addition to that, check the return value of usb_hub_set_port_power(),
so we don't need to wait if the set power operation fails.

Furthermore, remove parameter *hdev from usb_hub_set_port_power(), since
we can get *hdev from *hub directly.

Signed-off-by: Kai-Heng Feng <[email protected]>
---
 drivers/usb/core/hub.c  | 29 +++++++++++++++++++++++------
 drivers/usb/core/hub.h  |  3 +--
 drivers/usb/core/port.c |  4 ++--
 3 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 236313f41f4a..6655a6a1651b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -817,9 +817,9 @@ static void hub_tt_work(struct work_struct *work)
  *
  * Return: 0 if successful. A negative error code otherwise.
  */
-int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
-                          int port1, bool set)
+int usb_hub_set_port_power(struct usb_hub *hub, int port1, bool set)
 {
+       struct usb_device *hdev = hub->hdev;
        int ret;
 
        if (set)
@@ -2739,6 +2739,26 @@ static bool hub_port_warm_reset_required(struct usb_hub 
*hub, int port1,
                || link_state == USB_SS_PORT_LS_COMP_MOD;
 }
 
+static void hub_port_power_cycle(struct usb_hub *hub, int port1)
+{
+       int ret;
+
+       ret = usb_hub_set_port_power(hub, port1, false);
+       if (ret) {
+               dev_info(&udev->dev, "failed to disable port power\n");
+               return;
+       }
+
+       msleep(2 * hub_power_on_good_delay(hub));
+       ret = usb_hub_set_port_power(hub, port1, true);
+       if (ret) {
+               dev_info(&udev->dev, "failed to enable port power\n");
+               return;
+       }
+
+       msleep(hub_power_on_good_delay(hub));
+}
+
 static int hub_port_wait_reset(struct usb_hub *hub, int port1,
                        struct usb_device *udev, unsigned int delay, bool warm)
 {
@@ -5131,10 +5151,7 @@ static void hub_port_connect(struct usb_hub *hub, int 
port1, u16 portstatus,
                /* When halfway through our retry count, power-cycle the port */
                if (i == (SET_CONFIG_TRIES / 2) - 1) {
                        dev_info(&port_dev->dev, "attempt power cycle\n");
-                       usb_hub_set_port_power(hdev, hub, port1, false);
-                       msleep(2 * hub_power_on_good_delay(hub));
-                       usb_hub_set_port_power(hdev, hub, port1, true);
-                       msleep(hub_power_on_good_delay(hub));
+                       hub_port_power_cycle(hub, port1);
                }
        }
        if (hub->hdev->parent ||
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index a9e24e4b8df1..325a55637a6f 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -113,8 +113,7 @@ extern int usb_hub_create_port_device(struct usb_hub *hub,
                int port1);
 extern void usb_hub_remove_port_device(struct usb_hub *hub,
                int port1);
-extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
-               int port1, bool set);
+extern int usb_hub_set_port_power(struct usb_hub *hub, int port1, bool set);
 extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
 extern int hub_port_debounce(struct usb_hub *hub, int port1,
                bool must_be_connected);
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index bbbb35fa639f..0fc6f24c6da1 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -214,7 +214,7 @@ static int usb_port_runtime_resume(struct device *dev)
                pm_runtime_get_sync(&peer->dev);
 
        usb_autopm_get_interface(intf);
-       retval = usb_hub_set_port_power(hdev, hub, port1, true);
+       retval = usb_hub_set_port_power(hub, port1, true);
        msleep(hub_power_on_good_delay(hub));
        if (udev && !retval) {
                /*
@@ -267,7 +267,7 @@ static int usb_port_runtime_suspend(struct device *dev)
                return -EBUSY;
 
        usb_autopm_get_interface(intf);
-       retval = usb_hub_set_port_power(hdev, hub, port1, false);
+       retval = usb_hub_set_port_power(hub, port1, false);
        usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
        if (!port_dev->is_superspeed)
                usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE);
-- 
2.17.1

Reply via email to