aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c76
1 files changed, 58 insertions, 18 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 487abcfcccd8..b84fb141e122 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -42,6 +42,7 @@
#include <linux/pm_runtime.h>
#include <linux/types.h>
+#include <linux/phy/phy.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/phy.h>
@@ -1272,7 +1273,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_unlink_urb_from_ep);
* The usb core itself is however optimized for host controllers that can dma
* using regular system memory - like pci devices doing bus mastering.
*
- * To support host controllers with limited dma capabilites we provide dma
+ * To support host controllers with limited dma capabilities we provide dma
* bounce buffers. This feature can be enabled using the HCD_LOCAL_MEM flag.
* For this to work properly the host controller code must first use the
* function dma_declare_coherent_memory() to point out which memory area
@@ -1664,6 +1665,8 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
usbmon_urb_complete(&hcd->self, urb, status);
usb_anchor_suspend_wakeups(anchor);
usb_unanchor_urb(urb);
+ if (likely(status == 0))
+ usb_led_activity(USB_LED_EVENT_HOST);
/* pass ownership to the completion handler */
urb->status = status;
@@ -2301,7 +2304,7 @@ EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub);
* Context: in_interrupt()
*
* Starts enumeration, with an immediate reset followed later by
- * khubd identifying and possibly configuring the device.
+ * hub_wq identifying and possibly configuring the device.
* This is needed by OTG controller drivers, where it helps meet
* HNP protocol timing requirements for starting a port reset.
*
@@ -2320,7 +2323,7 @@ int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
if (port_num && hcd->driver->start_port_reset)
status = hcd->driver->start_port_reset(hcd, port_num);
- /* run khubd shortly after (first) root port reset finishes;
+ /* allocate hub_wq shortly after (first) root port reset finishes;
* it may issue others, until at least 50 msecs have passed.
*/
if (status == 0)
@@ -2383,20 +2386,20 @@ void usb_hc_died (struct usb_hcd *hcd)
if (hcd->rh_registered) {
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
- /* make khubd clean up old urbs and devices */
+ /* make hub_wq clean up old urbs and devices */
usb_set_device_state (hcd->self.root_hub,
USB_STATE_NOTATTACHED);
- usb_kick_khubd (hcd->self.root_hub);
+ usb_kick_hub_wq(hcd->self.root_hub);
}
if (usb_hcd_is_primary_hcd(hcd) && hcd->shared_hcd) {
hcd = hcd->shared_hcd;
if (hcd->rh_registered) {
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
- /* make khubd clean up old urbs and devices */
+ /* make hub_wq clean up old urbs and devices */
usb_set_device_state(hcd->self.root_hub,
USB_STATE_NOTATTACHED);
- usb_kick_khubd(hcd->self.root_hub);
+ usb_kick_hub_wq(hcd->self.root_hub);
}
}
spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
@@ -2627,7 +2630,7 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
- if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->phy) {
+ if (IS_ENABLED(CONFIG_USB_PHY) && !hcd->usb_phy) {
struct usb_phy *phy = usb_get_phy_dev(hcd->self.controller, 0);
if (IS_ERR(phy)) {
@@ -2640,11 +2643,34 @@ int usb_add_hcd(struct usb_hcd *hcd,
usb_put_phy(phy);
return retval;
}
- hcd->phy = phy;
+ hcd->usb_phy = phy;
hcd->remove_phy = 1;
}
}
+ if (IS_ENABLED(CONFIG_GENERIC_PHY)) {
+ struct phy *phy = phy_get(hcd->self.controller, "usb");
+
+ if (IS_ERR(phy)) {
+ retval = PTR_ERR(phy);
+ if (retval == -EPROBE_DEFER)
+ goto err_phy;
+ } else {
+ retval = phy_init(phy);
+ if (retval) {
+ phy_put(phy);
+ goto err_phy;
+ }
+ retval = phy_power_on(phy);
+ if (retval) {
+ phy_exit(phy);
+ phy_put(phy);
+ goto err_phy;
+ }
+ hcd->phy = phy;
+ }
+ }
+
dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
/* Keep old behaviour if authorized_default is not in [0, 1]. */
@@ -2655,12 +2681,12 @@ int usb_add_hcd(struct usb_hcd *hcd,
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* HC is in reset state, but accessible. Now do the one-time init,
- * bottom up so that hcds can customize the root hubs before khubd
+ * bottom up so that hcds can customize the root hubs before hub_wq
* starts talking to them. (Note, bus id is assigned early too.)
*/
if ((retval = hcd_buffer_create(hcd)) != 0) {
dev_dbg(hcd->self.controller, "pool alloc failed\n");
- goto err_remove_phy;
+ goto err_create_buf;
}
if ((retval = usb_register_bus(&hcd->self)) < 0)
@@ -2787,12 +2813,19 @@ err_allocate_root_hub:
usb_deregister_bus(&hcd->self);
err_register_bus:
hcd_buffer_destroy(hcd);
-err_remove_phy:
- if (hcd->remove_phy && hcd->phy) {
- usb_phy_shutdown(hcd->phy);
- usb_put_phy(hcd->phy);
+err_create_buf:
+ if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->phy) {
+ phy_power_off(hcd->phy);
+ phy_exit(hcd->phy);
+ phy_put(hcd->phy);
hcd->phy = NULL;
}
+err_phy:
+ if (hcd->remove_phy && hcd->usb_phy) {
+ usb_phy_shutdown(hcd->usb_phy);
+ usb_put_phy(hcd->usb_phy);
+ hcd->usb_phy = NULL;
+ }
return retval;
}
EXPORT_SYMBOL_GPL(usb_add_hcd);
@@ -2864,11 +2897,18 @@ void usb_remove_hcd(struct usb_hcd *hcd)
usb_deregister_bus(&hcd->self);
hcd_buffer_destroy(hcd);
- if (hcd->remove_phy && hcd->phy) {
- usb_phy_shutdown(hcd->phy);
- usb_put_phy(hcd->phy);
+
+ if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->phy) {
+ phy_power_off(hcd->phy);
+ phy_exit(hcd->phy);
+ phy_put(hcd->phy);
hcd->phy = NULL;
}
+ if (hcd->remove_phy && hcd->usb_phy) {
+ usb_phy_shutdown(hcd->usb_phy);
+ usb_put_phy(hcd->usb_phy);
+ hcd->usb_phy = NULL;
+ }
usb_put_invalidate_rhdev(hcd);
}