diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c958cf42a1bb..eb2625b48ba1 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -21,6 +21,7 @@ #include <linux/usbdevice_fs.h> #include <linux/usb/hcd.h> #include <linux/usb/otg.h> +#include <linux/usb/otg-fsm.h> #include <linux/usb/quirks.h> #include <linux/workqueue.h> #include <linux/mutex.h> @@ -1134,6 +1135,10 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) need_debounce_delay = true; usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_CONNECTION); +#ifdef CONFIG_USB_OTG + if (hdev->bus->is_b_host) + usb_bus_start_enum(hdev->bus, port1); +#endif } if (portchange & USB_PORT_STAT_C_ENABLE) { need_debounce_delay = true; @@ -2224,9 +2229,9 @@ static inline void announce_device(struct usb_device *udev) { } */ static int usb_enumerate_device_otg(struct usb_device *udev) { +#ifdef CONFIG_USB_OTG int err = 0; -#ifdef CONFIG_USB_OTG /* * OTG-aware devices on OTG-capable root hubs may be able to use SRP, * to wake us after we've powered off VBUS; and HNP, switching roles @@ -2267,6 +2272,12 @@ static int usb_enumerate_device_otg(struct usb_device *udev) err); bus->b_hnp_enable = 0; } + + if (bus->otg_fsm) { + bus->otg_fsm->b_hnp_enable = 1; + if (bus->b_hnp_enable) + bus->otg_fsm->a_set_b_hnp_en = 1; + } } else if (desc->bLength == sizeof (struct usb_otg_descriptor)) { /* Set a_alt_hnp_support for legacy otg device */ @@ -2283,7 +2294,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev) } } #endif - return err; + return 0; } @@ -2305,6 +2316,7 @@ static int usb_enumerate_device(struct usb_device *udev) { int err; struct usb_hcd *hcd = bus_to_hcd(udev->bus); + struct otg_fsm *fsm = udev->bus->otg_fsm; if (udev->config == NULL) { err = usb_get_configuration(udev); @@ -2336,8 +2348,10 @@ static int usb_enumerate_device(struct usb_device *udev) err = usb_port_suspend(udev, PMSG_AUTO_SUSPEND); if (err < 0) dev_dbg(&udev->dev, "HNP fail, %d\n", err); + return -ENOTSUPP; + } else if (!fsm || !fsm->b_hnp_enable || !fsm->hnp_polling) { + return -ENOTSUPP; } - return -ENOTSUPP; } usb_detect_interface_quirks(udev); @@ -4387,6 +4401,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, enum usb_device_speed oldspeed = udev->speed; const char *speed; int devnum = udev->devnum; + const char *driver_name; /* root hub ports have a slightly longer reset period * (from USB 2.0 spec, section 7.1.7.5) @@ -4454,11 +4469,23 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, else speed = usb_speed_string(udev->speed); + /* + * The controller driver may be NULL if the controller device + * is the middle device between platform device and roothub. + * This middle device may not need a device driver due to + * all hardware control can be at platform device driver, this + * platform device is usually a dual-role USB controller device. + */ + if (udev->bus->controller->driver) + driver_name = udev->bus->controller->driver->name; + else + driver_name = udev->bus->sysdev->driver->name; + if (udev->speed < USB_SPEED_SUPER) dev_info(&udev->dev, "%s %s USB device number %d using %s\n", (udev->config) ? "reset" : "new", speed, - devnum, udev->bus->controller->driver->name); + devnum, driver_name); /* Set up TT records, if needed */ if (hdev->tt) { @@ -4560,7 +4587,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, } if (r) { if (r != -ENODEV) - dev_err(&udev->dev, "device descriptor read/64, error %d\n", + dev_err(&udev->dev, + "device no response, device descriptor read/64, error %d\n", r); retval = -EMSGSIZE; continue; @@ -4592,7 +4620,7 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, "%s SuperSpeed%s USB device number %d using %s\n", (udev->config) ? "reset" : "new", (udev->speed == USB_SPEED_SUPER_PLUS) ? "Plus" : "", - devnum, udev->bus->controller->driver->name); + devnum, driver_name); } /* cope with hardware quirkiness: |