From owner-svn-src-head@FreeBSD.ORG Thu Jul 30 00:14:35 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 582571065676; Thu, 30 Jul 2009 00:14:35 +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 44D158FC20; Thu, 30 Jul 2009 00:14:35 +0000 (UTC) (envelope-from alfred@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6U0EZLj086353; Thu, 30 Jul 2009 00:14:35 GMT (envelope-from alfred@svn.freebsd.org) Received: (from alfred@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6U0EZ77086341; Thu, 30 Jul 2009 00:14:35 GMT (envelope-from alfred@svn.freebsd.org) Message-Id: <200907300014.n6U0EZ77086341@svn.freebsd.org> From: Alfred Perlstein Date: Thu, 30 Jul 2009 00:14:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195960 - in head/sys/dev/usb: . controller input X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Jul 2009 00:14:35 -0000 Author: alfred Date: Thu Jul 30 00:14:34 2009 New Revision: 195960 URL: http://svn.freebsd.org/changeset/base/195960 Log: USB CORE: - Add minimum polling support to drive UMASS and UKBD in case of panic. - Add extra check to ukbd probe to fix problem about mouse devices attaching like keyboards. - P4 ID: 166148 Submitted by: hps Approved by: re Modified: head/sys/dev/usb/controller/at91dci.c head/sys/dev/usb/controller/atmegadci.c head/sys/dev/usb/controller/avr32dci.c head/sys/dev/usb/controller/ehci.c head/sys/dev/usb/controller/musb_otg.c head/sys/dev/usb/controller/ohci.c head/sys/dev/usb/controller/uhci.c head/sys/dev/usb/controller/uss820dci.c head/sys/dev/usb/input/ukbd.c head/sys/dev/usb/usb_controller.h head/sys/dev/usb/usb_transfer.c Modified: head/sys/dev/usb/controller/at91dci.c ============================================================================== --- head/sys/dev/usb/controller/at91dci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/at91dci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2326,4 +2326,5 @@ struct usb_bus_methods at91dci_bus_metho .set_stall = &at91dci_set_stall, .clear_stall = &at91dci_clear_stall, .roothub_exec = &at91dci_roothub_exec, + .xfer_poll = &at91dci_do_poll, }; Modified: head/sys/dev/usb/controller/atmegadci.c ============================================================================== --- head/sys/dev/usb/controller/atmegadci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/atmegadci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2143,4 +2143,5 @@ struct usb_bus_methods atmegadci_bus_met .set_stall = &atmegadci_set_stall, .clear_stall = &atmegadci_clear_stall, .roothub_exec = &atmegadci_roothub_exec, + .xfer_poll = &atmegadci_do_poll, }; Modified: head/sys/dev/usb/controller/avr32dci.c ============================================================================== --- head/sys/dev/usb/controller/avr32dci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/avr32dci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2081,4 +2081,5 @@ struct usb_bus_methods avr32dci_bus_meth .set_stall = &avr32dci_set_stall, .clear_stall = &avr32dci_clear_stall, .roothub_exec = &avr32dci_roothub_exec, + .xfer_poll = &avr32dci_do_poll, }; Modified: head/sys/dev/usb/controller/ehci.c ============================================================================== --- head/sys/dev/usb/controller/ehci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/ehci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -3828,4 +3828,5 @@ struct usb_bus_methods ehci_bus_methods .device_suspend = ehci_device_suspend, .set_hw_power = ehci_set_hw_power, .roothub_exec = ehci_roothub_exec, + .xfer_poll = ehci_do_poll, }; Modified: head/sys/dev/usb/controller/musb_otg.c ============================================================================== --- head/sys/dev/usb/controller/musb_otg.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/musb_otg.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2736,4 +2736,5 @@ struct usb_bus_methods musbotg_bus_metho .set_stall = &musbotg_set_stall, .clear_stall = &musbotg_clear_stall, .roothub_exec = &musbotg_roothub_exec, + .xfer_poll = &musbotg_do_poll, }; Modified: head/sys/dev/usb/controller/ohci.c ============================================================================== --- head/sys/dev/usb/controller/ohci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/ohci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2756,4 +2756,5 @@ struct usb_bus_methods ohci_bus_methods .device_suspend = ohci_device_suspend, .set_hw_power = ohci_set_hw_power, .roothub_exec = ohci_roothub_exec, + .xfer_poll = ohci_do_poll, }; Modified: head/sys/dev/usb/controller/uhci.c ============================================================================== --- head/sys/dev/usb/controller/uhci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/uhci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -3251,4 +3251,5 @@ struct usb_bus_methods uhci_bus_methods .device_suspend = uhci_device_suspend, .set_hw_power = uhci_set_hw_power, .roothub_exec = uhci_roothub_exec, + .xfer_poll = uhci_do_poll, }; Modified: head/sys/dev/usb/controller/uss820dci.c ============================================================================== --- head/sys/dev/usb/controller/uss820dci.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/controller/uss820dci.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2360,4 +2360,5 @@ struct usb_bus_methods uss820dci_bus_met .set_stall = &uss820dci_set_stall, .clear_stall = &uss820dci_clear_stall, .roothub_exec = &uss820dci_roothub_exec, + .xfer_poll = &uss820dci_do_poll, }; Modified: head/sys/dev/usb/input/ukbd.c ============================================================================== --- head/sys/dev/usb/input/ukbd.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/input/ukbd.c Thu Jul 30 00:14:34 2009 (r195960) @@ -299,6 +299,28 @@ ukbd_put_key(struct ukbd_softc *sc, uint } } +static void +ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait) +{ + DPRINTFN(2, "polling\n"); + + while (sc->sc_inputs == 0) { + + usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); + + DELAY(1000); /* delay 1 ms */ + + sc->sc_time_ms++; + + /* support repetition of keys: */ + + ukbd_interrupt(sc); + + if (!wait) + break; + } +} + static int32_t ukbd_get_key(struct ukbd_softc *sc, uint8_t wait) { @@ -311,24 +333,7 @@ ukbd_get_key(struct ukbd_softc *sc, uint usbd_transfer_start(sc->sc_xfer[UKBD_INTR_DT]); } if (sc->sc_flags & UKBD_FLAG_POLLING) { - DPRINTFN(2, "polling\n"); - - while (sc->sc_inputs == 0) { - - usbd_transfer_poll(sc->sc_xfer, UKBD_N_TRANSFER); - - DELAY(1000); /* delay 1 ms */ - - sc->sc_time_ms++; - - /* support repetition of keys: */ - - ukbd_interrupt(sc); - - if (!wait) { - break; - } - } + ukbd_do_poll(sc, wait); } if (sc->sc_inputs == 0) { c = -1; @@ -706,7 +711,15 @@ ukbd_probe(device_t dev) if (error) return (ENXIO); + /* + * NOTE: we currently don't support USB mouse and USB keyboard + * on the same USB endpoint. + */ if (hid_is_collection(d_ptr, d_len, + HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_MOUSE))) { + /* most likely a mouse */ + error = ENXIO; + } else if (hid_is_collection(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_KEYBOARD))) { if (usb_test_quirk(uaa, UQ_KBD_IGNORE)) error = ENXIO; @@ -983,6 +996,14 @@ ukbd_lock(keyboard_t *kbd, int lock) static int ukbd_enable(keyboard_t *kbd) { + if (!mtx_owned(&Giant)) { + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_enable(kbd); + mtx_unlock(&Giant); + return (retval); + } mtx_assert(&Giant, MA_OWNED); KBD_ACTIVATE(kbd); return (0); @@ -992,6 +1013,14 @@ ukbd_enable(keyboard_t *kbd) static int ukbd_disable(keyboard_t *kbd) { + if (!mtx_owned(&Giant)) { + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_disable(kbd); + mtx_unlock(&Giant); + return (retval); + } mtx_assert(&Giant, MA_OWNED); KBD_DEACTIVATE(kbd); return (0); @@ -1003,14 +1032,26 @@ ukbd_check(keyboard_t *kbd) { struct ukbd_softc *sc = kbd->kb_data; - if (!mtx_owned(&Giant)) { - return (0); /* XXX */ + if (!KBD_IS_ACTIVE(kbd)) + return (0); + + if (sc->sc_flags & UKBD_FLAG_POLLING) { + if (!mtx_owned(&Giant)) { + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_check(kbd); + mtx_unlock(&Giant); + return (retval); + } + ukbd_do_poll(sc, 0); + } else { + /* XXX the keyboard layer requires Giant */ + if (!mtx_owned(&Giant)) + return (0); } mtx_assert(&Giant, MA_OWNED); - if (!KBD_IS_ACTIVE(kbd)) { - return (0); - } #ifdef UKBD_EMULATE_ATSCANCODE if (sc->sc_buffered_char[0]) { return (1); @@ -1028,14 +1069,25 @@ ukbd_check_char(keyboard_t *kbd) { struct ukbd_softc *sc = kbd->kb_data; - if (!mtx_owned(&Giant)) { - return (0); /* XXX */ + if (!KBD_IS_ACTIVE(kbd)) + return (0); + + if (sc->sc_flags & UKBD_FLAG_POLLING) { + if (!mtx_owned(&Giant)) { + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_check_char(kbd); + mtx_unlock(&Giant); + return (retval); + } + } else { + /* XXX the keyboard layer requires Giant */ + if (!mtx_owned(&Giant)) + return (0); } mtx_assert(&Giant, MA_OWNED); - if (!KBD_IS_ACTIVE(kbd)) { - return (0); - } if ((sc->sc_composed_char > 0) && (!(sc->sc_flags & UKBD_FLAG_COMPOSE))) { return (1); @@ -1056,9 +1108,22 @@ ukbd_read(keyboard_t *kbd, int wait) uint32_t scancode; #endif + if (!KBD_IS_ACTIVE(kbd)) + return (-1); - if (!mtx_owned(&Giant)) { - return -1; /* XXX */ + if (sc->sc_flags & UKBD_FLAG_POLLING) { + if (!mtx_owned(&Giant)) { + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_read(kbd, wait); + mtx_unlock(&Giant); + return (retval); + } + } else { + /* XXX the keyboard layer requires Giant */ + if (!mtx_owned(&Giant)) + return (-1); } mtx_assert(&Giant, MA_OWNED); @@ -1077,9 +1142,9 @@ ukbd_read(keyboard_t *kbd, int wait) /* XXX */ usbcode = ukbd_get_key(sc, (wait == FALSE) ? 0 : 1); - if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) { - return -1; - } + if (!KBD_IS_ACTIVE(kbd) || (usbcode == -1)) + return (-1); + ++(kbd->kb_count); #ifdef UKBD_EMULATE_ATSCANCODE @@ -1107,8 +1172,23 @@ ukbd_read_char(keyboard_t *kbd, int wait uint32_t scancode; #endif - if (!mtx_owned(&Giant)) { - return (NOKEY); /* XXX */ + + if (!KBD_IS_ACTIVE(kbd)) + return (NOKEY); + + if (sc->sc_flags & UKBD_FLAG_POLLING) { + if (!mtx_owned(&Giant)) { + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_read_char(kbd, wait); + mtx_unlock(&Giant); + return (retval); + } + } else { + /* XXX the keyboard layer requires Giant */ + if (!mtx_owned(&Giant)) + return (NOKEY); } mtx_assert(&Giant, MA_OWNED); @@ -1485,7 +1565,12 @@ ukbd_poll(keyboard_t *kbd, int on) struct ukbd_softc *sc = kbd->kb_data; if (!mtx_owned(&Giant)) { - return (0); /* XXX */ + /* XXX cludge */ + int retval; + mtx_lock(&Giant); + retval = ukbd_poll(kbd, on); + mtx_unlock(&Giant); + return (retval); } mtx_assert(&Giant, MA_OWNED); Modified: head/sys/dev/usb/usb_controller.h ============================================================================== --- head/sys/dev/usb/usb_controller.h Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/usb_controller.h Thu Jul 30 00:14:34 2009 (r195960) @@ -99,6 +99,9 @@ struct usb_bus_methods { void (*set_stall) (struct usb_device *udev, struct usb_xfer *xfer, struct usb_endpoint *ep, uint8_t *did_stall); void (*clear_stall) (struct usb_device *udev, struct usb_endpoint *ep); + /* Optional transfer polling support */ + + void (*xfer_poll) (struct usb_bus *); }; /* Modified: head/sys/dev/usb/usb_transfer.c ============================================================================== --- head/sys/dev/usb/usb_transfer.c Thu Jul 30 00:13:09 2009 (r195959) +++ head/sys/dev/usb/usb_transfer.c Thu Jul 30 00:14:34 2009 (r195960) @@ -2853,15 +2853,99 @@ usbd_clear_stall_callback(struct usb_xfe return (1); /* Clear Stall Finished */ } +/*------------------------------------------------------------------------* + * usbd_transfer_poll + * + * The following function gets called from the USB keyboard driver and + * UMASS when the system has paniced. + * + * NOTE: It is currently not possible to resume normal operation on + * the USB controller which has been polled, due to clearing of the + * "up_dsleep" and "up_msleep" flags. + *------------------------------------------------------------------------*/ void usbd_transfer_poll(struct usb_xfer **ppxfer, uint16_t max) { - static uint8_t once = 0; - /* polling is currently not supported */ - if (!once) { - once = 1; - printf("usbd_transfer_poll: USB polling is " - "not supported!\n"); + struct usb_xfer *xfer; + struct usb_xfer_root *xroot; + struct usb_device *udev; + struct usb_proc_msg *pm; + uint16_t n; + uint16_t drop_bus; + uint16_t drop_xfer; + + for (n = 0; n != max; n++) { + /* Extra checks to avoid panic */ + xfer = ppxfer[n]; + if (xfer == NULL) + continue; /* no USB transfer */ + xroot = xfer->xroot; + if (xroot == NULL) + continue; /* no USB root */ + udev = xroot->udev; + if (udev == NULL) + continue; /* no USB device */ + if (udev->bus == NULL) + continue; /* no BUS structure */ + if (udev->bus->methods == NULL) + continue; /* no BUS methods */ + if (udev->bus->methods->xfer_poll == NULL) + continue; /* no poll method */ + + /* make sure that the BUS mutex is not locked */ + drop_bus = 0; + while (mtx_owned(&xroot->udev->bus->bus_mtx)) { + mtx_unlock(&xroot->udev->bus->bus_mtx); + drop_bus++; + } + + /* make sure that the transfer mutex is not locked */ + drop_xfer = 0; + while (mtx_owned(xroot->xfer_mtx)) { + mtx_unlock(xroot->xfer_mtx); + drop_xfer++; + } + + /* 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 */ + (udev->bus->methods->xfer_poll) (udev->bus); + + USB_BUS_LOCK(xroot->bus); + + /* check for clear stall */ + if (udev->default_xfer[1] != NULL) { + + /* poll clear stall start */ + pm = &udev->cs_msg[0].hdr; + (pm->pm_callback) (pm); + /* poll clear stall done thread */ + pm = &udev->default_xfer[1]-> + xroot->done_m[0].hdr; + (pm->pm_callback) (pm); + } + + /* poll done thread */ + pm = &xroot->done_m[0].hdr; + (pm->pm_callback) (pm); + + USB_BUS_UNLOCK(xroot->bus); + + /* restore transfer mutex */ + while (drop_xfer--) + mtx_lock(xroot->xfer_mtx); + + /* restore BUS mutex */ + while (drop_bus--) + mtx_lock(&xroot->udev->bus->bus_mtx); } }