svn commit: r197974 - in projects/tcp_ffcaia2008_8.x/sys: dev/usb
dev/usb/controller dev/usb/serial netinet/ipfw
Lawrence Stewart
lstewart at FreeBSD.org
Mon Oct 12 07:29:51 UTC 2009
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 ***
More information about the svn-src-projects
mailing list