From 8aab106925849adffeac1b9e28af35315597d2b4 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Fri, 6 Dec 2019 01:05:26 +0800 Subject: [PATCH] UBUNTU: SAUCE: USB: core: Make port power cycle a seperate helper function BugLink: https://bugs.launchpad.net/bugs/1855312 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 Signed-off-by: Seth Forshee --- drivers/usb/core/hub.c | 30 ++++++++++++++++++++++++------ drivers/usb/core/hub.h | 3 +-- drivers/usb/core/port.c | 4 ++-- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 86658a81d284..f81654294460 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -828,9 +828,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) @@ -2829,6 +2829,27 @@ 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) +{ + struct usb_port *port_dev = hub->ports[port1 - 1]; + int ret; + + ret = usb_hub_set_port_power(hub, port1, false); + if (ret) { + dev_info(&port_dev->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(&port_dev->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) { @@ -5381,10 +5402,7 @@ loop: /* When halfway through our retry count, power-cycle the port */ if (i == (PORT_INIT_TRIES - 1) / 2) { 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 22ea1f4f2d66..72a7d13cffc6 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -114,8 +114,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 dfcca9c876c7..08f23264a6f4 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -217,7 +217,7 @@ static int usb_port_runtime_resume(struct device *dev) if (retval < 0) return retval; - 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) { /* @@ -273,7 +273,7 @@ static int usb_port_runtime_suspend(struct device *dev) if (retval < 0) return retval; - 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.39.5