Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Oct 2009 07:29:51 +0000 (UTC)
From:      Lawrence Stewart <lstewart@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r197974 - in projects/tcp_ffcaia2008_8.x/sys: dev/usb dev/usb/controller dev/usb/serial netinet/ipfw
Message-ID:  <200910120729.n9C7TpNv049956@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910120729.n9C7TpNv049956>