mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
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:
parent
16589bea5b
commit
e280503373
4 changed files with 55 additions and 41 deletions
|
|
@ -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 @@ done:
|
|||
*
|
||||
* 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 @@ repeat_set_config:
|
|||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -277,6 +277,10 @@ tr_repeat:
|
|||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Doing the alternate setting will detach the
|
||||
* interface aswell:
|
||||
*/
|
||||
error = usb2_set_alt_interface_index(udev,
|
||||
iface_index, req.wValue[0]);
|
||||
if (error) {
|
||||
|
|
|
|||
|
|
@ -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 @@ repeat:
|
|||
|
||||
/* 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 @@ repeat:
|
|||
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 @@ error:
|
|||
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 @@ repeat:
|
|||
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 @@ repeat:
|
|||
|
||||
/* 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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue