diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 126 |
1 files changed, 89 insertions, 37 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c9412daff682..a12cab5314e9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -435,6 +435,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) | |||
| 435 | static void hub_power_on(struct usb_hub *hub) | 435 | static void hub_power_on(struct usb_hub *hub) |
| 436 | { | 436 | { |
| 437 | int port1; | 437 | int port1; |
| 438 | unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; | ||
| 438 | 439 | ||
| 439 | /* if hub supports power switching, enable power on each port */ | 440 | /* if hub supports power switching, enable power on each port */ |
| 440 | if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { | 441 | if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) { |
| @@ -444,8 +445,8 @@ static void hub_power_on(struct usb_hub *hub) | |||
| 444 | USB_PORT_FEAT_POWER); | 445 | USB_PORT_FEAT_POWER); |
| 445 | } | 446 | } |
| 446 | 447 | ||
| 447 | /* Wait for power to be enabled */ | 448 | /* Wait at least 100 msec for power to become stable */ |
| 448 | msleep(hub->descriptor->bPwrOn2PwrGood * 2); | 449 | msleep(max(pgood_delay, (unsigned) 100)); |
| 449 | } | 450 | } |
| 450 | 451 | ||
| 451 | static void hub_quiesce(struct usb_hub *hub) | 452 | static void hub_quiesce(struct usb_hub *hub) |
| @@ -492,6 +493,23 @@ static int hub_hub_status(struct usb_hub *hub, | |||
| 492 | return ret; | 493 | return ret; |
| 493 | } | 494 | } |
| 494 | 495 | ||
| 496 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | ||
| 497 | { | ||
| 498 | struct usb_device *hdev = hub->hdev; | ||
| 499 | int ret; | ||
| 500 | |||
| 501 | if (hdev->children[port1-1] && set_state) { | ||
| 502 | usb_set_device_state(hdev->children[port1-1], | ||
| 503 | USB_STATE_NOTATTACHED); | ||
| 504 | } | ||
| 505 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); | ||
| 506 | if (ret) | ||
| 507 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | ||
| 508 | port1, ret); | ||
| 509 | |||
| 510 | return ret; | ||
| 511 | } | ||
| 512 | |||
| 495 | static int hub_configure(struct usb_hub *hub, | 513 | static int hub_configure(struct usb_hub *hub, |
| 496 | struct usb_endpoint_descriptor *endpoint) | 514 | struct usb_endpoint_descriptor *endpoint) |
| 497 | { | 515 | { |
| @@ -610,19 +628,33 @@ static int hub_configure(struct usb_hub *hub, | |||
| 610 | break; | 628 | break; |
| 611 | } | 629 | } |
| 612 | 630 | ||
| 631 | /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ | ||
| 613 | switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { | 632 | switch (hub->descriptor->wHubCharacteristics & HUB_CHAR_TTTT) { |
| 614 | case 0x00: | 633 | case HUB_TTTT_8_BITS: |
| 615 | if (hdev->descriptor.bDeviceProtocol != 0) | 634 | if (hdev->descriptor.bDeviceProtocol != 0) { |
| 616 | dev_dbg(hub_dev, "TT requires at most 8 FS bit times\n"); | 635 | hub->tt.think_time = 666; |
| 636 | dev_dbg(hub_dev, "TT requires at most %d " | ||
| 637 | "FS bit times (%d ns)\n", | ||
| 638 | 8, hub->tt.think_time); | ||
| 639 | } | ||
| 617 | break; | 640 | break; |
| 618 | case 0x20: | 641 | case HUB_TTTT_16_BITS: |
| 619 | dev_dbg(hub_dev, "TT requires at most 16 FS bit times\n"); | 642 | hub->tt.think_time = 666 * 2; |
| 643 | dev_dbg(hub_dev, "TT requires at most %d " | ||
| 644 | "FS bit times (%d ns)\n", | ||
| 645 | 16, hub->tt.think_time); | ||
| 620 | break; | 646 | break; |
| 621 | case 0x40: | 647 | case HUB_TTTT_24_BITS: |
| 622 | dev_dbg(hub_dev, "TT requires at most 24 FS bit times\n"); | 648 | hub->tt.think_time = 666 * 3; |
| 649 | dev_dbg(hub_dev, "TT requires at most %d " | ||
| 650 | "FS bit times (%d ns)\n", | ||
| 651 | 24, hub->tt.think_time); | ||
| 623 | break; | 652 | break; |
| 624 | case 0x60: | 653 | case HUB_TTTT_32_BITS: |
| 625 | dev_dbg(hub_dev, "TT requires at most 32 FS bit times\n"); | 654 | hub->tt.think_time = 666 * 4; |
| 655 | dev_dbg(hub_dev, "TT requires at most %d " | ||
| 656 | "FS bit times (%d ns)\n", | ||
| 657 | 32, hub->tt.think_time); | ||
| 626 | break; | 658 | break; |
| 627 | } | 659 | } |
| 628 | 660 | ||
| @@ -712,20 +744,36 @@ fail: | |||
| 712 | 744 | ||
| 713 | static unsigned highspeed_hubs; | 745 | static unsigned highspeed_hubs; |
| 714 | 746 | ||
| 747 | /* Called after the hub driver is unbound from a hub with children */ | ||
| 748 | static void hub_remove_children_work(void *__hub) | ||
| 749 | { | ||
| 750 | struct usb_hub *hub = __hub; | ||
| 751 | struct usb_device *hdev = hub->hdev; | ||
| 752 | int i; | ||
| 753 | |||
| 754 | kfree(hub); | ||
| 755 | |||
| 756 | usb_lock_device(hdev); | ||
| 757 | for (i = 0; i < hdev->maxchild; ++i) { | ||
| 758 | if (hdev->children[i]) | ||
| 759 | usb_disconnect(&hdev->children[i]); | ||
| 760 | } | ||
| 761 | usb_unlock_device(hdev); | ||
| 762 | usb_put_dev(hdev); | ||
| 763 | } | ||
| 764 | |||
| 715 | static void hub_disconnect(struct usb_interface *intf) | 765 | static void hub_disconnect(struct usb_interface *intf) |
| 716 | { | 766 | { |
| 717 | struct usb_hub *hub = usb_get_intfdata (intf); | 767 | struct usb_hub *hub = usb_get_intfdata (intf); |
| 718 | struct usb_device *hdev; | 768 | struct usb_device *hdev; |
| 769 | int n, port1; | ||
| 719 | 770 | ||
| 720 | if (!hub) | 771 | usb_set_intfdata (intf, NULL); |
| 721 | return; | ||
| 722 | hdev = hub->hdev; | 772 | hdev = hub->hdev; |
| 723 | 773 | ||
| 724 | if (hdev->speed == USB_SPEED_HIGH) | 774 | if (hdev->speed == USB_SPEED_HIGH) |
| 725 | highspeed_hubs--; | 775 | highspeed_hubs--; |
| 726 | 776 | ||
| 727 | usb_set_intfdata (intf, NULL); | ||
| 728 | |||
| 729 | hub_quiesce(hub); | 777 | hub_quiesce(hub); |
| 730 | usb_free_urb(hub->urb); | 778 | usb_free_urb(hub->urb); |
| 731 | hub->urb = NULL; | 779 | hub->urb = NULL; |
| @@ -746,8 +794,27 @@ static void hub_disconnect(struct usb_interface *intf) | |||
| 746 | hub->buffer = NULL; | 794 | hub->buffer = NULL; |
| 747 | } | 795 | } |
| 748 | 796 | ||
| 749 | /* Free the memory */ | 797 | /* If there are any children then this is an unbind only, not a |
| 750 | kfree(hub); | 798 | * physical disconnection. The active ports must be disabled |
| 799 | * and later on we must call usb_disconnect(). We can't call | ||
| 800 | * it now because we may not hold the hub's device lock. | ||
| 801 | */ | ||
| 802 | n = 0; | ||
| 803 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { | ||
| 804 | if (hdev->children[port1 - 1]) { | ||
| 805 | ++n; | ||
| 806 | hub_port_disable(hub, port1, 1); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 810 | if (n == 0) | ||
| 811 | kfree(hub); | ||
| 812 | else { | ||
| 813 | /* Reuse the hub->leds work_struct for our own purposes */ | ||
| 814 | INIT_WORK(&hub->leds, hub_remove_children_work, hub); | ||
| 815 | schedule_work(&hub->leds); | ||
| 816 | usb_get_dev(hdev); | ||
| 817 | } | ||
| 751 | } | 818 | } |
| 752 | 819 | ||
| 753 | static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) | 820 | static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| @@ -1051,6 +1118,7 @@ void usb_disconnect(struct usb_device **pdev) | |||
| 1051 | dev_dbg (&udev->dev, "unregistering device\n"); | 1118 | dev_dbg (&udev->dev, "unregistering device\n"); |
| 1052 | release_address(udev); | 1119 | release_address(udev); |
| 1053 | usbfs_remove_device(udev); | 1120 | usbfs_remove_device(udev); |
| 1121 | usbdev_remove(udev); | ||
| 1054 | usb_remove_sysfs_dev_files(udev); | 1122 | usb_remove_sysfs_dev_files(udev); |
| 1055 | 1123 | ||
| 1056 | /* Avoid races with recursively_mark_NOTATTACHED() */ | 1124 | /* Avoid races with recursively_mark_NOTATTACHED() */ |
| @@ -1290,6 +1358,7 @@ int usb_new_device(struct usb_device *udev) | |||
| 1290 | /* USB device state == configured ... usable */ | 1358 | /* USB device state == configured ... usable */ |
| 1291 | 1359 | ||
| 1292 | /* add a /proc/bus/usb entry */ | 1360 | /* add a /proc/bus/usb entry */ |
| 1361 | usbdev_add(udev); | ||
| 1293 | usbfs_add_device(udev); | 1362 | usbfs_add_device(udev); |
| 1294 | return 0; | 1363 | return 0; |
| 1295 | 1364 | ||
| @@ -1392,7 +1461,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
| 1392 | port1, status); | 1461 | port1, status); |
| 1393 | else { | 1462 | else { |
| 1394 | status = hub_port_wait_reset(hub, port1, udev, delay); | 1463 | status = hub_port_wait_reset(hub, port1, udev, delay); |
| 1395 | if (status) | 1464 | if (status && status != -ENOTCONN) |
| 1396 | dev_dbg(hub->intfdev, | 1465 | dev_dbg(hub->intfdev, |
| 1397 | "port_wait_reset: err = %d\n", | 1466 | "port_wait_reset: err = %d\n", |
| 1398 | status); | 1467 | status); |
| @@ -1401,8 +1470,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
| 1401 | /* return on disconnect or reset */ | 1470 | /* return on disconnect or reset */ |
| 1402 | switch (status) { | 1471 | switch (status) { |
| 1403 | case 0: | 1472 | case 0: |
| 1404 | /* TRSTRCY = 10 ms */ | 1473 | /* TRSTRCY = 10 ms; plus some extra */ |
| 1405 | msleep(10); | 1474 | msleep(10 + 40); |
| 1406 | /* FALL THROUGH */ | 1475 | /* FALL THROUGH */ |
| 1407 | case -ENOTCONN: | 1476 | case -ENOTCONN: |
| 1408 | case -ENODEV: | 1477 | case -ENODEV: |
| @@ -1428,23 +1497,6 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
| 1428 | return status; | 1497 | return status; |
| 1429 | } | 1498 | } |
| 1430 | 1499 | ||
| 1431 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | ||
| 1432 | { | ||
| 1433 | struct usb_device *hdev = hub->hdev; | ||
| 1434 | int ret; | ||
| 1435 | |||
| 1436 | if (hdev->children[port1-1] && set_state) { | ||
| 1437 | usb_set_device_state(hdev->children[port1-1], | ||
| 1438 | USB_STATE_NOTATTACHED); | ||
| 1439 | } | ||
| 1440 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); | ||
| 1441 | if (ret) | ||
| 1442 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | ||
| 1443 | port1, ret); | ||
| 1444 | |||
| 1445 | return ret; | ||
| 1446 | } | ||
| 1447 | |||
| 1448 | /* | 1500 | /* |
| 1449 | * Disable a port and mark a logical connnect-change event, so that some | 1501 | * Disable a port and mark a logical connnect-change event, so that some |
| 1450 | * time later khubd will disconnect() any existing usb_device on the port | 1502 | * time later khubd will disconnect() any existing usb_device on the port |
