diff options
author | hselasky <hselasky@FreeBSD.org> | 2012-01-12 21:21:20 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2012-01-12 21:21:20 +0000 |
commit | 6c85604246f379ee4bb4d0701a1f85b5b1cdf10f (patch) | |
tree | 38f3d90c8fddf434631d370481d287f6ba079ccb /sys/dev/usb/usb_hub.c | |
parent | 0238379b18c22577e791b322bb2f68d9447a5b12 (diff) | |
download | FreeBSD-src-6c85604246f379ee4bb4d0701a1f85b5b1cdf10f.zip FreeBSD-src-6c85604246f379ee4bb4d0701a1f85b5b1cdf10f.tar.gz |
- Try to fix support for USB 3.0 HUBs.
- Try to fix support for USB 3.0 suspend and resume.
MFC after: 1 week
Diffstat (limited to 'sys/dev/usb/usb_hub.c')
-rw-r--r-- | sys/dev/usb/usb_hub.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index 168e9eb..0cc055e 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -369,10 +369,25 @@ repeat: } /* check if there is no power on the port and print a warning */ - if (!(sc->sc_st.port_status & UPS_PORT_POWER)) { - DPRINTF("WARNING: strange, connected port %d " - "has no power\n", portno); + switch (udev->speed) { + case USB_SPEED_HIGH: + case USB_SPEED_FULL: + case USB_SPEED_LOW: + if (!(sc->sc_st.port_status & UPS_PORT_POWER)) { + DPRINTF("WARNING: strange, connected port %d " + "has no power\n", portno); + } + break; + case USB_SPEED_SUPER: + if (!(sc->sc_st.port_status & UPS_PORT_POWER_SS)) { + DPRINTF("WARNING: strange, connected port %d " + "has no power\n", portno); + } + break; + default: + break; } + /* check if the device is in Host Mode */ if (!(sc->sc_st.port_status & UPS_PORT_MODE_DEVICE)) { @@ -611,6 +626,7 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno) switch (UPS_PORT_LINK_STATE_GET(sc->sc_st.port_status)) { case UPS_PORT_LS_U0: case UPS_PORT_LS_U1: + case UPS_PORT_LS_U2: case UPS_PORT_LS_RESUME: is_suspend = 0; break; @@ -632,8 +648,7 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno) */ if (is_suspend == 0) usb_dev_resume_peer(child); - else if ((child->flags.usb_mode == USB_MODE_DEVICE) || - (usb_device_20_compatible(child) == 0)) + else if (child->flags.usb_mode == USB_MODE_DEVICE) usb_dev_suspend_peer(child); } done: @@ -2064,7 +2079,6 @@ usb_peer_should_wakeup(struct usb_device *udev) (udev->pwr_save.write_refs != 0) || ((udev->pwr_save.read_refs != 0) && (udev->flags.usb_mode == USB_MODE_HOST) && - (usb_device_20_compatible(udev) != 0) && (usb_peer_can_wakeup(udev) == 0))); } @@ -2244,6 +2258,14 @@ usb_dev_resume_peer(struct usb_device *udev) DPRINTFN(0, "Resuming port failed\n"); return; } + } else { + /* resume current port (Valid in Host and Device Mode) */ + err = usbd_req_set_port_link_state(udev->parent_hub, + NULL, udev->port_no, UPS_PORT_LS_U0); + if (err) { + DPRINTFN(0, "Resuming port failed\n"); + return; + } } /* resume settle time */ @@ -2285,8 +2307,7 @@ usb_dev_resume_peer(struct usb_device *udev) usbd_sr_unlock(udev); /* check if peer has wakeup capability */ - if (usb_peer_can_wakeup(udev) && - usb_device_20_compatible(udev)) { + if (usb_peer_can_wakeup(udev)) { /* clear remote wakeup */ err = usbd_req_clear_device_feature(udev, NULL, UF_DEVICE_REMOTE_WAKEUP); @@ -2347,8 +2368,7 @@ repeat: } } - if (usb_peer_can_wakeup(udev) && - usb_device_20_compatible(udev)) { + if (usb_peer_can_wakeup(udev)) { /* * This request needs to be done before we set * "udev->flags.self_suspended": @@ -2380,8 +2400,7 @@ repeat: USB_BUS_UNLOCK(udev->bus); if (err != 0) { - if (usb_peer_can_wakeup(udev) && - usb_device_20_compatible(udev)) { + if (usb_peer_can_wakeup(udev)) { /* allow device to do remote wakeup */ err = usbd_req_clear_device_feature(udev, NULL, UF_DEVICE_REMOTE_WAKEUP); @@ -2437,6 +2456,14 @@ repeat: DPRINTFN(0, "Suspending port failed\n"); return; } + } else { + /* suspend current port */ + err = usbd_req_set_port_link_state(udev->parent_hub, + NULL, udev->port_no, UPS_PORT_LS_U3); + if (err) { + DPRINTFN(0, "Suspending port failed\n"); + return; + } } udev = udev->parent_hub; |