diff options
author | Matthew Garrett <mjg@redhat.com> | 2012-02-03 17:11:55 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-09 11:40:11 -0500 |
commit | d35e70d50a0641ebc1502fd343bef9b4011ada27 (patch) | |
tree | 0bbfc34982200c98ed9191dab8c5efc93029aaf6 | |
parent | 0846e7e9856c0928223447d9349a877202a63f24 (diff) |
usb: Use hub port data to determine whether a port is removable
Hubs have a flag to indicate whether a given port carries removable devices
or not. This is not strictly accurate in that some built-in devices
will be flagged as removable, but followup patches will make use of platform
data to make this more reliable.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/core/hub.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a0613d8f9be7..2d773cbe191c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -1838,6 +1838,37 @@ fail: | |||
1838 | return err; | 1838 | return err; |
1839 | } | 1839 | } |
1840 | 1840 | ||
1841 | static void set_usb_port_removable(struct usb_device *udev) | ||
1842 | { | ||
1843 | struct usb_device *hdev = udev->parent; | ||
1844 | struct usb_hub *hub; | ||
1845 | u8 port = udev->portnum; | ||
1846 | u16 wHubCharacteristics; | ||
1847 | bool removable = true; | ||
1848 | |||
1849 | if (!hdev) | ||
1850 | return; | ||
1851 | |||
1852 | hub = hdev_to_hub(udev->parent); | ||
1853 | |||
1854 | wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); | ||
1855 | |||
1856 | if (!(wHubCharacteristics & HUB_CHAR_COMPOUND)) | ||
1857 | return; | ||
1858 | |||
1859 | if (hub_is_superspeed(hdev)) { | ||
1860 | if (hub->descriptor->u.ss.DeviceRemovable & (1 << port)) | ||
1861 | removable = false; | ||
1862 | } else { | ||
1863 | if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) | ||
1864 | removable = false; | ||
1865 | } | ||
1866 | |||
1867 | if (removable) | ||
1868 | udev->removable = USB_DEVICE_REMOVABLE; | ||
1869 | else | ||
1870 | udev->removable = USB_DEVICE_FIXED; | ||
1871 | } | ||
1841 | 1872 | ||
1842 | /** | 1873 | /** |
1843 | * usb_new_device - perform initial device setup (usbcore-internal) | 1874 | * usb_new_device - perform initial device setup (usbcore-internal) |
@@ -1896,6 +1927,15 @@ int usb_new_device(struct usb_device *udev) | |||
1896 | announce_device(udev); | 1927 | announce_device(udev); |
1897 | 1928 | ||
1898 | device_enable_async_suspend(&udev->dev); | 1929 | device_enable_async_suspend(&udev->dev); |
1930 | |||
1931 | /* | ||
1932 | * check whether the hub marks this port as non-removable. Do it | ||
1933 | * now so that platform-specific data can override it in | ||
1934 | * device_add() | ||
1935 | */ | ||
1936 | if (udev->parent) | ||
1937 | set_usb_port_removable(udev); | ||
1938 | |||
1899 | /* Register the device. The device driver is responsible | 1939 | /* Register the device. The device driver is responsible |
1900 | * for configuring the device and invoking the add-device | 1940 | * for configuring the device and invoking the add-device |
1901 | * notifier chain (used by usbfs and possibly others). | 1941 | * notifier chain (used by usbfs and possibly others). |