From: Kai-Heng Feng Date: Thu, 5 Dec 2019 17:05:00 +0000 (+0100) Subject: UBUNTU: SAUCE: USB: core: Make port power cycle a seperate helper function X-Git-Tag: Ubuntu-4.15.0-87.87~429 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=8e48df1c3ba051e17dafd815d961c977b1d04326;hp=5d5cc9b18a9117ba202174db3b7df6416f1636f6;p=mirror_ubuntu-bionic-kernel.git 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 Acked-by: Stefan Bader Acked-by: Kleber Sacilotto de Souza Signed-off-by: Kleber Sacilotto de Souza --- diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6ff732a7fc49..6ed7de25d3f4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -786,9 +786,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) @@ -2673,6 +2673,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) { @@ -4994,10 +5015,7 @@ loop: /* 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 2a700ccc868c..dab8921b2711 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -109,8 +109,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 032683ac4db4..f55e44524b05 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -171,7 +171,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) { /* @@ -224,7 +224,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);