Date: Sat, 29 Dec 2007 17:05:06 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 131971 for review Message-ID: <200712291705.lBTH560Z026459@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=131971 Change 131971 by hselasky@hselasky_laptop001 on 2007/12/29 17:04:28 This commit is device side related. o Fix support for Suspend and Resume. o Make "udev->flags.self_powered" read only in Device Side Mode. o Fix support for Remote Wakeup. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/at9100_dci.c#10 edit .. //depot/projects/usb/src/sys/dev/usb/if_cdce.c#42 edit .. //depot/projects/usb/src/sys/dev/usb/uhub.c#31 edit .. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#81 edit .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#90 edit .. //depot/projects/usb/src/sys/dev/usb/usb_template.c#12 edit .. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#97 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/at9100_dci.c#10 (text+ko) ==== @@ -270,7 +270,30 @@ if (!(temp & AT91_UDP_GSTATE_ESR)) { return; } - temp |= AT91_UDP_GSTATE_ESR; + AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp); + + return; +} + +static void +at9100_dci_rem_wakeup_set(struct usbd_device *udev, uint8_t is_on) +{ + struct at9100_dci_softc *sc; + uint32_t temp; + + DPRINTFN(4, "is_on=%u\n", is_on); + + mtx_assert(&(udev->bus->mtx), MA_OWNED); + + sc = AT9100_DCI_BUS2SC(udev->bus); + + temp = AT91_UDP_READ_4(sc, AT91_UDP_GSTATE); + + if (is_on) { + temp |= AT91_UDP_GSTATE_ESR; + } else { + temp &= ~AT91_UDP_GSTATE_ESR; + } AT91_UDP_WRITE_4(sc, AT91_UDP_GSTATE, temp); @@ -2542,4 +2565,5 @@ .set_stall = &at9100_dci_set_stall, .clear_stall = &at9100_dci_clear_stall, .vbus_interrupt = &at9100_dci_vbus_interrupt, + .rem_wakeup_set = &at9100_dci_rem_wakeup_set, }; ==== //depot/projects/usb/src/sys/dev/usb/if_cdce.c#42 (text+ko) ==== @@ -73,6 +73,8 @@ static device_attach_t cdce_attach; static device_detach_t cdce_detach; static device_shutdown_t cdce_shutdown; +static device_suspend_t cdce_suspend; +static device_resume_t cdce_resume; static usb_handle_request_t cdce_handle_request; static usbd_callback_t cdce_bulk_write_clear_stall_callback; @@ -774,6 +776,20 @@ } static int +cdce_suspend(device_t dev) +{ + device_printf(dev, "Suspending\n"); + return 0; +} + +static int +cdce_resume(device_t dev) +{ + device_printf(dev, "Resuming\n"); + return 0; +} + +static int cdce_ioctl_cb(struct ifnet *ifp, u_long command, caddr_t data) { struct cdce_softc *sc = ifp->if_softc; ==== //depot/projects/usb/src/sys/dev/usb/uhub.c#31 (text+ko) ==== @@ -434,6 +434,57 @@ } /*------------------------------------------------------------------------* + * uhub_suspend_resume_port + * + * Returns: + * 0: Success + * Else: A control transaction failed + *------------------------------------------------------------------------*/ +static usbd_status_t +uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno) +{ + struct usbd_device *child; + struct usbd_device *udev; + uint8_t is_suspend; + usbd_status_t err; + + DPRINTF(sc, 0, "port %d\n", portno); + + udev = sc->sc_udev; + child = usbd_bus_port_get_device(udev->bus, + udev->hub->ports + portno - 1); + + /* first clear the port suspend change bit */ + + err = usbreq_clear_port_feature + (udev, &usb_global_lock, portno, UHF_C_PORT_SUSPEND); + + if (err) { + goto done; + } + /* get fresh status */ + + err = uhub_read_port_status(sc, portno); + if (err) { + goto done; + } + /* get current state */ + + if (sc->sc_st.port_status & UPS_SUSPEND) { + is_suspend = 1; + } else { + is_suspend = 0; + } + /* do the suspend or resume */ + + if (child) { + err = usbd_suspend_resume(child, is_suspend); + } +done: + return (err); +} + +/*------------------------------------------------------------------------* * uhub_explore * * Returns: @@ -502,6 +553,13 @@ break; } } + if (sc->sc_st.port_change & UPS_C_SUSPEND) { + err = uhub_suspend_resume_port(sc, portno); + if (err) { + /* most likely the HUB is gone */ + break; + } + } err = uhub_explore_sub(sc, up); if (err) { /* no device(s) present */ ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#81 (text+ko) ==== @@ -888,7 +888,8 @@ /* Figure out if the device is self or bus powered. */ selfpowered = 0; if (!(udev->quirks->uq_flags & UQ_BUS_POWERED) && - (cdp->bmAttributes & UC_SELF_POWERED)) { + (cdp->bmAttributes & UC_SELF_POWERED) && + (udev->flags.usb_mode == USB_MODE_HOST)) { /* May be self powered. */ if (cdp->bmAttributes & UC_BUS_POWERED) { /* Must ask device. */ @@ -953,8 +954,11 @@ err = USBD_NO_POWER; goto error; } + /* Only update "self_powered" in USB Host Mode */ + if (udev->flags.usb_mode == USB_MODE_HOST) { + udev->flags.self_powered = selfpowered; + } udev->power = power; - udev->flags.self_powered = selfpowered; udev->curr_config_no = cdp->bConfigurationValue; /* Set the actual configuration value. */ @@ -1455,6 +1459,9 @@ if (dev == NULL) { return; } + if (!device_is_attached(dev)) { + return; + } if (do_suspend) { err = DEVICE_SUSPEND(dev); } else { @@ -1482,7 +1489,7 @@ /* nothing to do */ return (0); } - PRINTFN(3, ("udev=%p\n", udev)); + PRINTFN(3, ("udev=%p do_suspend=%d\n", udev, do_suspend)); mtx_lock(&(udev->bus->mtx)); if (udev->flags.suspended == do_suspend) { @@ -1671,6 +1678,8 @@ /* allow device time to set new address */ usbd_delay_ms(udev, USB_SET_ADDRESS_SETTLE); } else { + /* We are not self powered */ + udev->flags.self_powered = 0; /* * TODO: Make some kind of command that lets the user choose @@ -1757,7 +1766,6 @@ /* assume 100mA bus powered for now. Changed when configured. */ udev->power = USB_MIN_POWER; - udev->flags.self_powered = 0; /* get serial number string */ err = usbreq_get_string_any ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#90 (text+ko) ==== @@ -153,6 +153,7 @@ void *buf; uint32_t size; uint8_t usb_speed; + uint8_t self_powered; uint8_t bNumEndpoints; uint8_t bInterfaceNumber; uint8_t bAlternateSetting; @@ -179,6 +180,7 @@ void (*get_hw_ep_profile) (struct usbd_device *udev, const struct usbd_hw_ep_profile **ppf, uint8_t ep_addr); void (*set_stall) (struct usbd_device *udev, struct usbd_xfer *xfer, struct usbd_pipe *pipe); void (*clear_stall) (struct usbd_device *udev, struct usbd_pipe *pipe); + void (*rem_wakeup_set) (struct usbd_device *udev, uint8_t is_on); /* USB Device mode only - Optional */ void (*vbus_interrupt) (struct usbd_bus *, uint8_t is_on); @@ -414,7 +416,8 @@ uint8_t no_strings:1; /* set if USB device does not support * strings */ uint8_t detaching:1; /* set if USB device is detaching */ - uint8_t unused:3; + uint8_t remote_wakeup:1; /* set if remote wakeup is enabled */ + uint8_t unused:2; }; struct usbd_device { ==== //depot/projects/usb/src/sys/dev/usb/usb_template.c#12 (text+ko) ==== @@ -286,6 +286,13 @@ cd->iConfiguration = tcd->iConfiguration; cd->bmAttributes = tcd->bmAttributes; cd->bMaxPower = tcd->bMaxPower; + cd->bmAttributes |= (UC_REMOTE_WAKEUP | UC_BUS_POWERED); + + if (temp->self_powered) { + cd->bmAttributes |= UC_SELF_POWERED; + } else { + cd->bmAttributes &= ~UC_SELF_POWERED; + } } return; } @@ -1043,6 +1050,7 @@ bzero(uts, sizeof(*uts)); uts->usb_speed = udev->speed; + uts->self_powered = udev->flags.self_powered; /* first pass */ ==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#97 (text+ko) ==== @@ -3008,14 +3008,27 @@ * usbd_handle_remote_wakeup *------------------------------------------------------------------------*/ static usbd_status_t -usbd_handle_remote_wakeup(struct usbd_xfer *xfer, uint8_t do_suspend) +usbd_handle_remote_wakeup(struct usbd_xfer *xfer, uint8_t is_on) { - usbd_status_t err; + struct usbd_device *udev; + struct usbd_bus *bus; + + udev = xfer->udev; + bus = udev->bus; + + mtx_lock(&(bus->mtx)); + + if (is_on) { + udev->flags.remote_wakeup = 1; + } else { + udev->flags.remote_wakeup = 0; + } + + (bus->methods->rem_wakeup_set) (xfer->udev, is_on); + + mtx_unlock(&(bus->mtx)); - mtx_unlock(xfer->priv_mtx); - err = usbd_suspend_resume(xfer->udev, do_suspend); - mtx_lock(xfer->priv_mtx); - return (err); + return (0); /* success */ } /*------------------------------------------------------------------------* @@ -3148,6 +3161,22 @@ goto tr_handle_set_address; case UR_SET_CONFIG: goto tr_handle_set_config; + case UR_CLEAR_FEATURE: + switch (wValue) { + case UF_DEVICE_REMOTE_WAKEUP: + goto tr_handle_clear_wakeup; + default: + goto tr_stalled; + } + break; + case UR_SET_FEATURE: + switch (wValue) { + case UF_DEVICE_REMOTE_WAKEUP: + goto tr_handle_set_wakeup; + default: + goto tr_stalled; + } + break; default: goto tr_stalled; } @@ -3159,19 +3188,14 @@ switch (wValue) { case UF_ENDPOINT_HALT: goto tr_handle_clear_halt; - case UF_DEVICE_REMOTE_WAKEUP: - goto tr_handle_clear_wakeup; default: goto tr_stalled; } break; - case UR_SET_FEATURE: switch (wValue) { case UF_ENDPOINT_HALT: goto tr_handle_set_halt; - case UF_DEVICE_REMOTE_WAKEUP: - goto tr_handle_set_wakeup; default: goto tr_stalled; } @@ -3214,8 +3238,19 @@ goto tr_valid; tr_handle_get_status: - /* XXX FIXME */ - USETW(temp.wStatus, UDS_SELF_POWERED); + + wValue = 0; + + mtx_lock(&(udev->bus->mtx)); + if (udev->flags.remote_wakeup) { + wValue |= UDS_REMOTE_WAKEUP; + } + if (udev->flags.self_powered) { + wValue |= UDS_SELF_POWERED; + } + mtx_unlock(&(udev->bus->mtx)); + + USETW(temp.wStatus, wValue); src_mcopy = temp.wStatus; max_len = sizeof(temp.wStatus); goto tr_valid;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712291705.lBTH560Z026459>