MFp4 //depot/projects/usb@157958

- We don't need to exit the Giant mutex when sleeping. This is done
  automatically. Replace Giant by NULL mutex for all control requests in the
  enumeration path.
- Optimise away duplicate alternate interface selection requests in USB Host
  mode.

Submitted by:	Hans Petter Selasky
This commit is contained in:
Andrew Thompson 2009-02-24 03:41:52 +00:00
parent 16589bea5b
commit e280503373
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=188986
4 changed files with 55 additions and 41 deletions

View File

@ -551,12 +551,12 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
* device. "usb2_free_iface_data()" will also reset
* the current config number and index.
*/
err = usb2_req_set_config(udev, &Giant, USB_UNCONFIG_NO);
err = usb2_req_set_config(udev, NULL, USB_UNCONFIG_NO);
goto done;
}
/* get the full config descriptor */
err = usb2_req_get_config_desc_full(udev,
&Giant, &cdp, M_USB, index);
NULL, &cdp, M_USB, index);
if (err) {
goto done;
}
@ -583,7 +583,7 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
* determined by the HUB characteristics.
*/
err = usb2_req_get_hub_descriptor
(udev, &Giant, &hd, 1);
(udev, NULL, &hd, 1);
if (err) {
DPRINTFN(0, "could not read "
"HUB descriptor: %s\n",
@ -597,7 +597,7 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
UGETW(hd.wHubCharacteristics));
} else {
err = usb2_req_get_device_status
(udev, &Giant, &ds);
(udev, NULL, &ds);
if (err) {
DPRINTFN(0, "could not read "
"device status: %s\n",
@ -640,7 +640,7 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
udev->curr_config_index = index;
/* Set the actual configuration value. */
err = usb2_req_set_config(udev, &Giant, cdp->bConfigurationValue);
err = usb2_req_set_config(udev, NULL, cdp->bConfigurationValue);
if (err) {
goto done;
}
@ -669,8 +669,10 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
*
* This function will select an alternate interface index for the
* given interface index. The interface should not be in use when this
* function is called. That means there should be no open USB
* transfers. Else an error is returned.
* function is called. That means there should not be any open USB
* transfers. Else an error is returned. If the alternate setting is
* already set this function will simply return success. This function
* is called in Host mode and Device mode!
*
* Returns:
* 0: Success
@ -697,6 +699,15 @@ usb2_set_alt_interface_index(struct usb2_device *udev,
}
if (udev->flags.usb2_mode == USB_MODE_DEVICE) {
usb2_detach_device(udev, iface_index, 1);
} else {
if (iface->alt_index == alt_index) {
/*
* Optimise away duplicate setting of
* alternate setting in USB Host Mode!
*/
err = 0;
goto done;
}
}
/*
* Free all generic FIFOs for this interface, except control
@ -708,8 +719,7 @@ usb2_set_alt_interface_index(struct usb2_device *udev,
if (err) {
goto done;
}
err = usb2_req_set_alt_interface_no
(udev, &Giant, iface_index,
err = usb2_req_set_alt_interface_no(udev, NULL, iface_index,
iface->idesc->bAlternateSetting);
done:
@ -1415,7 +1425,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
if (udev->flags.usb2_mode == USB_MODE_HOST) {
err = usb2_req_set_address(udev, &Giant, device_index);
err = usb2_req_set_address(udev, NULL, device_index);
/* This is the new USB device address from now on */
@ -1435,7 +1445,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
"(ignored)\n", udev->address);
}
/* allow device time to set new address */
usb2_pause_mtx(&Giant,
usb2_pause_mtx(NULL,
USB_MS_TO_TICKS(USB_SET_ADDRESS_SETTLE));
} else {
/* We are not self powered */
@ -1464,13 +1474,13 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
* 0. If this value is different from "USB_MAX_IPACKET" a new
* USB control request will be setup!
*/
err = usb2_req_get_desc(udev, &Giant, NULL, &udev->ddesc,
err = usb2_req_get_desc(udev, NULL, NULL, &udev->ddesc,
USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
if (err) {
DPRINTFN(0, "getting device descriptor "
"at addr %d failed!\n", udev->address);
/* XXX try to re-enumerate the device */
err = usb2_req_re_enumerate(udev, &Giant);
err = usb2_req_re_enumerate(udev, NULL);
if (err) {
goto done;
}
@ -1486,7 +1496,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
udev->speed);
/* get the full device descriptor */
err = usb2_req_get_device_desc(udev, &Giant, &udev->ddesc);
err = usb2_req_get_device_desc(udev, NULL, &udev->ddesc);
if (err) {
DPRINTF("addr=%d, getting full desc failed\n",
udev->address);
@ -1525,7 +1535,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
udev->ddesc.iProduct ||
udev->ddesc.iSerialNumber) {
/* read out the language ID string */
err = usb2_req_get_string_desc(udev, &Giant,
err = usb2_req_get_string_desc(udev, NULL,
(char *)scratch_ptr, 4, scratch_size,
USB_LANGUAGE_TABLE);
} else {
@ -1544,21 +1554,21 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
/* get serial number string */
err = usb2_req_get_string_any
(udev, &Giant, (char *)scratch_ptr,
(udev, NULL, (char *)scratch_ptr,
scratch_size, udev->ddesc.iSerialNumber);
strlcpy(udev->serial, (char *)scratch_ptr, sizeof(udev->serial));
/* get manufacturer string */
err = usb2_req_get_string_any
(udev, &Giant, (char *)scratch_ptr,
(udev, NULL, (char *)scratch_ptr,
scratch_size, udev->ddesc.iManufacturer);
strlcpy(udev->manufacturer, (char *)scratch_ptr, sizeof(udev->manufacturer));
/* get product string */
err = usb2_req_get_string_any
(udev, &Giant, (char *)scratch_ptr,
(udev, NULL, (char *)scratch_ptr,
scratch_size, udev->ddesc.iProduct);
strlcpy(udev->product, (char *)scratch_ptr, sizeof(udev->product));
@ -1609,7 +1619,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
set_config_failed = 1;
/* XXX try to re-enumerate the device */
err = usb2_req_re_enumerate(
udev, &Giant);
udev, NULL);
if (err == 0)
goto repeat_set_config;
}

View File

@ -664,7 +664,7 @@ ugen_get_cdesc(struct usb2_fifo *f, struct usb2_gen_descriptor *ugd)
} else {
if (usb2_req_get_config_desc_full(udev,
&Giant, &cdesc, M_USBDEV,
NULL, &cdesc, M_USBDEV,
ugd->ugd_config_index)) {
return (ENXIO);
}
@ -695,7 +695,7 @@ ugen_get_sdesc(struct usb2_fifo *f, struct usb2_gen_descriptor *ugd)
uint16_t size = sizeof(f->udev->bus->scratch[0].data);
int error;
if (usb2_req_get_string_desc(f->udev, &Giant, ptr,
if (usb2_req_get_string_desc(f->udev, NULL, ptr,
size, ugd->ugd_lang_id, ugd->ugd_string_index)) {
error = EINVAL;
} else {

View File

@ -277,6 +277,10 @@ usb2_handle_iface_request(struct usb2_xfer *xfer,
}
break;
}
/*
* Doing the alternate setting will detach the
* interface aswell:
*/
error = usb2_set_alt_interface_index(udev,
iface_index, req.wValue[0]);
if (error) {

View File

@ -244,7 +244,7 @@ uhub_read_port_status(struct uhub_softc *sc, uint8_t portno)
usb2_error_t err;
err = usb2_req_get_port_status(
sc->sc_udev, &Giant, &ps, portno);
sc->sc_udev, NULL, &ps, portno);
/* update status regardless of error */
@ -289,7 +289,7 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
/* first clear the port connection change bit */
err = usb2_req_clear_port_feature(udev, &Giant,
err = usb2_req_clear_port_feature(udev, NULL,
portno, UHF_C_PORT_CONNECTION);
if (err) {
@ -329,18 +329,18 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
DPRINTF("Port %d was still "
"suspended, clearing.\n", portno);
err = usb2_req_clear_port_feature(sc->sc_udev,
&Giant, portno, UHF_PORT_SUSPEND);
NULL, portno, UHF_PORT_SUSPEND);
}
/* USB Host Mode */
/* wait for maximum device power up time */
usb2_pause_mtx(&Giant,
usb2_pause_mtx(NULL,
USB_MS_TO_TICKS(USB_PORT_POWERUP_DELAY));
/* reset port, which implies enabling it */
err = usb2_req_reset_port(udev, &Giant, portno);
err = usb2_req_reset_port(udev, NULL, portno);
if (err) {
DPRINTFN(0, "port %d reset "
@ -425,7 +425,7 @@ uhub_reattach_port(struct uhub_softc *sc, uint8_t portno)
if (err == 0) {
if (sc->sc_st.port_status & UPS_PORT_ENABLED) {
err = usb2_req_clear_port_feature(
sc->sc_udev, &Giant,
sc->sc_udev, NULL,
portno, UHF_PORT_ENABLE);
}
}
@ -459,7 +459,7 @@ uhub_suspend_resume_port(struct uhub_softc *sc, uint8_t portno)
/* first clear the port suspend change bit */
err = usb2_req_clear_port_feature(udev, &Giant,
err = usb2_req_clear_port_feature(udev, NULL,
portno, UHF_C_PORT_SUSPEND);
if (err) {
DPRINTF("clearing suspend failed.\n");
@ -542,7 +542,7 @@ uhub_explore(struct usb2_device *udev)
if (sc->sc_st.port_change & UPS_C_OVERCURRENT_INDICATOR) {
DPRINTF("Overcurrent on port %u.\n", portno);
err = usb2_req_clear_port_feature(
udev, &Giant, portno, UHF_C_PORT_OVER_CURRENT);
udev, NULL, portno, UHF_C_PORT_OVER_CURRENT);
if (err) {
/* most likely the HUB is gone */
break;
@ -558,7 +558,7 @@ uhub_explore(struct usb2_device *udev)
}
if (sc->sc_st.port_change & UPS_C_PORT_ENABLED) {
err = usb2_req_clear_port_feature(
udev, &Giant, portno, UHF_C_PORT_ENABLE);
udev, NULL, portno, UHF_C_PORT_ENABLE);
if (err) {
/* most likely the HUB is gone */
break;
@ -682,13 +682,13 @@ uhub_attach(device_t dev)
DPRINTFN(2, "getting HUB descriptor\n");
/* assuming that there is one port */
err = usb2_req_get_hub_descriptor(udev, &Giant, &hubdesc, 1);
err = usb2_req_get_hub_descriptor(udev, NULL, &hubdesc, 1);
nports = hubdesc.bNbrPorts;
if (!err && (nports >= 8)) {
/* get complete HUB descriptor */
err = usb2_req_get_hub_descriptor(udev, &Giant, &hubdesc, nports);
err = usb2_req_get_hub_descriptor(udev, NULL, &hubdesc, nports);
}
if (err) {
DPRINTFN(0, "getting hub descriptor failed,"
@ -737,7 +737,7 @@ uhub_attach(device_t dev)
goto error;
}
/* wait with power off for a while */
usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME));
usb2_pause_mtx(NULL, USB_MS_TO_TICKS(USB_POWER_DOWN_TIME));
/*
* To have the best chance of success we do things in the exact same
@ -784,7 +784,7 @@ uhub_attach(device_t dev)
}
if (!err) {
/* turn the power on */
err = usb2_req_set_port_feature(udev, &Giant,
err = usb2_req_set_port_feature(udev, NULL,
portno, UHF_PORT_POWER);
}
if (err) {
@ -795,7 +795,7 @@ uhub_attach(device_t dev)
portno);
/* wait for stable power */
usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(pwrdly));
usb2_pause_mtx(NULL, USB_MS_TO_TICKS(pwrdly));
}
device_printf(dev, "%d port%s with %d "
@ -1661,13 +1661,13 @@ usb2_dev_resume_peer(struct usb2_device *udev)
/* resume current port (Valid in Host and Device Mode) */
err = usb2_req_clear_port_feature(udev->parent_hub,
&Giant, udev->port_no, UHF_PORT_SUSPEND);
NULL, udev->port_no, UHF_PORT_SUSPEND);
if (err) {
DPRINTFN(0, "Resuming port failed!\n");
return;
}
/* resume settle time */
usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
usb2_pause_mtx(NULL, USB_MS_TO_TICKS(USB_PORT_RESUME_DELAY));
if (bus->methods->device_resume != NULL) {
/* resume USB device on the USB controller */
@ -1703,7 +1703,7 @@ usb2_dev_resume_peer(struct usb2_device *udev)
if (usb2_peer_can_wakeup(udev)) {
/* clear remote wakeup */
err = usb2_req_clear_device_feature(udev,
&Giant, UF_DEVICE_REMOTE_WAKEUP);
NULL, UF_DEVICE_REMOTE_WAKEUP);
if (err) {
DPRINTFN(0, "Clearing device "
"remote wakeup failed: %s!\n",
@ -1782,7 +1782,7 @@ usb2_dev_suspend_peer(struct usb2_device *udev)
if (usb2_peer_can_wakeup(udev)) {
/* allow device to do remote wakeup */
err = usb2_req_set_device_feature(udev,
&Giant, UF_DEVICE_REMOTE_WAKEUP);
NULL, UF_DEVICE_REMOTE_WAKEUP);
if (err) {
DPRINTFN(0, "Setting device "
"remote wakeup failed!\n");
@ -1803,12 +1803,12 @@ usb2_dev_suspend_peer(struct usb2_device *udev)
/* do DMA delay */
temp = usb2_get_dma_delay(udev->bus);
usb2_pause_mtx(&Giant, USB_MS_TO_TICKS(temp));
usb2_pause_mtx(NULL, USB_MS_TO_TICKS(temp));
}
/* suspend current port */
err = usb2_req_set_port_feature(udev->parent_hub,
&Giant, udev->port_no, UHF_PORT_SUSPEND);
NULL, udev->port_no, UHF_PORT_SUSPEND);
if (err) {
DPRINTFN(0, "Suspending port failed\n");
return;