PERFORCE change 180523 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Tue Jul 6 09:52:33 UTC 2010
http://p4web.freebsd.org/@@180523?ac=10
Change 180523 by hselasky at hselasky_laptop001 on 2010/07/06 09:51:56
USB CORE: (bugfixes)
- there are two more conditions for waking up
an USB device (See: usb_peer_should_wakeup() function):
a) when a new driver has been loaded
b) when we are re-enumerating
- rework the re-enumerate code, so it
runs in series with the rest of the USB
explore code, so that we avoid re-enumerating
the wrong USB device. The re-enumerate feature
is not very commonly used.
- patch by: HPS @
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/usb_dev.c#46 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_device.h#37 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_generic.c#32 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_hub.c#48 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/usb_dev.c#46 (text+ko) ====
@@ -1085,21 +1085,45 @@
err = usb_ioctl_f_sub(f, cmd, addr, td);
}
KASSERT(f != NULL, ("fifo not found"));
- if (err == ENOIOCTL) {
- err = (f->methods->f_ioctl) (f, cmd, addr, fflags);
- DPRINTFN(2, "f_ioctl cmd 0x%lx = %d\n", cmd, err);
- if (err == ENOIOCTL) {
- if (usb_usb_ref_device(cpd, &refs)) {
- err = ENXIO;
- goto done;
- }
- err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
- DPRINTFN(2, "f_ioctl_post cmd 0x%lx = %d\n", cmd, err);
- }
+ if (err != ENOIOCTL)
+ goto done;
+
+ err = (f->methods->f_ioctl) (f, cmd, addr, fflags);
+
+ DPRINTFN(2, "f_ioctl cmd 0x%lx = %d\n", cmd, err);
+
+ if (err != ENOIOCTL)
+ goto done;
+
+ if (usb_usb_ref_device(cpd, &refs)) {
+ err = ENXIO;
+ goto done;
}
- if (err == ENOIOCTL) {
+
+ err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
+
+ DPRINTFN(2, "f_ioctl_post cmd 0x%lx = %d\n", cmd, err);
+
+ if (err == ENOIOCTL)
err = ENOTTY;
+
+ if (err)
+ goto done;
+
+ /* Wait for re-enumeration, if any */
+
+ while (f->udev->re_enumerate_wait != 0) {
+
+ usb_unref_device(cpd, &refs);
+
+ usb_pause_mtx(NULL, hz / 128);
+
+ if (usb_ref_device(cpd, &refs, 1 /* need uref */)) {
+ err = ENXIO;
+ goto done;
+ }
}
+
done:
usb_unref_device(cpd, &refs);
return (err);
==== //depot/projects/usb/src/sys/dev/usb/usb_device.h#37 (text+ko) ====
@@ -160,6 +160,7 @@
uint8_t hs_port_no; /* high-speed HUB port number */
uint8_t driver_added_refcount; /* our driver added generation count */
uint8_t power_mode; /* see USB_POWER_XXX */
+ uint8_t re_enumerate_wait; /* set if re-enum. is in progress */
uint8_t ifaces_max; /* number of interfaces present */
uint8_t endpoints_max; /* number of endpoints present */
==== //depot/projects/usb/src/sys/dev/usb/usb_generic.c#32 (text+ko) ====
@@ -109,7 +109,7 @@
static int ugen_re_enumerate(struct usb_fifo *);
static int ugen_iface_ioctl(struct usb_fifo *, u_long, void *, int);
static uint8_t ugen_fs_get_complete(struct usb_fifo *, uint8_t *);
-static int ugen_fs_uninit(struct usb_fifo *f);
+static int ugen_fs_uninit(struct usb_fifo *f);
/* structures */
@@ -951,23 +951,19 @@
if (error) {
return (error);
}
- /* get the device unconfigured */
- error = ugen_set_config(f, USB_UNCONFIG_INDEX);
- if (error) {
- return (error);
+ if (udev->flags.usb_mode != USB_MODE_HOST) {
+ /* not possible in device side mode */
+ return (ENOTTY);
}
- /* do a bus-reset */
- mtx_lock(f->priv_mtx);
- error = usbd_req_re_enumerate(udev, f->priv_mtx);
- mtx_unlock(f->priv_mtx);
-
- if (error) {
- return (ENXIO);
+ /* make sure all FIFO's are gone */
+ /* else there can be a deadlock */
+ if (ugen_fs_uninit(f)) {
+ /* ignore any errors */
+ DPRINTFN(6, "no FIFOs\n");
}
- /* restore configuration to index 0 */
- error = ugen_set_config(f, 0);
- if (error) {
- return (error);
+ if (udev->re_enumerate_wait == 0) {
+ udev->re_enumerate_wait = 1;
+ usb_needs_explore(udev->bus, 0);
}
return (0);
}
@@ -1775,9 +1771,11 @@
/* if we are powered off we need to re-enumerate first */
if (old_mode == USB_POWER_MODE_OFF) {
- err = ugen_re_enumerate(f);
- if (err)
- return (err);
+ if (udev->flags.usb_mode == USB_MODE_HOST) {
+ if (udev->re_enumerate_wait == 0)
+ udev->re_enumerate_wait = 1;
+ }
+ /* set power mode will wake up the explore thread */
}
/* set new power mode */
==== //depot/projects/usb/src/sys/dev/usb/usb_hub.c#48 (text+ko) ====
@@ -234,6 +234,24 @@
/* nothing to do */
goto done;
}
+
+ /* check if device should be re-enumerated */
+
+ if (child->flags.usb_mode == USB_MODE_HOST) {
+ usbd_enum_lock(child);
+ if (child->re_enumerate_wait) {
+ err = usbd_set_config_index(child, USB_UNCONFIG_INDEX);
+ if (err == 0)
+ err = usbd_req_re_enumerate(child, NULL);
+ if (err == 0)
+ err = usbd_set_config_index(child, 0);
+
+ child->re_enumerate_wait = 0;
+ err = 0;
+ }
+ usbd_enum_unlock(child);
+ }
+
/* check if probe and attach should be done */
if (child->driver_added_refcount != refcount) {
@@ -1761,6 +1779,8 @@
usb_peer_should_wakeup(struct usb_device *udev)
{
return ((udev->power_mode == USB_POWER_MODE_ON) ||
+ (udev->driver_added_refcount != udev->bus->driver_added_refcount) ||
+ (udev->re_enumerate_wait != 0) ||
(udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0) ||
(udev->pwr_save.write_refs != 0) ||
((udev->pwr_save.read_refs != 0) &&
More information about the p4-projects
mailing list