View | Details | Raw Unified | Return to bug 41752 | Differences between
and this patch

Collapse All | Expand All

(-)drivers/usb/core/hub.c.orig (-71 / +84 lines)
Lines 2664-2719 Link Here
2664
	if ((portstatus & USB_PORT_STAT_RESET))
2664
	if ((portstatus & USB_PORT_STAT_RESET))
2665
		return -EBUSY;
2665
		return -EBUSY;
2666
2666
2667
	if (hub_port_warm_reset_required(hub, port1, portstatus))
2667
	/* Some buggy devices require a warm reset to be issued even
2668
		return -ENOTCONN;
2668
	 * when the port appears not to be connected.
2669
2670
	/* Device went away? */
2671
	if (!(portstatus & USB_PORT_STAT_CONNECTION))
2672
		return -ENOTCONN;
2673
2674
	/* bomb out completely if the connection bounced.  A USB 3.0
2675
	 * connection may bounce if multiple warm resets were issued,
2676
	 * but the device may have successfully re-connected. Ignore it.
2677
	 */
2669
	 */
2678
	if (!hub_is_superspeed(hub->hdev) &&
2670
               if (!warm) {
2679
			(portchange & USB_PORT_STAT_C_CONNECTION))
2671
                       /*
2680
		return -ENOTCONN;
2672
                        * Some buggy devices can cause an NEC host controller
2681
2673
                        * to transition to the "Error" state after a hot port
2682
	if (!(portstatus & USB_PORT_STAT_ENABLE))
2674
                        * reset.  This will show up as the port state in
2683
		return -EBUSY;
2675
                        * "Inactive", and the port may also report a
2676
                        * disconnect.  Forcing a warm port reset seems to make
2677
                        * the device work.
2678
                        *
2679
                        * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
2680
                        */
2681
                       if (hub_port_warm_reset_required(hub, port1, portstatus)) {
2682
                               int ret;
2683
2684
                               if ((portchange & USB_PORT_STAT_C_CONNECTION))
2685
                                       usb_clear_port_feature(hub->hdev, port1,
2686
                                                       USB_PORT_FEAT_C_CONNECTION);
2687
                               if (portchange & USB_PORT_STAT_C_LINK_STATE)
2688
                                       usb_clear_port_feature(hub->hdev, port1,
2689
                                                       USB_PORT_FEAT_C_PORT_LINK_STATE);
2690
                               if (portchange & USB_PORT_STAT_C_RESET)
2691
                                       usb_clear_port_feature(hub->hdev, port1,
2692
                                                       USB_PORT_FEAT_C_RESET);
2693
                               dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n",
2694
                                               port1);
2695
                               ret = hub_port_reset(hub, port1,
2696
                                               udev, HUB_BH_RESET_TIME,
2697
                                               true);
2698
                               if ((portchange & USB_PORT_STAT_C_CONNECTION))
2699
                                       usb_clear_port_feature(hub->hdev, port1,
2700
                                                       USB_PORT_FEAT_C_CONNECTION);
2701
                               return ret;
2702
                       }
2703
                       /* Device went away? */
2704
                       if (!(portstatus & USB_PORT_STAT_CONNECTION))
2705
                               return -ENOTCONN;
2706
2707
                       /* bomb out completely if the connection bounced */
2708
                       if ((portchange & USB_PORT_STAT_C_CONNECTION))
2709
                               return -ENOTCONN;
2710
2711
                       if ((portstatus & USB_PORT_STAT_ENABLE)) {
2712
                               if (!udev)
2713
                                       return 0;
2714
2715
                               if (hub_is_wusb(hub))
2716
                                       udev->speed = USB_SPEED_WIRELESS;
2717
                               else if (hub_is_superspeed(hub->hdev))
2718
                                       udev->speed = USB_SPEED_SUPER;
2719
                               else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
2720
                                       udev->speed = USB_SPEED_HIGH;
2721
                               else if (portstatus & USB_PORT_STAT_LOW_SPEED)
2722
                                       udev->speed = USB_SPEED_LOW;
2723
                               else
2724
                                       udev->speed = USB_SPEED_FULL;
2725
				return 0;
2726
                       }
2727
               } else {
2728
                       if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
2729
                                       hub_port_warm_reset_required(hub, port1,
2730
                                               portstatus))
2731
                               return -ENOTCONN;
2684
2732
2685
	if (!udev)
2686
		return 0;
2733
		return 0;
2687
2734
	}
2688
	if (hub_is_wusb(hub))
2735
	return -EBUSY;
2689
		udev->speed = USB_SPEED_WIRELESS;
2690
	else if (hub_is_superspeed(hub->hdev))
2691
		udev->speed = USB_SPEED_SUPER;
2692
	else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
2693
		udev->speed = USB_SPEED_HIGH;
2694
	else if (portstatus & USB_PORT_STAT_LOW_SPEED)
2695
		udev->speed = USB_SPEED_LOW;
2696
	else
2697
		udev->speed = USB_SPEED_FULL;
2698
	return 0;
2699
}
2736
}
2700
2737
2701
static void hub_port_finish_reset(struct usb_hub *hub, int port1,
2738
static void hub_port_finish_reset(struct usb_hub *hub, int port1,
2702
			struct usb_device *udev, int *status)
2739
			struct usb_device *udev, int *status, bool warm)
2703
{
2740
{
2704
	switch (*status) {
2741
	switch (*status) {
2705
	case 0:
2742
	case 0:
2706
		/* TRSTRCY = 10 ms; plus some extra */
2743
               if (!warm) {
2707
		msleep(10 + 40);
2744
                       struct usb_hcd *hcd;
2708
		if (udev) {
2745
                       /* TRSTRCY = 10 ms; plus some extra */
2709
			struct usb_hcd *hcd = bus_to_hcd(udev->bus);
2746
                       msleep(10 + 40);
2710
2747
                       if (udev) {
2711
			update_devnum(udev, 0);
2748
                               update_devnum(udev, 0);
2712
			/* The xHC may think the device is already reset,
2749
                               hcd = bus_to_hcd(udev->bus);
2713
			 * so ignore the status.
2750
                               /* The xHC may think the device is already
2714
			 */
2751
                                * reset, so ignore the status.
2715
			if (hcd->driver->reset_device)
2752
                                */
2716
				hcd->driver->reset_device(hcd, udev);
2753
                               if (hcd->driver->reset_device)
2754
                                       hcd->driver->reset_device(hcd, udev);
2755
                       }
2717
		}
2756
		}
2718
		/* FALL THROUGH */
2757
		/* FALL THROUGH */
2719
	case -ENOTCONN:
2758
	case -ENOTCONN:
Lines 2725-2734 Link Here
2725
					USB_PORT_FEAT_C_BH_PORT_RESET);
2764
					USB_PORT_FEAT_C_BH_PORT_RESET);
2726
			usb_clear_port_feature(hub->hdev, port1,
2765
			usb_clear_port_feature(hub->hdev, port1,
2727
					USB_PORT_FEAT_C_PORT_LINK_STATE);
2766
					USB_PORT_FEAT_C_PORT_LINK_STATE);
2728
			usb_clear_port_feature(hub->hdev, port1,
2729
					USB_PORT_FEAT_C_CONNECTION);
2730
		}
2767
		}
2731
		if (udev)
2768
		if (!warm && udev)
2732
			usb_set_device_state(udev, *status
2769
			usb_set_device_state(udev, *status
2733
					? USB_STATE_NOTATTACHED
2770
					? USB_STATE_NOTATTACHED
2734
					: USB_STATE_DEFAULT);
2771
					: USB_STATE_DEFAULT);
Lines 2789-2822 Link Here
2789
						status);
2826
						status);
2790
		}
2827
		}
2791
2828
2792
		/* Check for disconnect or reset */
2829
		/* return on disconnect or reset */
2793
		if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
2830
		if (status == 0 || status == -ENOTCONN || status == -ENODEV) {
2794
			hub_port_finish_reset(hub, port1, udev, &status);
2831
                       hub_port_finish_reset(hub, port1, udev, &status, warm);
2795
2832
                       goto done;
2796
			if (!hub_is_superspeed(hub->hdev))
2797
				goto done;
2798
2799
			/*
2800
			 * If a USB 3.0 device migrates from reset to an error
2801
			 * state, re-issue the warm reset.
2802
			 */
2803
			if (hub_port_status(hub, port1,
2804
					&portstatus, &portchange) < 0)
2805
				goto done;
2806
2807
			if (!hub_port_warm_reset_required(hub, port1,
2808
					portstatus))
2809
				goto done;
2810
2811
			/*
2812
			 * If the port is in SS.Inactive or Compliance Mode, the
2813
			 * hot or warm reset failed.  Try another warm reset.
2814
			 */
2815
			if (!warm) {
2816
				dev_dbg(&port_dev->dev,
2817
						"hot reset failed, warm reset\n");
2818
				warm = true;
2819
			}
2820
		}
2833
		}
2821
2834
2822
		dev_dbg(&port_dev->dev,
2835
		dev_dbg(&port_dev->dev,

Return to bug 41752