[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20191007182840.4867-1-kai.heng.feng@canonical.com>
Date: Tue, 8 Oct 2019 02:28:39 +0800
From: Kai-Heng Feng <kai.heng.feng@...onical.com>
To: gregkh@...uxfoundation.org
Cc: stern@...land.harvard.edu, linux-usb@...r.kernel.org,
linux-kernel@...r.kernel.org,
Kai-Heng Feng <kai.heng.feng@...onical.com>
Subject: [PATCH 1/2] usb: core: Make port power cycle a separate helper function
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 <kai.heng.feng@...onical.com>
---
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
Powered by blists - more mailing lists