From owner-svn-src-stable@FreeBSD.ORG Wed Sep 2 02:12:07 2009 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AE6B11065670; Wed, 2 Sep 2009 02:12:07 +0000 (UTC) (envelope-from alfred@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 99DE88FC13; Wed, 2 Sep 2009 02:12:07 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n822C7L4078389; Wed, 2 Sep 2009 02:12:07 GMT (envelope-from alfred@svn.freebsd.org) Received: (from alfred@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n822C7Il078379; Wed, 2 Sep 2009 02:12:07 GMT (envelope-from alfred@svn.freebsd.org) Message-Id: <200909020212.n822C7Il078379@svn.freebsd.org> From: Alfred Perlstein Date: Wed, 2 Sep 2009 02:12:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r196746 - in stable/8/sys: . amd64/include/xen cddl/contrib/opensolaris contrib/dev/acpica contrib/pf dev/usb dev/usb/input dev/xen/xenpci X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Sep 2009 02:12:07 -0000 Author: alfred Date: Wed Sep 2 02:12:07 2009 New Revision: 196746 URL: http://svn.freebsd.org/changeset/base/196746 Log: MFC: r196489,196498 Critical USB bugfixes for 8.0 Approved by: re Modified: stable/8/sys/ (props changed) stable/8/sys/amd64/include/xen/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) stable/8/sys/contrib/dev/acpica/ (props changed) stable/8/sys/contrib/pf/ (props changed) stable/8/sys/dev/usb/input/ukbd.c stable/8/sys/dev/usb/usb_dev.c stable/8/sys/dev/usb/usb_device.c stable/8/sys/dev/usb/usb_device.h stable/8/sys/dev/usb/usb_handle_request.c stable/8/sys/dev/usb/usb_hub.c stable/8/sys/dev/usb/usb_process.c stable/8/sys/dev/usb/usb_process.h stable/8/sys/dev/usb/usb_transfer.c stable/8/sys/dev/xen/xenpci/ (props changed) Modified: stable/8/sys/dev/usb/input/ukbd.c ============================================================================== --- stable/8/sys/dev/usb/input/ukbd.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/input/ukbd.c Wed Sep 2 02:12:07 2009 (r196746) @@ -96,10 +96,14 @@ __FBSDID("$FreeBSD$"); #if USB_DEBUG static int ukbd_debug = 0; +static int ukbd_no_leds = 0; SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW, 0, "USB ukbd"); SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RW, &ukbd_debug, 0, "Debug level"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, no_leds, CTLFLAG_RW, + &ukbd_no_leds, 0, "Disables setting of keyboard leds"); + #endif #define UPROTO_BOOT_KEYBOARD 1 @@ -165,6 +169,7 @@ struct ukbd_softc { #define UKBD_FLAG_APPLE_EJECT 0x0040 #define UKBD_FLAG_APPLE_FN 0x0080 #define UKBD_FLAG_APPLE_SWAP 0x0100 +#define UKBD_FLAG_TIMER_RUNNING 0x0200 int32_t sc_mode; /* input mode (K_XLATE,K_RAW,K_CODE) */ int32_t sc_state; /* shift/lock key state */ @@ -279,6 +284,25 @@ static device_attach_t ukbd_attach; static device_detach_t ukbd_detach; static device_resume_t ukbd_resume; +static uint8_t +ukbd_any_key_pressed(struct ukbd_softc *sc) +{ + uint8_t i; + uint8_t j; + + for (j = i = 0; i < UKBD_NKEYCODE; i++) + j |= sc->sc_odata.keycode[i]; + + return (j ? 1 : 0); +} + +static void +ukbd_start_timer(struct ukbd_softc *sc) +{ + sc->sc_flags |= UKBD_FLAG_TIMER_RUNNING; + usb_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc); +} + static void ukbd_put_key(struct ukbd_softc *sc, uint32_t key) { @@ -308,11 +332,15 @@ ukbd_do_poll(struct ukbd_softc *sc, uint usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); - DELAY(1000); /* delay 1 ms */ + /* Delay-optimised support for repetition of keys */ - sc->sc_time_ms++; + if (ukbd_any_key_pressed(sc)) { + /* a key is pressed - need timekeeping */ + DELAY(1000); - /* support repetition of keys: */ + /* 1 millisecond has passed */ + sc->sc_time_ms += 1; + } ukbd_interrupt(sc); @@ -470,7 +498,11 @@ ukbd_timeout(void *arg) } ukbd_interrupt(sc); - usb_callout_reset(&sc->sc_callout, hz / 40, &ukbd_timeout, sc); + if (ukbd_any_key_pressed(sc)) { + ukbd_start_timer(sc); + } else { + sc->sc_flags &= ~UKBD_FLAG_TIMER_RUNNING; + } } static uint8_t @@ -582,6 +614,12 @@ ukbd_intr_callback(struct usb_xfer *xfer } ukbd_interrupt(sc); + + if (!(sc->sc_flags & UKBD_FLAG_TIMER_RUNNING)) { + if (ukbd_any_key_pressed(sc)) { + ukbd_start_timer(sc); + } + } } case USB_ST_SETUP: tr_setup: @@ -613,6 +651,11 @@ ukbd_set_leds_callback(struct usb_xfer * uint8_t buf[2]; struct ukbd_softc *sc = usbd_xfer_softc(xfer); +#if USB_DEBUG + if (ukbd_no_leds) + return; +#endif + switch (USB_GET_STATE(xfer)) { case USB_ST_TRANSFERRED: case USB_ST_SETUP: @@ -647,11 +690,11 @@ ukbd_set_leds_callback(struct usb_xfer * usbd_xfer_set_frames(xfer, 2); usbd_transfer_submit(xfer); } - return; + break; default: /* Error */ DPRINTFN(0, "error=%s\n", usbd_errstr(error)); - return; + break; } } @@ -745,8 +788,6 @@ ukbd_attach(device_t dev) uint16_t n; uint16_t hid_len; - mtx_assert(&Giant, MA_OWNED); - kbd_init_struct(kbd, UKBD_DRIVER_NAME, KB_OTHER, unit, 0, 0, 0); kbd->kb_data = (void *)sc; @@ -831,7 +872,7 @@ ukbd_attach(device_t dev) } /* ignore if SETIDLE fails, hence it is not crucial */ - err = usbd_req_set_idle(sc->sc_udev, &Giant, sc->sc_iface_index, 0, 0); + err = usbd_req_set_idle(sc->sc_udev, NULL, sc->sc_iface_index, 0, 0); ukbd_ioctl(kbd, KDSETLED, (caddr_t)&sc->sc_state); @@ -862,9 +903,6 @@ ukbd_attach(device_t dev) usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); - /* start the timer */ - - ukbd_timeout(sc); mtx_unlock(&Giant); return (0); /* success */ @@ -879,8 +917,6 @@ ukbd_detach(device_t dev) struct ukbd_softc *sc = device_get_softc(dev); int error; - mtx_assert(&Giant, MA_OWNED); - DPRINTF("\n"); if (sc->sc_flags & UKBD_FLAG_POLLING) { @@ -927,8 +963,6 @@ ukbd_resume(device_t dev) { struct ukbd_softc *sc = device_get_softc(dev); - mtx_assert(&Giant, MA_OWNED); - ukbd_clear_state(&sc->sc_kbd); return (0); @@ -945,7 +979,6 @@ ukbd_configure(int flags) static int ukbd__probe(int unit, void *arg, int flags) { - mtx_assert(&Giant, MA_OWNED); return (ENXIO); } @@ -953,7 +986,6 @@ ukbd__probe(int unit, void *arg, int fla static int ukbd_init(int unit, keyboard_t **kbdp, void *arg, int flags) { - mtx_assert(&Giant, MA_OWNED); return (ENXIO); } @@ -961,7 +993,6 @@ ukbd_init(int unit, keyboard_t **kbdp, v static int ukbd_test_if(keyboard_t *kbd) { - mtx_assert(&Giant, MA_OWNED); return (0); } @@ -969,7 +1000,6 @@ ukbd_test_if(keyboard_t *kbd) static int ukbd_term(keyboard_t *kbd) { - mtx_assert(&Giant, MA_OWNED); return (ENXIO); } @@ -977,7 +1007,6 @@ ukbd_term(keyboard_t *kbd) static int ukbd_intr(keyboard_t *kbd, void *arg) { - mtx_assert(&Giant, MA_OWNED); return (0); } @@ -985,7 +1014,6 @@ ukbd_intr(keyboard_t *kbd, void *arg) static int ukbd_lock(keyboard_t *kbd, int lock) { - mtx_assert(&Giant, MA_OWNED); return (1); } @@ -1004,7 +1032,6 @@ ukbd_enable(keyboard_t *kbd) mtx_unlock(&Giant); return (retval); } - mtx_assert(&Giant, MA_OWNED); KBD_ACTIVATE(kbd); return (0); } @@ -1021,7 +1048,6 @@ ukbd_disable(keyboard_t *kbd) mtx_unlock(&Giant); return (retval); } - mtx_assert(&Giant, MA_OWNED); KBD_DEACTIVATE(kbd); return (0); } @@ -1050,7 +1076,6 @@ ukbd_check(keyboard_t *kbd) if (!mtx_owned(&Giant)) return (0); } - mtx_assert(&Giant, MA_OWNED); #ifdef UKBD_EMULATE_ATSCANCODE if (sc->sc_buffered_char[0]) { @@ -1086,7 +1111,6 @@ ukbd_check_char(keyboard_t *kbd) if (!mtx_owned(&Giant)) return (0); } - mtx_assert(&Giant, MA_OWNED); if ((sc->sc_composed_char > 0) && (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { @@ -1125,7 +1149,6 @@ ukbd_read(keyboard_t *kbd, int wait) if (!mtx_owned(&Giant)) return (-1); } - mtx_assert(&Giant, MA_OWNED); #ifdef UKBD_EMULATE_ATSCANCODE if (sc->sc_buffered_char[0]) { @@ -1190,7 +1213,6 @@ ukbd_read_char(keyboard_t *kbd, int wait if (!mtx_owned(&Giant)) return (NOKEY); } - mtx_assert(&Giant, MA_OWNED); next_code: @@ -1393,7 +1415,6 @@ ukbd_ioctl(keyboard_t *kbd, u_long cmd, */ return (EINVAL); } - mtx_assert(&Giant, MA_OWNED); switch (cmd) { case KDGKBMODE: /* get keyboard mode */ @@ -1527,7 +1548,6 @@ ukbd_clear_state(keyboard_t *kbd) if (!mtx_owned(&Giant)) { return; /* XXX */ } - mtx_assert(&Giant, MA_OWNED); sc->sc_flags &= ~(UKBD_FLAG_COMPOSE | UKBD_FLAG_POLLING); sc->sc_state &= LOCK_MASK; /* preserve locking key state */ @@ -1547,7 +1567,6 @@ ukbd_clear_state(keyboard_t *kbd) static int ukbd_get_state(keyboard_t *kbd, void *buf, size_t len) { - mtx_assert(&Giant, MA_OWNED); return (len == 0) ? 1 : -1; } @@ -1555,7 +1574,6 @@ ukbd_get_state(keyboard_t *kbd, void *bu static int ukbd_set_state(keyboard_t *kbd, void *buf, size_t len) { - mtx_assert(&Giant, MA_OWNED); return (EINVAL); } @@ -1572,7 +1590,6 @@ ukbd_poll(keyboard_t *kbd, int on) mtx_unlock(&Giant); return (retval); } - mtx_assert(&Giant, MA_OWNED); if (on) { sc->sc_flags |= UKBD_FLAG_POLLING; Modified: stable/8/sys/dev/usb/usb_dev.c ============================================================================== --- stable/8/sys/dev/usb/usb_dev.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_dev.c Wed Sep 2 02:12:07 2009 (r196746) @@ -217,7 +217,7 @@ usb_ref_device(struct usb_cdev_privdata * We need to grab the sx-lock before grabbing the * FIFO refs to avoid deadlock at detach! */ - sx_xlock(cpd->udev->default_sx + 1); + usbd_enum_lock(cpd->udev); mtx_lock(&usb_ref_lock); @@ -275,14 +275,12 @@ usb_ref_device(struct usb_cdev_privdata } mtx_unlock(&usb_ref_lock); - if (crd->is_uref) { - mtx_lock(&Giant); /* XXX */ - } return (0); error: if (crd->is_uref) { - sx_unlock(cpd->udev->default_sx + 1); + usbd_enum_unlock(cpd->udev); + if (--(cpd->udev->refcount) == 0) { cv_signal(cpd->udev->default_cv + 1); } @@ -334,10 +332,9 @@ usb_unref_device(struct usb_cdev_privdat DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref); - if (crd->is_uref) { - mtx_unlock(&Giant); /* XXX */ - sx_unlock(cpd->udev->default_sx + 1); - } + if (crd->is_uref) + usbd_enum_unlock(cpd->udev); + mtx_lock(&usb_ref_lock); if (crd->is_read) { if (--(crd->rxfifo->refcount) == 0) { @@ -1042,9 +1039,9 @@ usb_ioctl(struct cdev *dev, u_long cmd, * reference if we need it! */ err = usb_ref_device(cpd, &refs, 0 /* no uref */ ); - if (err) { + if (err) return (ENXIO); - } + fflags = cpd->fflags; f = NULL; /* set default value */ Modified: stable/8/sys/dev/usb/usb_device.c ============================================================================== --- stable/8/sys/dev/usb/usb_device.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_device.c Wed Sep 2 02:12:07 2009 (r196746) @@ -402,11 +402,11 @@ usb_unconfigure(struct usb_device *udev, uint8_t do_unlock; /* automatic locking */ - if (sx_xlocked(udev->default_sx + 1)) { + if (usbd_enum_is_locked(udev)) { do_unlock = 0; } else { do_unlock = 1; - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); } /* detach all interface drivers */ @@ -442,9 +442,8 @@ usb_unconfigure(struct usb_device *udev, udev->curr_config_no = USB_UNCONFIG_NO; udev->curr_config_index = USB_UNCONFIG_INDEX; - if (do_unlock) { - sx_unlock(udev->default_sx + 1); - } + if (do_unlock) + usbd_enum_unlock(udev); } /*------------------------------------------------------------------------* @@ -472,11 +471,11 @@ usbd_set_config_index(struct usb_device DPRINTFN(6, "udev=%p index=%d\n", udev, index); /* automatic locking */ - if (sx_xlocked(udev->default_sx + 1)) { + if (usbd_enum_is_locked(udev)) { do_unlock = 0; } else { do_unlock = 1; - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); } usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV); @@ -585,9 +584,8 @@ done: if (err) { usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV); } - if (do_unlock) { - sx_unlock(udev->default_sx + 1); - } + if (do_unlock) + usbd_enum_unlock(udev); return (err); } @@ -823,11 +821,11 @@ usbd_set_alt_interface_index(struct usb_ uint8_t do_unlock; /* automatic locking */ - if (sx_xlocked(udev->default_sx + 1)) { + if (usbd_enum_is_locked(udev)) { do_unlock = 0; } else { do_unlock = 1; - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); } if (iface == NULL) { err = USB_ERR_INVAL; @@ -863,9 +861,9 @@ usbd_set_alt_interface_index(struct usb_ iface->idesc->bAlternateSetting); done: - if (do_unlock) { - sx_unlock(udev->default_sx + 1); - } + if (do_unlock) + usbd_enum_unlock(udev); + return (err); } @@ -1230,11 +1228,11 @@ usb_probe_and_attach(struct usb_device * return (USB_ERR_INVAL); } /* automatic locking */ - if (sx_xlocked(udev->default_sx + 1)) { + if (usbd_enum_is_locked(udev)) { do_unlock = 0; } else { do_unlock = 1; - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); } if (udev->curr_config_index == USB_UNCONFIG_INDEX) { @@ -1315,9 +1313,9 @@ usb_probe_and_attach(struct usb_device * } } done: - if (do_unlock) { - sx_unlock(udev->default_sx + 1); - } + if (do_unlock) + usbd_enum_unlock(udev); + return (0); } @@ -1779,7 +1777,8 @@ repeat_set_config: } } else if (usb_test_huawei_autoinst_p(udev, &uaa) == 0) { DPRINTFN(0, "Found Huawei auto-install disk!\n"); - err = USB_ERR_STALLED; /* fake an error */ + /* leave device unconfigured */ + usb_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV); } } else { err = 0; /* set success */ @@ -1902,15 +1901,18 @@ static void usb_cdev_free(struct usb_device *udev) { struct usb_fs_privdata* pd; + struct cdev* pcdev; DPRINTFN(2, "Freeing device nodes\n"); while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) { KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt")); - destroy_dev_sched_cb(pd->cdev, usb_cdev_cleanup, pd); + pcdev = pd->cdev; pd->cdev = NULL; LIST_REMOVE(pd, pd_next); + if (pcdev != NULL) + destroy_dev_sched_cb(pcdev, usb_cdev_cleanup, pd); } } @@ -2448,3 +2450,37 @@ usbd_device_attached(struct usb_device * { return (udev->state > USB_STATE_DETACHED); } + +/* The following function locks enumerating the given USB device. */ + +void +usbd_enum_lock(struct usb_device *udev) +{ + sx_xlock(udev->default_sx + 1); + /* + * NEWBUS LOCK NOTE: We should check if any parent SX locks + * are locked before locking Giant. Else the lock can be + * locked multiple times. + */ + mtx_lock(&Giant); +} + +/* The following function unlocks enumerating the given USB device. */ + +void +usbd_enum_unlock(struct usb_device *udev) +{ + mtx_unlock(&Giant); + sx_xunlock(udev->default_sx + 1); +} + +/* + * The following function checks the enumerating lock for the given + * USB device. + */ + +uint8_t +usbd_enum_is_locked(struct usb_device *udev) +{ + return (sx_xlocked(udev->default_sx + 1)); +} Modified: stable/8/sys/dev/usb/usb_device.h ============================================================================== --- stable/8/sys/dev/usb/usb_device.h Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_device.h Wed Sep 2 02:12:07 2009 (r196746) @@ -211,5 +211,8 @@ uint8_t usb_peer_can_wakeup(struct usb_d struct usb_endpoint *usb_endpoint_foreach(struct usb_device *udev, struct usb_endpoint *ep); void usb_set_device_state(struct usb_device *udev, enum usb_dev_state state); +void usbd_enum_lock(struct usb_device *); +void usbd_enum_unlock(struct usb_device *); +uint8_t usbd_enum_is_locked(struct usb_device *); #endif /* _USB_DEVICE_H_ */ Modified: stable/8/sys/dev/usb/usb_handle_request.c ============================================================================== --- stable/8/sys/dev/usb/usb_handle_request.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_handle_request.c Wed Sep 2 02:12:07 2009 (r196746) @@ -152,8 +152,8 @@ usb_handle_set_config(struct usb_xfer *x * attach: */ USB_XFER_UNLOCK(xfer); - mtx_lock(&Giant); /* XXX */ - sx_xlock(udev->default_sx + 1); + + usbd_enum_lock(udev); if (conf_no == USB_UNCONFIG_NO) { conf_no = USB_UNCONFIG_INDEX; @@ -176,8 +176,7 @@ usb_handle_set_config(struct usb_xfer *x goto done; } done: - mtx_unlock(&Giant); /* XXX */ - sx_unlock(udev->default_sx + 1); + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (err); } @@ -190,19 +189,19 @@ usb_check_alt_setting(struct usb_device usb_error_t err = 0; /* automatic locking */ - if (sx_xlocked(udev->default_sx + 1)) { + if (usbd_enum_is_locked(udev)) { do_unlock = 0; } else { do_unlock = 1; - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); } if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc)) err = USB_ERR_INVAL; - if (do_unlock) { - sx_unlock(udev->default_sx + 1); - } + if (do_unlock) + usbd_enum_unlock(udev); + return (err); } @@ -236,8 +235,8 @@ usb_handle_iface_request(struct usb_xfer * attach: */ USB_XFER_UNLOCK(xfer); - mtx_lock(&Giant); /* XXX */ - sx_xlock(udev->default_sx + 1); + + usbd_enum_lock(udev); error = ENXIO; @@ -353,20 +352,17 @@ tr_repeat: goto tr_stalled; } tr_valid: - mtx_unlock(&Giant); - sx_unlock(udev->default_sx + 1); + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (0); tr_short: - mtx_unlock(&Giant); - sx_unlock(udev->default_sx + 1); + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (USB_ERR_SHORT_XFER); tr_stalled: - mtx_unlock(&Giant); - sx_unlock(udev->default_sx + 1); + usbd_enum_unlock(udev); USB_XFER_LOCK(xfer); return (USB_ERR_STALLED); } Modified: stable/8/sys/dev/usb/usb_hub.c ============================================================================== --- stable/8/sys/dev/usb/usb_hub.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_hub.c Wed Sep 2 02:12:07 2009 (r196746) @@ -96,6 +96,7 @@ struct uhub_current_state { struct uhub_softc { struct uhub_current_state sc_st;/* current state */ device_t sc_dev; /* base device */ + struct mtx sc_mtx; /* our mutex */ struct usb_device *sc_udev; /* USB device */ struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */ uint8_t sc_flags; @@ -428,7 +429,6 @@ repeat: mode = USB_MODE_HOST; /* need to create a new child */ - child = usb_alloc_device(sc->sc_dev, udev->bus, udev, udev->depth + 1, portno - 1, portno, speed, mode); if (child == NULL) { @@ -691,6 +691,8 @@ uhub_attach(device_t dev) sc->sc_udev = udev; sc->sc_dev = dev; + mtx_init(&sc->sc_mtx, "USB HUB mutex", NULL, MTX_DEF); + snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", device_get_nameunit(dev)); @@ -774,7 +776,7 @@ uhub_attach(device_t dev) } else { /* normal HUB */ err = usbd_transfer_setup(udev, &iface_index, sc->sc_xfer, - uhub_config, UHUB_N_TRANSFER, sc, &Giant); + uhub_config, UHUB_N_TRANSFER, sc, &sc->sc_mtx); } if (err) { DPRINTFN(0, "cannot setup interrupt transfer, " @@ -850,9 +852,9 @@ uhub_attach(device_t dev) /* Start the interrupt endpoint, if any */ if (sc->sc_xfer[0] != NULL) { - USB_XFER_LOCK(sc->sc_xfer[0]); + mtx_lock(&sc->sc_mtx); usbd_transfer_start(sc->sc_xfer[0]); - USB_XFER_UNLOCK(sc->sc_xfer[0]); + mtx_unlock(&sc->sc_mtx); } /* Enable automatic power save on all USB HUBs */ @@ -868,6 +870,9 @@ error: free(udev->hub, M_USBDEV); udev->hub = NULL; } + + mtx_destroy(&sc->sc_mtx); + return (ENXIO); } @@ -908,6 +913,9 @@ uhub_detach(device_t dev) free(hub, M_USBDEV); sc->sc_udev->hub = NULL; + + mtx_destroy(&sc->sc_mtx); + return (0); } @@ -1775,10 +1783,13 @@ usb_dev_resume_peer(struct usb_device *u /* always update hardware power! */ (bus->methods->set_hw_power) (bus); } - sx_xlock(udev->default_sx + 1); + + usbd_enum_lock(udev); + /* notify all sub-devices about resume */ err = usb_suspend_resume(udev, 0); - sx_unlock(udev->default_sx + 1); + + usbd_enum_unlock(udev); /* check if peer has wakeup capability */ if (usb_peer_can_wakeup(udev)) { @@ -1844,10 +1855,12 @@ repeat: } } - sx_xlock(udev->default_sx + 1); + usbd_enum_lock(udev); + /* notify all sub-devices about suspend */ err = usb_suspend_resume(udev, 1); - sx_unlock(udev->default_sx + 1); + + usbd_enum_unlock(udev); if (usb_peer_can_wakeup(udev)) { /* allow device to do remote wakeup */ Modified: stable/8/sys/dev/usb/usb_process.c ============================================================================== --- stable/8/sys/dev/usb/usb_process.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_process.c Wed Sep 2 02:12:07 2009 (r196746) @@ -457,3 +457,29 @@ usb_proc_drain(struct usb_process *up) } mtx_unlock(up->up_mtx); } + +/*------------------------------------------------------------------------* + * usb_proc_rewakeup + * + * This function is called to re-wakeup the the given USB + * process. This usually happens after that the USB system has been in + * polling mode, like during a panic. This function must be called + * having "up->up_mtx" locked. + *------------------------------------------------------------------------*/ +void +usb_proc_rewakeup(struct usb_process *up) +{ + /* check if not initialised */ + if (up->up_mtx == NULL) + return; + /* check if gone */ + if (up->up_gone) + return; + + mtx_assert(up->up_mtx, MA_OWNED); + + if (up->up_msleep == 0) { + /* re-wakeup */ + cv_signal(&up->up_cv); + } +} Modified: stable/8/sys/dev/usb/usb_process.h ============================================================================== --- stable/8/sys/dev/usb/usb_process.h Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_process.h Wed Sep 2 02:12:07 2009 (r196746) @@ -75,5 +75,6 @@ void usb_proc_drain(struct usb_process * void usb_proc_mwait(struct usb_process *up, void *pm0, void *pm1); void usb_proc_free(struct usb_process *up); void *usb_proc_msignal(struct usb_process *up, void *pm0, void *pm1); +void usb_proc_rewakeup(struct usb_process *up); #endif /* _USB_PROCESS_H_ */ Modified: stable/8/sys/dev/usb/usb_transfer.c ============================================================================== --- stable/8/sys/dev/usb/usb_transfer.c Wed Sep 2 00:39:59 2009 (r196745) +++ stable/8/sys/dev/usb/usb_transfer.c Wed Sep 2 02:12:07 2009 (r196746) @@ -2907,13 +2907,9 @@ usbd_transfer_poll(struct usb_xfer **ppx } /* Make sure cv_signal() and cv_broadcast() is not called */ - udev->bus->control_xfer_proc.up_dsleep = 0; udev->bus->control_xfer_proc.up_msleep = 0; - udev->bus->explore_proc.up_dsleep = 0; udev->bus->explore_proc.up_msleep = 0; - udev->bus->giant_callback_proc.up_dsleep = 0; udev->bus->giant_callback_proc.up_msleep = 0; - udev->bus->non_giant_callback_proc.up_dsleep = 0; udev->bus->non_giant_callback_proc.up_msleep = 0; /* poll USB hardware */