diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 70 |
1 files changed, 29 insertions, 41 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 590ec82d0515..bde29ab2b504 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -44,6 +44,7 @@ struct usb_hub { | |||
44 | struct usb_hub_status hub; | 44 | struct usb_hub_status hub; |
45 | struct usb_port_status port; | 45 | struct usb_port_status port; |
46 | } *status; /* buffer for status reports */ | 46 | } *status; /* buffer for status reports */ |
47 | struct mutex status_mutex; /* for the status buffer */ | ||
47 | 48 | ||
48 | int error; /* last reported error */ | 49 | int error; /* last reported error */ |
49 | int nerrors; /* track consecutive errors */ | 50 | int nerrors; /* track consecutive errors */ |
@@ -118,8 +119,7 @@ MODULE_PARM_DESC(use_both_schemes, | |||
118 | "first one fails"); | 119 | "first one fails"); |
119 | 120 | ||
120 | 121 | ||
121 | #ifdef DEBUG | 122 | static inline char *portspeed(int portstatus) |
122 | static inline char *portspeed (int portstatus) | ||
123 | { | 123 | { |
124 | if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) | 124 | if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) |
125 | return "480 Mb/s"; | 125 | return "480 Mb/s"; |
@@ -128,7 +128,6 @@ static inline char *portspeed (int portstatus) | |||
128 | else | 128 | else |
129 | return "12 Mb/s"; | 129 | return "12 Mb/s"; |
130 | } | 130 | } |
131 | #endif | ||
132 | 131 | ||
133 | /* Note that hdev or one of its children must be locked! */ | 132 | /* Note that hdev or one of its children must be locked! */ |
134 | static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev) | 133 | static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev) |
@@ -535,6 +534,7 @@ static int hub_hub_status(struct usb_hub *hub, | |||
535 | { | 534 | { |
536 | int ret; | 535 | int ret; |
537 | 536 | ||
537 | mutex_lock(&hub->status_mutex); | ||
538 | ret = get_hub_status(hub->hdev, &hub->status->hub); | 538 | ret = get_hub_status(hub->hdev, &hub->status->hub); |
539 | if (ret < 0) | 539 | if (ret < 0) |
540 | dev_err (hub->intfdev, | 540 | dev_err (hub->intfdev, |
@@ -544,6 +544,7 @@ static int hub_hub_status(struct usb_hub *hub, | |||
544 | *change = le16_to_cpu(hub->status->hub.wHubChange); | 544 | *change = le16_to_cpu(hub->status->hub.wHubChange); |
545 | ret = 0; | 545 | ret = 0; |
546 | } | 546 | } |
547 | mutex_unlock(&hub->status_mutex); | ||
547 | return ret; | 548 | return ret; |
548 | } | 549 | } |
549 | 550 | ||
@@ -617,6 +618,7 @@ static int hub_configure(struct usb_hub *hub, | |||
617 | ret = -ENOMEM; | 618 | ret = -ENOMEM; |
618 | goto fail; | 619 | goto fail; |
619 | } | 620 | } |
621 | mutex_init(&hub->status_mutex); | ||
620 | 622 | ||
621 | hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); | 623 | hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); |
622 | if (!hub->descriptor) { | 624 | if (!hub->descriptor) { |
@@ -1277,11 +1279,8 @@ int usb_new_device(struct usb_device *udev) | |||
1277 | { | 1279 | { |
1278 | int err; | 1280 | int err; |
1279 | 1281 | ||
1280 | /* Lock ourself into memory in order to keep a probe sequence | 1282 | /* Determine quirks */ |
1281 | * sleeping in a new thread from allowing us to be unloaded. | 1283 | usb_detect_quirks(udev); |
1282 | */ | ||
1283 | if (!try_module_get(THIS_MODULE)) | ||
1284 | return -EINVAL; | ||
1285 | 1284 | ||
1286 | err = usb_get_configuration(udev); | 1285 | err = usb_get_configuration(udev); |
1287 | if (err < 0) { | 1286 | if (err < 0) { |
@@ -1368,11 +1367,15 @@ int usb_new_device(struct usb_device *udev) | |||
1368 | } | 1367 | } |
1369 | #endif | 1368 | #endif |
1370 | 1369 | ||
1370 | /* export the usbdev device-node for libusb */ | ||
1371 | udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, | ||
1372 | (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); | ||
1373 | |||
1371 | /* Register the device. The device driver is responsible | 1374 | /* Register the device. The device driver is responsible |
1372 | * for adding the device files to usbfs and sysfs and for | 1375 | * for adding the device files to sysfs and for configuring |
1373 | * configuring the device. | 1376 | * the device. |
1374 | */ | 1377 | */ |
1375 | err = device_add (&udev->dev); | 1378 | err = device_add(&udev->dev); |
1376 | if (err) { | 1379 | if (err) { |
1377 | dev_err(&udev->dev, "can't device_add, error %d\n", err); | 1380 | dev_err(&udev->dev, "can't device_add, error %d\n", err); |
1378 | goto fail; | 1381 | goto fail; |
@@ -1383,7 +1386,6 @@ int usb_new_device(struct usb_device *udev) | |||
1383 | usb_autoresume_device(udev->parent); | 1386 | usb_autoresume_device(udev->parent); |
1384 | 1387 | ||
1385 | exit: | 1388 | exit: |
1386 | module_put(THIS_MODULE); | ||
1387 | return err; | 1389 | return err; |
1388 | 1390 | ||
1389 | fail: | 1391 | fail: |
@@ -1396,6 +1398,7 @@ static int hub_port_status(struct usb_hub *hub, int port1, | |||
1396 | { | 1398 | { |
1397 | int ret; | 1399 | int ret; |
1398 | 1400 | ||
1401 | mutex_lock(&hub->status_mutex); | ||
1399 | ret = get_port_status(hub->hdev, port1, &hub->status->port); | 1402 | ret = get_port_status(hub->hdev, port1, &hub->status->port); |
1400 | if (ret < 4) { | 1403 | if (ret < 4) { |
1401 | dev_err (hub->intfdev, | 1404 | dev_err (hub->intfdev, |
@@ -1407,6 +1410,7 @@ static int hub_port_status(struct usb_hub *hub, int port1, | |||
1407 | *change = le16_to_cpu(hub->status->port.wPortChange); | 1410 | *change = le16_to_cpu(hub->status->port.wPortChange); |
1408 | ret = 0; | 1411 | ret = 0; |
1409 | } | 1412 | } |
1413 | mutex_unlock(&hub->status_mutex); | ||
1410 | return ret; | 1414 | return ret; |
1411 | } | 1415 | } |
1412 | 1416 | ||
@@ -1855,12 +1859,8 @@ static int remote_wakeup(struct usb_device *udev) | |||
1855 | usb_lock_device(udev); | 1859 | usb_lock_device(udev); |
1856 | if (udev->state == USB_STATE_SUSPENDED) { | 1860 | if (udev->state == USB_STATE_SUSPENDED) { |
1857 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); | 1861 | dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); |
1858 | status = usb_autoresume_device(udev); | 1862 | usb_mark_last_busy(udev); |
1859 | 1863 | status = usb_external_resume_device(udev); | |
1860 | /* Give the interface drivers a chance to do something, | ||
1861 | * then autosuspend the device again. */ | ||
1862 | if (status == 0) | ||
1863 | usb_autosuspend_device(udev); | ||
1864 | } | 1864 | } |
1865 | usb_unlock_device(udev); | 1865 | usb_unlock_device(udev); |
1866 | return status; | 1866 | return status; |
@@ -1904,6 +1904,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
1904 | struct usb_hub *hub = usb_get_intfdata (intf); | 1904 | struct usb_hub *hub = usb_get_intfdata (intf); |
1905 | struct usb_device *hdev = hub->hdev; | 1905 | struct usb_device *hdev = hub->hdev; |
1906 | unsigned port1; | 1906 | unsigned port1; |
1907 | int status = 0; | ||
1907 | 1908 | ||
1908 | /* fail if children aren't already suspended */ | 1909 | /* fail if children aren't already suspended */ |
1909 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | 1910 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { |
@@ -1927,24 +1928,18 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
1927 | 1928 | ||
1928 | dev_dbg(&intf->dev, "%s\n", __FUNCTION__); | 1929 | dev_dbg(&intf->dev, "%s\n", __FUNCTION__); |
1929 | 1930 | ||
1931 | /* stop khubd and related activity */ | ||
1932 | hub_quiesce(hub); | ||
1933 | |||
1930 | /* "global suspend" of the downstream HC-to-USB interface */ | 1934 | /* "global suspend" of the downstream HC-to-USB interface */ |
1931 | if (!hdev->parent) { | 1935 | if (!hdev->parent) { |
1932 | struct usb_bus *bus = hdev->bus; | 1936 | status = hcd_bus_suspend(hdev->bus); |
1933 | if (bus) { | 1937 | if (status != 0) { |
1934 | int status = hcd_bus_suspend (bus); | 1938 | dev_dbg(&hdev->dev, "'global' suspend %d\n", status); |
1935 | 1939 | hub_activate(hub); | |
1936 | if (status != 0) { | 1940 | } |
1937 | dev_dbg(&hdev->dev, "'global' suspend %d\n", | ||
1938 | status); | ||
1939 | return status; | ||
1940 | } | ||
1941 | } else | ||
1942 | return -EOPNOTSUPP; | ||
1943 | } | 1941 | } |
1944 | 1942 | return status; | |
1945 | /* stop khubd and related activity */ | ||
1946 | hub_quiesce(hub); | ||
1947 | return 0; | ||
1948 | } | 1943 | } |
1949 | 1944 | ||
1950 | static int hub_resume(struct usb_interface *intf) | 1945 | static int hub_resume(struct usb_interface *intf) |
@@ -1989,13 +1984,6 @@ static inline int remote_wakeup(struct usb_device *udev) | |||
1989 | #define hub_resume NULL | 1984 | #define hub_resume NULL |
1990 | #endif | 1985 | #endif |
1991 | 1986 | ||
1992 | void usb_resume_root_hub(struct usb_device *hdev) | ||
1993 | { | ||
1994 | struct usb_hub *hub = hdev_to_hub(hdev); | ||
1995 | |||
1996 | kick_khubd(hub); | ||
1997 | } | ||
1998 | |||
1999 | 1987 | ||
2000 | /* USB 2.0 spec, 7.1.7.3 / fig 7-29: | 1988 | /* USB 2.0 spec, 7.1.7.3 / fig 7-29: |
2001 | * | 1989 | * |
@@ -2439,7 +2427,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
2439 | 2427 | ||
2440 | if (portchange & USB_PORT_STAT_C_CONNECTION) { | 2428 | if (portchange & USB_PORT_STAT_C_CONNECTION) { |
2441 | status = hub_port_debounce(hub, port1); | 2429 | status = hub_port_debounce(hub, port1); |
2442 | if (status < 0) { | 2430 | if (status < 0 && printk_ratelimit()) { |
2443 | dev_err (hub_dev, | 2431 | dev_err (hub_dev, |
2444 | "connect-debounce failed, port %d disabled\n", | 2432 | "connect-debounce failed, port %d disabled\n", |
2445 | port1); | 2433 | port1); |