From owner-svn-src-projects@FreeBSD.ORG Mon Oct 12 07:29:51 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8BC6B1065670; Mon, 12 Oct 2009 07:29:51 +0000 (UTC) (envelope-from lstewart@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 788EE8FC0A; Mon, 12 Oct 2009 07:29:51 +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 n9C7TpjG049978; Mon, 12 Oct 2009 07:29:51 GMT (envelope-from lstewart@svn.freebsd.org) Received: (from lstewart@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n9C7TpNv049956; Mon, 12 Oct 2009 07:29:51 GMT (envelope-from lstewart@svn.freebsd.org) Message-Id: <200910120729.n9C7TpNv049956@svn.freebsd.org> From: Lawrence Stewart Date: Mon, 12 Oct 2009 07:29:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197974 - in projects/tcp_ffcaia2008_8.x/sys: dev/usb dev/usb/controller dev/usb/serial netinet/ipfw X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Oct 2009 07:29:51 -0000 Author: lstewart Date: Mon Oct 12 07:29:50 2009 New Revision: 197974 URL: http://svn.freebsd.org/changeset/base/197974 Log: Fix mismerged files. Sponsored by: FreeBSD Foundation Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/at91dci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/atmegadci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci_pci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/musb_otg.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci_pci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci_pci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/usb_controller.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uss820dci.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/u3g.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/ulpt.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_busdma.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.h projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_controller.h projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.h projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_device.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_device.h projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_handle_request.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_hid.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_hub.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_parse.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_process.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_process.h projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_request.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_transfer.c projects/tcp_ffcaia2008_8.x/sys/dev/usb/usbdevs projects/tcp_ffcaia2008_8.x/sys/netinet/ipfw/ip_fw2.c projects/tcp_ffcaia2008_8.x/sys/netinet/ipfw/ip_fw_nat.c projects/tcp_ffcaia2008_8.x/sys/netinet/ipfw/ip_fw_pfil.c Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/at91dci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/at91dci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/at91dci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/atmegadci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/atmegadci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/atmegadci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -131,6 +131,7 @@ struct ehci_std_temp { uint8_t auto_data_toggle; uint8_t setup_alt_next; uint8_t last_frame; + uint8_t can_use_next; }; void @@ -1207,11 +1208,6 @@ ehci_non_isoc_done_sub(struct usb_xfer * xfer->td_transfer_cache = td; - /* update data toggle */ - - xfer->endpoint->toggle_next = - (status & EHCI_QTD_TOGGLE_MASK) ? 1 : 0; - #if USB_DEBUG if (status & EHCI_QTD_STATERRS) { DPRINTFN(11, "error, addr=%d, endpt=0x%02x, frame=0x%02x" @@ -1235,6 +1231,9 @@ ehci_non_isoc_done_sub(struct usb_xfer * static void ehci_non_isoc_done(struct usb_xfer *xfer) { + ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus); + ehci_qh_t *qh; + uint32_t status; usb_error_t err = 0; DPRINTFN(13, "xfer=%p endpoint=%p transfer done\n", @@ -1248,6 +1247,17 @@ ehci_non_isoc_done(struct usb_xfer *xfer } #endif + /* extract data toggle directly from the QH's overlay area */ + + qh = xfer->qh_start[xfer->flags_int.curr_dma_set]; + + usb_pc_cpu_invalidate(qh->page_cache); + + status = hc32toh(sc, qh->qh_qtd.qtd_status); + + xfer->endpoint->toggle_next = + (status & EHCI_QTD_TOGGLE_MASK) ? 1 : 0; + /* reset scanner */ xfer->td_transfer_cache = xfer->td_transfer_first; @@ -1348,6 +1358,7 @@ ehci_check_transfer(struct usb_xfer *xfe } } else { ehci_qtd_t *td; + ehci_qh_t *qh; /* non-isochronous transfer */ @@ -1357,16 +1368,35 @@ ehci_check_transfer(struct usb_xfer *xfe */ td = xfer->td_transfer_cache; + qh = xfer->qh_start[xfer->flags_int.curr_dma_set]; + + usb_pc_cpu_invalidate(qh->page_cache); + + status = hc32toh(sc, qh->qh_qtd.qtd_status); + if (status & EHCI_QTD_ACTIVE) { + /* transfer is pending */ + goto done; + } + while (1) { usb_pc_cpu_invalidate(td->page_cache); status = hc32toh(sc, td->qtd_status); /* - * if there is an active TD the transfer isn't done + * Check if there is an active TD which + * indicates that the transfer isn't done. */ if (status & EHCI_QTD_ACTIVE) { /* update cache */ - xfer->td_transfer_cache = td; + if (xfer->td_transfer_cache != td) { + xfer->td_transfer_cache = td; + if (qh->qh_qtd.qtd_next & + htohc32(sc, EHCI_LINK_TERMINATE)) { + /* XXX - manually advance to next frame */ + qh->qh_qtd.qtd_next = td->qtd_self; + usb_pc_cpu_flush(td->page_cache); + } + } goto done; } /* @@ -1545,7 +1575,6 @@ ehci_setup_standard_chain_sub(struct ehc ehci_qtd_t *td; ehci_qtd_t *td_next; ehci_qtd_t *td_alt_next; - uint32_t qtd_altnext; uint32_t buf_offset; uint32_t average; uint32_t len_old; @@ -1554,7 +1583,6 @@ ehci_setup_standard_chain_sub(struct ehc uint8_t precompute; terminate = htohc32(temp->sc, EHCI_LINK_TERMINATE); - qtd_altnext = terminate; td_alt_next = NULL; buf_offset = 0; shortpkt_old = temp->shortpkt; @@ -1612,7 +1640,8 @@ restart: td->qtd_status = temp->qtd_status | - htohc32(temp->sc, EHCI_QTD_SET_BYTES(average)); + htohc32(temp->sc, EHCI_QTD_IOC | + EHCI_QTD_SET_BYTES(average)); if (average == 0) { @@ -1687,11 +1716,23 @@ restart: td->qtd_buffer_hi[x] = 0; } - if (td_next) { - /* link the current TD with the next one */ - td->qtd_next = td_next->qtd_self; + if (temp->can_use_next) { + if (td_next) { + /* link the current TD with the next one */ + td->qtd_next = td_next->qtd_self; + } + } else { + /* + * BUG WARNING: The EHCI HW can use the + * qtd_next field instead of qtd_altnext when + * a short packet is received! We work this + * around in software by not queueing more + * than one job/TD at a time! + */ + td->qtd_next = terminate; } - td->qtd_altnext = qtd_altnext; + + td->qtd_altnext = terminate; td->alt_next = td_alt_next; usb_pc_cpu_flush(td->page_cache); @@ -1703,15 +1744,9 @@ restart: /* setup alt next pointer, if any */ if (temp->last_frame) { td_alt_next = NULL; - qtd_altnext = terminate; } else { /* we use this field internally */ td_alt_next = td_next; - if (temp->setup_alt_next) { - qtd_altnext = td_next->qtd_self; - } else { - qtd_altnext = terminate; - } } /* restore */ @@ -1756,6 +1791,8 @@ ehci_setup_standard_chain(struct usb_xfe temp.qtd_status = 0; temp.last_frame = 0; temp.setup_alt_next = xfer->flags_int.short_frames_ok; + temp.can_use_next = (xfer->flags_int.control_xfr || + (UE_GET_DIR(xfer->endpointno) == UE_DIR_OUT)); if (xfer->flags_int.control_xfr) { if (xfer->endpoint->toggle_next) { @@ -1889,7 +1926,6 @@ ehci_setup_standard_chain(struct usb_xfe /* the last TD terminates the transfer: */ td->qtd_next = htohc32(temp.sc, EHCI_LINK_TERMINATE); td->qtd_altnext = htohc32(temp.sc, EHCI_LINK_TERMINATE); - td->qtd_status |= htohc32(temp.sc, EHCI_QTD_IOC); usb_pc_cpu_flush(td->page_cache); @@ -3828,4 +3864,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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci_pci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci_pci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ehci_pci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -206,6 +206,8 @@ ehci_pci_match(device_t self) return "NVIDIA nForce3 250 USB 2.0 controller"; case 0x005b10de: return "NVIDIA nForce4 USB 2.0 controller"; + case 0x03f210de: + return "NVIDIA nForce MCP61 USB 2.0 controller"; case 0x15621131: return "Philips ISP156x USB 2.0 controller"; Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/musb_otg.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/musb_otg.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/musb_otg.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci_pci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci_pci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/ohci_pci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -172,6 +172,9 @@ ohci_pci_match(device_t self) case 0x00d710de: return ("nVidia nForce3 USB Controller"); + case 0x03f110de: + return ("nVidia nForce MCP61 USB Controller"); + case 0x70011039: return ("SiS 5571 USB controller"); Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci_pci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci_pci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uhci_pci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -200,6 +200,15 @@ uhci_pci_match(device_t self) case 0x265b8086: return ("Intel 82801FB/FR/FW/FRW (ICH6) USB controller USB-D"); + case 0x27c88086: + return ("Intel 82801G (ICH7) USB controller USB-A"); + case 0x27c98086: + return ("Intel 82801G (ICH7) USB controller USB-B"); + case 0x27ca8086: + return ("Intel 82801G (ICH7) USB controller USB-C"); + case 0x27cb8086: + return ("Intel 82801G (ICH7) USB controller USB-D"); + case 0x28308086: return ("Intel 82801H (ICH8) USB controller USB-A"); case 0x28318086: Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/usb_controller.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/usb_controller.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/usb_controller.c Mon Oct 12 07:29:50 2009 (r197974) @@ -79,6 +79,11 @@ SYSCTL_INT(_hw_usb_ctrl, OID_AUTO, debug "Debug level"); #endif +static int usb_no_boot_wait = 0; +TUNABLE_INT("hw.usb.no_boot_wait", &usb_no_boot_wait); +SYSCTL_INT(_hw_usb, OID_AUTO, no_boot_wait, CTLFLAG_RDTUN, &usb_no_boot_wait, 0, + "No device enumerate waiting at boot."); + static uint8_t usb_post_init_called = 0; static devclass_t usb_devclass; @@ -132,8 +137,10 @@ usb_attach(device_t dev) return (ENXIO); } - /* delay vfs_mountroot until the bus is explored */ - bus->bus_roothold = root_mount_hold(device_get_nameunit(dev)); + if (usb_no_boot_wait == 0) { + /* delay vfs_mountroot until the bus is explored */ + bus->bus_roothold = root_mount_hold(device_get_nameunit(dev)); + } if (usb_post_init_called) { mtx_lock(&Giant); Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uss820dci.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uss820dci.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/controller/uss820dci.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/u3g.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/u3g.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/u3g.c Mon Oct 12 07:29:50 2009 (r197974) @@ -186,6 +186,7 @@ static const struct usb_device_id u3g_de U3G_DEV(QUALCOMMINC, CDMA_MSM, U3GFL_SCSI_EJECT), /* OEM: Huawei */ U3G_DEV(HUAWEI, MOBILE, U3GFL_HUAWEI_INIT), + U3G_DEV(HUAWEI, E180V, U3GFL_HUAWEI_INIT), U3G_DEV(HUAWEI, E220, U3GFL_HUAWEI_INIT), /* OEM: Novatel */ U3G_DEV(NOVATEL, CDMA_MODEM, 0), Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/ulpt.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/ulpt.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/serial/ulpt.c Mon Oct 12 07:29:50 2009 (r197974) @@ -426,6 +426,9 @@ ulpt_open(struct usb_fifo *fifo, int ffl /* we assume that open is a serial process */ if (sc->sc_fflags == 0) { + + /* reset USB paralell port */ + ulpt_reset(sc); } return (unlpt_open(fifo, fflags)); @@ -720,7 +723,12 @@ ulpt_watchdog(void *arg) mtx_assert(&sc->sc_mtx, MA_OWNED); - usbd_transfer_start(sc->sc_xfer[ULPT_INTR_DT_RD]); + /* + * Only read status while the device is not opened, due to + * possible hardware or firmware bug in some printers. + */ + if (sc->sc_fflags == 0) + usbd_transfer_start(sc->sc_xfer[ULPT_INTR_DT_RD]); usb_callout_reset(&sc->sc_watchdog, hz, &ulpt_watchdog, sc); Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_busdma.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_busdma.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_busdma.c Mon Oct 12 07:29:50 2009 (r197974) @@ -679,8 +679,8 @@ usb_pc_cpu_invalidate(struct usb_page_ca /* nothing has been loaded into this page cache! */ return; } - bus_dmamap_sync(pc->tag, pc->map, - BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD); } /*------------------------------------------------------------------------* @@ -693,8 +693,7 @@ usb_pc_cpu_flush(struct usb_page_cache * /* nothing has been loaded into this page cache! */ return; } - bus_dmamap_sync(pc->tag, pc->map, - BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); + bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE); } /*------------------------------------------------------------------------* Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.c Mon Oct 12 07:29:50 2009 (r197974) @@ -398,15 +398,32 @@ int usb_submit_urb(struct urb *urb, uint16_t mem_flags) { struct usb_host_endpoint *uhe; + uint8_t do_unlock; + int err; - if (urb == NULL) { + if (urb == NULL) return (-EINVAL); - } - mtx_assert(&Giant, MA_OWNED); + + do_unlock = mtx_owned(&Giant) ? 0 : 1; + if (do_unlock) + mtx_lock(&Giant); if (urb->endpoint == NULL) { - return (-EINVAL); + err = -EINVAL; + goto done; } + + /* + * Check to see if the urb is in the process of being killed + * and stop a urb that is in the process of being killed from + * being re-submitted (e.g. from its completion callback + * function). + */ + if (urb->kill_count != 0) { + err = -EPERM; + goto done; + } + uhe = urb->endpoint; /* @@ -424,12 +441,16 @@ usb_submit_urb(struct urb *urb, uint16_t usbd_transfer_start(uhe->bsd_xfer[0]); usbd_transfer_start(uhe->bsd_xfer[1]); + err = 0; } else { /* no pipes have been setup yet! */ urb->status = -EINVAL; - return (-EINVAL); + err = -EINVAL; } - return (0); +done: + if (do_unlock) + mtx_unlock(&Giant); + return (err); } /*------------------------------------------------------------------------* @@ -448,9 +469,11 @@ static void usb_unlink_bsd(struct usb_xfer *xfer, struct urb *urb, uint8_t drain) { - if (xfer && - usbd_transfer_pending(xfer) && - (xfer->priv_fifo == (void *)urb)) { + if (xfer == NULL) + return; + if (!usbd_transfer_pending(xfer)) + return; + if (xfer->priv_fifo == (void *)urb) { if (drain) { mtx_unlock(&Giant); usbd_transfer_drain(xfer); @@ -467,14 +490,21 @@ usb_unlink_urb_sub(struct urb *urb, uint { struct usb_host_endpoint *uhe; uint16_t x; + uint8_t do_unlock; + int err; - if (urb == NULL) { + if (urb == NULL) return (-EINVAL); - } - mtx_assert(&Giant, MA_OWNED); + + do_unlock = mtx_owned(&Giant) ? 0 : 1; + if (do_unlock) + mtx_lock(&Giant); + if (drain) + urb->kill_count++; if (urb->endpoint == NULL) { - return (-EINVAL); + err = -EINVAL; + goto done; } uhe = urb->endpoint; @@ -504,7 +534,13 @@ usb_unlink_urb_sub(struct urb *urb, uint usb_unlink_bsd(uhe->bsd_xfer[0], urb, drain); usb_unlink_bsd(uhe->bsd_xfer[1], urb, drain); } - return (0); + err = 0; +done: + if (drain) + urb->kill_count--; + if (do_unlock) + mtx_unlock(&Giant); + return (err); } /*------------------------------------------------------------------------* @@ -555,6 +591,7 @@ static int usb_start_wait_urb(struct urb *urb, usb_timeout_t timeout, uint16_t *p_actlen) { int err; + uint8_t do_unlock; /* you must have a timeout! */ if (timeout == 0) { @@ -565,6 +602,9 @@ usb_start_wait_urb(struct urb *urb, usb_ urb->transfer_flags |= URB_WAIT_WAKEUP; urb->transfer_flags &= ~URB_IS_SLEEPING; + do_unlock = mtx_owned(&Giant) ? 0 : 1; + if (do_unlock) + mtx_lock(&Giant); err = usb_submit_urb(urb, 0); if (err) goto done; @@ -582,6 +622,8 @@ usb_start_wait_urb(struct urb *urb, usb_ err = urb->status; done: + if (do_unlock) + mtx_unlock(&Giant); if (err) { *p_actlen = 0; } else { @@ -638,7 +680,7 @@ usb_control_msg(struct usb_device *dev, * transfers on control endpoint zero: */ err = usbd_do_request_flags(dev, - &Giant, &req, data, USB_SHORT_XFER_OK, + NULL, &req, data, USB_SHORT_XFER_OK, &actlen, timeout); if (err) { err = -EPIPE; @@ -1216,9 +1258,7 @@ usb_init_urb(struct urb *urb) void usb_kill_urb(struct urb *urb) { - if (usb_unlink_urb_sub(urb, 1)) { - /* ignore */ - } + usb_unlink_urb_sub(urb, 1); } /*------------------------------------------------------------------------* Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.h ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.h Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_compat_linux.h Mon Oct 12 07:29:50 2009 (r197974) @@ -262,6 +262,7 @@ struct urb { uint8_t setup_dma; /* (in) not used on FreeBSD */ uint8_t transfer_dma; /* (in) not used on FreeBSD */ uint8_t bsd_isread; + uint8_t kill_count; /* FreeBSD specific */ struct usb_iso_packet_descriptor iso_frame_desc[]; /* (in) ISO ONLY */ }; Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_controller.h ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_controller.h Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_controller.h Mon Oct 12 07:29:50 2009 (r197974) @@ -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: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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) { @@ -740,6 +737,8 @@ usb_fifo_reset(struct usb_fifo *f) break; } } + /* reset have fragment flag */ + f->flag_have_fragment = 0; } /*------------------------------------------------------------------------* @@ -783,6 +782,16 @@ usb_fifo_close(struct usb_fifo *f, int f /* set flushing flag */ f->flag_flushing = 1; + /* get the last packet in */ + if (f->flag_have_fragment) { + struct usb_mbuf *m; + f->flag_have_fragment = 0; + USB_IF_DEQUEUE(&f->free_q, m); + if (m) { + USB_IF_ENQUEUE(&f->used_q, m); + } + } + /* start write transfer, if not already started */ (f->methods->f_start_write) (f); @@ -1030,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 */ @@ -1303,6 +1312,7 @@ usb_write(struct cdev *dev, struct uio * struct usb_cdev_privdata* cpd; struct usb_fifo *f; struct usb_mbuf *m; + uint8_t *pdata; int fflags; int resid; int io_len; @@ -1373,33 +1383,59 @@ usb_write(struct cdev *dev, struct uio * } tr_data = 1; - USB_MBUF_RESET(m); - - io_len = MIN(m->cur_data_len, uio->uio_resid); - - m->cur_data_len = io_len; + if (f->flag_have_fragment == 0) { + USB_MBUF_RESET(m); + io_len = m->cur_data_len; + pdata = m->cur_data_ptr; + if (io_len > uio->uio_resid) + io_len = uio->uio_resid; + m->cur_data_len = io_len; + } else { + io_len = m->max_data_len - m->cur_data_len; + pdata = m->cur_data_ptr + m->cur_data_len; + if (io_len > uio->uio_resid) + io_len = uio->uio_resid; + m->cur_data_len += io_len; + } DPRINTFN(2, "transfer %d bytes to %p\n", - io_len, m->cur_data_ptr); + io_len, pdata); - err = usb_fifo_uiomove(f, - m->cur_data_ptr, io_len, uio); + err = usb_fifo_uiomove(f, pdata, io_len, uio); if (err) { + f->flag_have_fragment = 0; USB_IF_ENQUEUE(&f->free_q, m); break; } - if (f->methods->f_filter_write) { + + /* check if the buffer is ready to be transmitted */ + + if ((f->flag_write_defrag == 0) || + (m->cur_data_len == m->max_data_len)) { + f->flag_have_fragment = 0; + /* - * Sometimes it is convenient to process data at the - * expense of a userland process instead of a kernel - * process. + * Check for write filter: + * + * Sometimes it is convenient to process data + * at the expense of a userland process + * instead of a kernel process. */ - (f->methods->f_filter_write) (f, m); - } - USB_IF_ENQUEUE(&f->used_q, m); + if (f->methods->f_filter_write) { + (f->methods->f_filter_write) (f, m); + } - (f->methods->f_start_write) (f); + /* Put USB mbuf in the used queue */ + USB_IF_ENQUEUE(&f->used_q, m); + + /* Start writing data, if not already started */ + (f->methods->f_start_write) (f); + } else { + /* Wait for more data or close */ + f->flag_have_fragment = 1; + USB_IF_PREPEND(&f->free_q, m); + } } while (uio->uio_resid > 0); done: @@ -2220,6 +2256,18 @@ usb_fifo_set_close_zlp(struct usb_fifo * f->flag_short = onoff; } +void +usb_fifo_set_write_defrag(struct usb_fifo *f, uint8_t onoff) +{ + if (f == NULL) + return; + + /* defrag written data */ + f->flag_write_defrag = onoff; + /* reset defrag state */ + f->flag_have_fragment = 0; +} + void * usb_fifo_softc(struct usb_fifo *f) { Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.h ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.h Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_dev.h Mon Oct 12 07:29:50 2009 (r197974) @@ -130,6 +130,8 @@ struct usb_fifo { uint8_t flag_short; /* set if short_ok or force_short * transfer flags should be set */ uint8_t flag_stall; /* set if clear stall should be run */ + uint8_t flag_write_defrag; /* set to defrag written data */ + uint8_t flag_have_fragment; /* set if defragging */ uint8_t iface_index; /* set to the interface we belong to */ uint8_t fifo_index; /* set to the FIFO index in "struct * usb_device" */ @@ -144,11 +146,9 @@ extern struct cdevsw usb_devsw; int usb_fifo_wait(struct usb_fifo *fifo); void usb_fifo_signal(struct usb_fifo *fifo); uint8_t usb_fifo_opened(struct usb_fifo *fifo); -void usb_fifo_free(struct usb_fifo *f); struct usb_symlink *usb_alloc_symlink(const char *target); void usb_free_symlink(struct usb_symlink *ps); int usb_read_symlink(uint8_t *user_ptr, uint32_t startentry, uint32_t user_len); -void usb_fifo_set_close_zlp(struct usb_fifo *, uint8_t); #endif /* _USB_DEV_H_ */ Modified: projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_device.c ============================================================================== --- projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_device.c Sun Oct 11 21:28:56 2009 (r197973) +++ projects/tcp_ffcaia2008_8.x/sys/dev/usb/usb_device.c Mon Oct 12 07:29:50 2009 (r197974) @@ -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,28 +821,23 @@ 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; goto done; } - if (udev->flags.usb_mode == USB_MODE_DEVICE) { - usb_detach_device(udev, iface_index, - USB_UNCFG_FLAG_FREE_SUBDEV); - } else { - if (iface->alt_index == alt_index) { - /* - * Optimise away duplicate setting of - * alternate setting in USB Host Mode! - */ - err = 0; - goto done; - } + if (iface->alt_index == alt_index) { + /* + * Optimise away duplicate setting of + * alternate setting in USB Host Mode! + */ + err = 0; + goto done; } #if USB_HAVE_UGEN /* @@ -858,13 +851,19 @@ usbd_set_alt_interface_index(struct usb_ if (err) { goto done; } + if (iface->alt_index != alt_index) { + /* the alternate setting does not exist */ + err = USB_ERR_INVAL; + goto done; + } + err = usbd_req_set_alt_interface_no(udev, NULL, iface_index, iface->idesc->bAlternateSetting); done: - if (do_unlock) { - sx_unlock(udev->default_sx + 1); - } + if (do_unlock) + usbd_enum_unlock(udev); + return (err); } @@ -959,7 +958,6 @@ usb_reset_iface_endpoints(struct usb_dev { struct usb_endpoint *ep; struct usb_endpoint *ep_end; - usb_error_t err; ep = udev->endpoints; ep_end = udev->endpoints + udev->endpoints_max; @@ -971,10 +969,7 @@ usb_reset_iface_endpoints(struct usb_dev continue; } /* simulate a clear stall from the peer */ - err = usbd_set_endpoint_stall(udev, ep, 0); - if (err) { - /* just ignore */ - } + usbd_set_endpoint_stall(udev, ep, 0); } return (0); } @@ -1233,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) { @@ -1286,6 +1281,7 @@ usb_probe_and_attach(struct usb_device * uaa.info.bIfaceNum = iface->idesc->bInterfaceNumber; uaa.use_generic = 0; + uaa.driver_info = 0; /* reset driver_info */ DPRINTFN(2, "iclass=%u/%u/%u iindex=%u/%u\n", uaa.info.bInterfaceClass, @@ -1302,6 +1298,7 @@ usb_probe_and_attach(struct usb_device * /* try generic interface drivers last */ uaa.use_generic = 1; + uaa.driver_info = 0; /* reset driver_info */ if (usb_probe_and_attach_sub(udev, &uaa)) { /* ignore */ @@ -1316,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); } @@ -1780,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 */ @@ -1903,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); } } @@ -2334,6 +2335,7 @@ usb_notify_addq(const char *type, struct "devclass=0x%02x " "devsubclass=0x%02x " "sernum=\"%s\" " + "release=0x%04x " "at " "port=%u " "on " @@ -2345,6 +2347,7 @@ usb_notify_addq(const char *type, struct udev->ddesc.bDeviceClass, udev->ddesc.bDeviceSubClass, udev->serial, + UGETW(udev->ddesc.bcdDevice), udev->port_no, udev->parent_hub != NULL ? udev->parent_hub->ugen_name : @@ -2447,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) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***