diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cfdd4eecc5a9..29ca6ed3bea8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1513,6 +1513,8 @@ static int hub_configure(struct usb_hub *hub, dev_err(hub->intfdev, "couldn't create port%d device.\n", i + 1); + usb_hub_adjust_deviceremovable(hdev, hub->descriptor); + hub_activate(hub, HUB_INIT); return 0; @@ -5219,6 +5221,47 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) return hub->ports[port1 - 1]->connect_type; } +void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc) +{ + enum usb_port_connect_type connect_type; + int i; + + if (!hub_is_superspeed(hdev)) { + for (i = 1; i <= hdev->maxchild; i++) { + connect_type = usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u8 mask = 1 << (i%8); + + if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) { + dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", + i); + desc->u.hs.DeviceRemovable[i/8] |= mask; + } + } + } + } else { + u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable); + + for (i = 1; i <= hdev->maxchild; i++) { + connect_type = usb_get_hub_port_connect_type(hdev, i); + + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u16 mask = 1 << i; + + if (!(port_removable & mask)) { + dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n", + i); + port_removable |= mask; + } + } + } + + desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); + } +} + #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle |