Date: Mon, 26 Jan 2009 17:49:58 +0000 (UTC) From: Andrew Thompson <thompsa@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r187730 - in head/sys/dev/usb2: controller core Message-ID: <200901261749.n0QHnwZm057789@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: thompsa Date: Mon Jan 26 17:49:58 2009 New Revision: 187730 URL: http://svn.freebsd.org/changeset/base/187730 Log: MFp4 //depot/projects/usb/ @156522,156530 UHCI SOF Quirk. Makes some broken USB devices work again. Reported by several people. Patch made by me. Submitted by: Hans Petter Selasky Modified: head/sys/dev/usb2/controller/uhci2.c head/sys/dev/usb2/controller/usb2_controller.h head/sys/dev/usb2/core/usb2_hub.c Modified: head/sys/dev/usb2/controller/uhci2.c ============================================================================== --- head/sys/dev/usb2/controller/uhci2.c Mon Jan 26 17:49:48 2009 (r187729) +++ head/sys/dev/usb2/controller/uhci2.c Mon Jan 26 17:49:58 2009 (r187730) @@ -2396,6 +2396,24 @@ uhci_portreset(uhci_softc_t *sc, uint16_ else return (USB_ERR_IOERROR); + /* + * Before we do anything, turn on SOF messages on the USB + * BUS. Some USB devices do not cope without them! + */ + if (!(UREAD2(sc, UHCI_CMD) & UHCI_CMD_RS)) { + + DPRINTF("Activating SOFs!\n"); + + UHCICMD(sc, (UHCI_CMD_MAXP | UHCI_CMD_RS)); + + /* wait a little bit */ + if (use_polling) { + DELAY(10000); + } else { + usb2_pause_mtx(&sc->sc_bus.bus_mtx, 10); + } + } + x = URWMASK(UREAD2(sc, port)); UWRITE2(sc, port, x | UHCI_PORTSC_PR); @@ -3320,7 +3338,13 @@ uhci_set_hw_power(struct usb2_bus *bus) flags = bus->hw_power_state; + /* + * WARNING: Some FULL speed USB devices require periodic SOF + * messages! If any USB devices are connected through the + * UHCI, power save will be disabled! + */ if (flags & (USB_HW_POWER_CONTROL | + USB_HW_POWER_NON_ROOT_HUB | USB_HW_POWER_BULK | USB_HW_POWER_INTERRUPT | USB_HW_POWER_ISOC)) { Modified: head/sys/dev/usb2/controller/usb2_controller.h ============================================================================== --- head/sys/dev/usb2/controller/usb2_controller.h Mon Jan 26 17:49:48 2009 (r187729) +++ head/sys/dev/usb2/controller/usb2_controller.h Mon Jan 26 17:49:58 2009 (r187730) @@ -84,6 +84,11 @@ struct usb2_bus_methods { * are active: */ #define USB_HW_POWER_ISOC 0x08 + /* + * The following flag is set if one or more non-root-HUB devices + * are present on the given USB bus: + */ +#define USB_HW_POWER_NON_ROOT_HUB 0x10 /* USB Device mode only - Mandatory */ Modified: head/sys/dev/usb2/core/usb2_hub.c ============================================================================== --- head/sys/dev/usb2/core/usb2_hub.c Mon Jan 26 17:49:48 2009 (r187729) +++ head/sys/dev/usb2/core/usb2_hub.c Mon Jan 26 17:49:58 2009 (r187730) @@ -1503,7 +1503,7 @@ usb2_bus_powerd(struct usb2_bus *bus) unsigned int temp; unsigned int limit; unsigned int mintime; - uint32_t type_refs[4]; + uint32_t type_refs[5]; uint8_t x; uint8_t rem_wakeup; @@ -1564,6 +1564,7 @@ usb2_bus_powerd(struct usb2_bus *bus) type_refs[1] = 0; type_refs[2] = 0; type_refs[3] = 0; + type_refs[4] = 0; /* Re-loop all the devices to get the actual state */ @@ -1574,6 +1575,9 @@ usb2_bus_powerd(struct usb2_bus *bus) if (udev == NULL) continue; + /* we found a non-Root-Hub USB device */ + type_refs[4] += 1; + /* "last_xfer_time" can be updated by a resume */ temp = ticks - udev->pwr_save.last_xfer_time; @@ -1604,6 +1608,8 @@ usb2_bus_powerd(struct usb2_bus *bus) bus->hw_power_state |= USB_HW_POWER_INTERRUPT; if (type_refs[UE_ISOCHRONOUS] != 0) bus->hw_power_state |= USB_HW_POWER_ISOC; + if (type_refs[4] != 0) + bus->hw_power_state |= USB_HW_POWER_NON_ROOT_HUB; } USB_BUS_UNLOCK(bus);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901261749.n0QHnwZm057789>