ACPI provide "_PLD" and "_UPC" aml methods to describe usb port visibility and connectability. This patch is to use those information to change ehci root hub descriptors and set usb hub port's DeviceRemovable in the hub_configure(). When hub descriptor request is issued at first time, usb port device isn't created and usb port is not bound with acpi. So first hub descriptor request is not changed based on ACPI information. After usb port device being created, set hub port's DeviceRemovable according ACPI information and this also works for non-root hub. Signed-off-by: Lan Tianyu <tianyu.lan@xxxxxxxxx> --- drivers/usb/core/hub.c | 23 +++++++++++++++++++++++ drivers/usb/core/usb.h | 4 ---- drivers/usb/host/ehci-hub.c | 9 +++++++++ include/linux/usb.h | 4 ++++ 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 90accde..706db5c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1546,6 +1546,25 @@ static int hub_configure(struct usb_hub *hub, dev_err(hub->intfdev, "couldn't create port%d device.\n", i + 1); + if (!hub_is_superspeed(hdev)) { + for (i = 1; i <= hdev->maxchild; i++) + if (hub->ports[i - 1]->connect_type + == USB_PORT_CONNECT_TYPE_HARD_WIRED) + hub->descriptor->u.hs.DeviceRemovable[i/8] + |= 1 << (i%8); + } else { + u16 port_removable = + le16_to_cpu(hub->descriptor->u.ss.DeviceRemovable); + + for (i = 1; i <= hdev->maxchild; i++) + if (hub->ports[i - 1]->connect_type + == USB_PORT_CONNECT_TYPE_HARD_WIRED) + port_removable |= 1 << i; + + hub->descriptor->u.ss.DeviceRemovable = + cpu_to_le16(port_removable); + } + hub_activate(hub, HUB_INIT); return 0; @@ -5191,8 +5210,12 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) { struct usb_hub *hub = hdev_to_hub(hdev); + if (!hub) + return USB_PORT_CONNECT_TYPE_UNKNOWN; + return hub->ports[port1 - 1]->connect_type; } +EXPORT_SYMBOL_GPL(usb_get_hub_port_connect_type); #ifdef CONFIG_ACPI /** diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 1c528c1..1633f6e 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -169,10 +169,6 @@ extern void usb_notify_add_device(struct usb_device *udev); extern void usb_notify_remove_device(struct usb_device *udev); extern void usb_notify_add_bus(struct usb_bus *ubus); extern void usb_notify_remove_bus(struct usb_bus *ubus); -extern enum usb_port_connect_type - usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); -extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, - enum usb_port_connect_type type); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4ccb97c..dd084b3 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -662,6 +662,7 @@ ehci_hub_descriptor ( struct usb_hub_descriptor *desc ) { int ports = HCS_N_PORTS (ehci->hcs_params); + int i; u16 temp; desc->bDescriptorType = 0x29; @@ -676,6 +677,14 @@ ehci_hub_descriptor ( memset(&desc->u.hs.DeviceRemovable[0], 0, temp); memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); + for (i = 1; i <= ports; i++) { + if (usb_get_hub_port_connect_type( + ehci_to_hcd(ehci)->self.root_hub, i) + == USB_PORT_CONNECT_TYPE_HARD_WIRED) + desc->u.hs.DeviceRemovable[i/8] |= 1 << (i%8); + } + + temp = 0x0008; /* per-port overcurrent reporting */ if (HCS_PPC (ehci->hcs_params)) temp |= 0x0001; /* per-port power control */ diff --git a/include/linux/usb.h b/include/linux/usb.h index 689b14b..e996bb6 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -577,6 +577,10 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf) return to_usb_device(intf->dev.parent); } +extern enum usb_port_connect_type + usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); +extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, + enum usb_port_connect_type type); extern struct usb_device *usb_get_dev(struct usb_device *dev); extern void usb_put_dev(struct usb_device *dev); extern struct usb_device *usb_hub_find_child(struct usb_device *hdev, -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html