[PATCH2] for ng_ubt2 stalled transfers

Lars Engels lme at FreeBSD.org
Fri Jan 23 14:17:07 PST 2009


On Fri, Jan 23, 2009 at 10:49:23PM +0100, Hans Petter Selasky wrote:
> On Friday 23 January 2009, Lars Engels wrote:
> > I forgot to mention that both bt devices worked without problems with
> > the old stack, so there is no hardware issue. :)
> 
> Hi,
> 
> Bluetooth has worked fine with the new USB stack aswell. I have tested this 
> myself. It is just some small problems with the latest changes from Maksim 
> that needs to be ironed out.
> 
> Maybe you can give my patch a try?
> 
> cvsup first
> 
> Then:
> 
> cd /usr/src/sys/dev/usb2/bluetooth; cat bt_patch.diff | patch
> 
> recompile "/usr/src/sys/modules/usb2/bluetooth_ng" module only and test, 
> assuming you are loading the module.
> 
> I'm not sure if my patch is 100% correct, Maksim is the bluetooth+Netgraph 
> expert, but at least my bluetooth dongle now works again.
> 

This didn't work too well, the patch did not apply:


ng collection src-all/cvs
 Checkout src/sys/dev/usb2/bluetooth/TODO.TXT
 Checkout src/sys/dev/usb2/bluetooth/ng_ubt2.c
 Checkout src/sys/dev/usb2/bluetooth/ng_ubt2_var.h
 Checkout src/sys/dev/usb2/bluetooth/ubtbcmfw2.c
 Checkout src/sys/dev/usb2/bluetooth/usb2_bluetooth.c
 Checkout src/sys/dev/usb2/bluetooth/usb2_bluetooth.h
Shutting down connection to server
Finished successfully
                                                                                                                                                                       Fri, 23. Jan 2009, 23:14:44                                                                                                                                            <FreeBSD 8.0-CURRENT> [maggie:/usr/src/sys/dev/usb2/bluetooth]                                                                                                         lars at pts/3 # cat ~/local-patches/bt_patch.diff | patch
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff -u ng_ubt2.c ng_ubt2.c
|--- ng_ubt2.c  Wed Jan 21 17:51:04 2009
|+++ ng_ubt2.c  Fri Jan 23 20:17:44 2009
--------------------------
Patching file ng_ubt2.c using Plan A...
Reversed (or previously applied) patch detected!  Assume -R? [y] y
Hunk #1 succeeded at 28.
Hunk #2 failed at 37.
Hunk #3 failed at 67.
Hunk #4 failed at 111.
Hunk #5 succeeded at 163 with fuzz 2 (offset 35 lines).
Hunk #6 failed at 314.
Hunk #7 failed at 323.
Hunk #8 failed at 332.
Hunk #9 failed at 341.
Hunk #10 failed at 350.
Hunk #11 failed at 360.
Hunk #12 failed at 373.
Hunk #13 failed at 388.
Hunk #14 failed at 398.
Hunk #15 failed at 408.
Hunk #16 failed at 418.
Hunk #17 failed at 485.
Hunk #18 failed at 518.
Hunk #19 failed at 555.
Hunk #20 failed at 615.
Hunk #21 failed at 629.
Hunk #22 failed at 647.
Hunk #23 failed at 665.
Hunk #24 failed at 692.
Hunk #25 succeeded at 825 with fuzz 2 (offset 106 lines).
Hunk #26 failed at 846.
Hunk #27 failed at 942.
Hunk #28 succeeded at 834 with fuzz 2 (offset -21 lines).
Hunk #29 failed at 846.
Hunk #30 failed at 866.
Hunk #31 failed at 962.
Hunk #32 succeeded at 980 with fuzz 2 (offset -22 lines).
Hunk #33 failed at 992.
Hunk #34 failed at 1009.
Hunk #35 failed at 1067.
Hunk #36 succeeded at 1115 with fuzz 2 (offset 7 lines).
Hunk #37 failed at 1127.
Hunk #38 succeeded at 1121 with fuzz 2 (offset -16 lines).
Hunk #39 failed at 1155.
Hunk #40 failed at 1261.
Hunk #41 failed at 1289.
Hunk #42 failed at 1312.
Hunk #43 failed at 1339.
Hunk #44 failed at 1530.
Hunk #45 failed at 1576.
Hunk #46 failed at 1593.
Hunk #47 failed at 1602.
Hunk #48 failed at 1648.
Hunk #49 failed at 1656.
Hunk #50 failed at 1807.
Hunk #51 failed at 1837.
Hunk #52 failed at 1847.
Hunk #53 failed at 1865.
Hunk #54 failed at 1878.
Hunk #55 succeeded at 2235 (offset 273 lines).
47 out of 55 hunks failed--saving rejects to ng_ubt2.c.rej
Hmm...  The next patch looks like a unified diff to me...
The text leading up to this was:
--------------------------
|diff -u ng_ubt2_var.h ng_ubt2_var.h
|--- ng_ubt2_var.h      Wed Jan 21 17:51:04 2009
|+++ ng_ubt2_var.h      Fri Jan 23 20:08:04 2009
--------------------------
Patching file ng_ubt2_var.h using Plan A...
Reversed (or previously applied) patch detected!  Assume -R? [y] y
Hunk #1 succeeded at 28.
Hunk #2 failed at 47.
Hunk #3 failed at 65.
Hunk #4 failed at 89.
Hunk #5 failed at 100.
Hunk #6 failed at 123.
5 out of 6 hunks failed--saving rejects to ng_ubt2_var.h.rej
done
Exit 52




> diff -u ng_ubt2.c ng_ubt2.c
> --- ng_ubt2.c	Wed Jan 21 17:51:04 2009
> +++ ng_ubt2.c	Fri Jan 23 20:17:44 2009
> @@ -28,7 +28,7 @@
>   * SUCH DAMAGE.
>   *
>   * $Id: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
> - * $FreeBSD$
> + * $FreeBSD: src/sys/dev/usb2/bluetooth/ng_ubt2.c,v 1.6 2009/01/20 23:25:27 emax Exp $
>   */
>  
>  /*
> @@ -37,22 +37,12 @@
>   * driver will *NOT* create traditional /dev/ enties, only Netgraph 
>   * node.
>   *
> - * NOTE ON LOCKS USED: ng_ubt2 drives uses 3 locks (mutexes)
> + * NOTE ON LOCKS USED: ng_ubt2 drives uses 1 lock
>   *
> - * 1) sc_if_mtx[0] - lock for device's interface #0. This lock is used
> - *    by USB2 for any USB request going over device's interface #0, i.e.
> - *    interrupt, control and bulk transfers.
> - * 
> - * 2) sc_if_mtx[1] - lock for device's interface #1. This lock is used
> - *    by USB2 for any USB request going over device's interface #1, i.e
> - *    isoc. transfers.
> - * 
> - * 3) sc_mbufq_mtx - lock for mbufq and task flags. This lock is used
> - *    to protect device's outgoing mbuf queues and task flags. This lock
> - *    *SHOULD NOT* be grabbed for a long time. In fact, think of it as a 
> - *    spin lock.
> + * The "sc_mtx" lock protects both USB and Netgraph data. The "sc_mtx"
> + * lock should not be grabbed for a long time.
>   *
> - * NOTE ON LOCKING STRATEGY: ng_ubt2 driver operates in 3 different contexts.
> + * NOTE ON LOCKING STRATEGY: ng_ubt2 driver operates in 2 different contexts.
>   *
>   * 1) USB context. This is where all the USB related stuff happens. All
>   *    callbacks run in this context. All callbacks are called (by USB2) with
> @@ -67,26 +57,6 @@
>   *    grab any long-sleep lock in the Netgraph context. In fact, the only
>   *    lock that is allowed in the Netgraph context is the sc_mbufq_mtx lock.
>   *
> - * 3) Taskqueue context. This is where ubt_task runs. Since we are NOT allowed
> - *    to grab any locks in the Netgraph context, and, USB2 requires us to
> - *    grab interface lock before doing things with transfers, we need to
> - *    transition from the Netgraph context to the Taskqueue context before
> - *    we can call into USB2 subsystem.
> - *
> - * So, to put everything together, the rules are as follows.
> - *	It is OK to call from the USB context or the Taskqueue context into
> - * the Netgraph context (i.e. call NG_SEND_xxx functions). In other words
> - * it is allowed to call into the Netgraph context with locks held.
> - *	Is it *NOT* OK to call from the Netgraph context into the USB context,
> - * because USB2 requires us to grab interface locks and we can not do that.
> - * To avoid this, we set task flags to indicate which actions we want to
> - * perform and schedule ubt_task which would run in the Taskqueue context.
> - *	Is is OK to call from the Taskqueue context into the USB context,
> - * and, ubt_task does just that (i.e. grabs appropriate interface locks
> - * before calling into USB2).
> - *	Access to the outgoing queues and task flags is controlled by the
> - * sc_mbufq_mtx lock. It is an unavoidable evil. Again, sc_mbufq_mtx should
> - * really be a spin lock.
>   *	All USB callbacks accept Netgraph node pointer as private data. To
>   * ensure that Netgraph node pointer remains valid for the duration of the
>   * transfer, we grab a referrence to the node. In other words, if transfer is
> @@ -111,7 +81,6 @@
>  #include <dev/usb2/core/usb2_transfer.h>
>  
>  #include <sys/mbuf.h>
> -#include <sys/taskqueue.h>
>  
>  #include <netgraph/ng_message.h>
>  #include <netgraph/netgraph.h>
> @@ -128,10 +97,6 @@
>  static device_attach_t	ubt_attach;
>  static device_detach_t	ubt_detach;
>  
> -static int		ubt_task_schedule(ubt_softc_p, int);
> -static task_fn_t	ubt_task;
> -static void		ubt_xfer_start(ubt_softc_p, int);
> -
>  /* Netgraph methods */
>  static ng_constructor_t	ng_ubt_constructor;
>  static ng_shutdown_t	ng_ubt_shutdown;
> @@ -279,6 +244,7 @@
>  		.type =		UE_BULK,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_OUT,
> +		.if_index =	0,
>  		.mh.bufsize =	UBT_BULK_WRITE_BUFFER_SIZE,
>  		.mh.flags =	{ .pipe_bof = 1, },
>  		.mh.callback =	&ubt_bulk_write_callback,
> @@ -288,6 +254,7 @@
>  		.type =		UE_BULK,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_IN,
> +		.if_index =	0,
>  		.mh.bufsize =	UBT_BULK_READ_BUFFER_SIZE,
>  		.mh.flags =	{ .pipe_bof = 1, .short_xfer_ok = 1, },
>  		.mh.callback =	&ubt_bulk_read_callback,
> @@ -297,6 +264,7 @@
>  		.type =		UE_INTERRUPT,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_IN,
> +		.if_index =	0,
>  		.mh.flags =	{ .pipe_bof = 1, .short_xfer_ok = 1, },
>  		.mh.bufsize =	UBT_INTR_BUFFER_SIZE,
>  		.mh.callback =	&ubt_intr_read_callback,
> @@ -306,6 +274,7 @@
>  		.type =		UE_CONTROL,
>  		.endpoint =	0x00,	/* control pipe */
>  		.direction =	UE_DIR_ANY,
> +		.if_index =	0,
>  		.mh.bufsize =	UBT_CTRL_BUFFER_SIZE,
>  		.mh.callback =	&ubt_ctrl_write_callback,
>  		.mh.timeout =	5000,	/* 5 seconds */
> @@ -315,6 +284,7 @@
>  		.type =		UE_CONTROL,
>  		.endpoint =	0x00,	/* control pipe */
>  		.direction =	UE_DIR_ANY,
> +		.if_index =	0,
>  		.mh.bufsize =	sizeof(struct usb2_device_request),
>  		.mh.callback =	&ubt_bulk_write_clear_stall_callback,
>  		.mh.timeout =	1000,	/* 1 second */
> @@ -325,6 +295,7 @@
>  		.type =		UE_CONTROL,
>  		.endpoint =	0x00,	/* control pipe */
>  		.direction =	UE_DIR_ANY,
> +		.if_index =	0,
>  		.mh.bufsize =	sizeof(struct usb2_device_request),
>  		.mh.callback =	&ubt_bulk_read_clear_stall_callback,
>  		.mh.timeout =	1000,	/* 1 second */
> @@ -338,6 +309,7 @@
>  		.type =		UE_CONTROL,
>  		.endpoint =	0x00,	/* control pipe */
>  		.direction =	UE_DIR_ANY,
> +		.if_index =	0,
>  		.mh.bufsize =	sizeof(struct usb2_device_request),
>  		.mh.callback =	&ubt_intr_read_clear_stall_callback,
>  		.mh.timeout =	1000,	/* 1 second */
> @@ -353,6 +325,7 @@
>  		.type =		UE_ISOCHRONOUS,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_IN,
> +		.if_index =	1,
>  		.mh.bufsize =	0,	/* use "wMaxPacketSize * frames" */
>  		.mh.frames =	UBT_ISOC_NFRAMES,
>  		.mh.flags =	{ .short_xfer_ok = 1, },
> @@ -363,6 +336,7 @@
>  		.type =		UE_ISOCHRONOUS,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_IN,
> +		.if_index =	1,
>  		.mh.bufsize =	0,	/* use "wMaxPacketSize * frames" */
>  		.mh.frames =	UBT_ISOC_NFRAMES,
>  		.mh.flags =	{ .short_xfer_ok = 1, },
> @@ -373,6 +347,7 @@
>  		.type =		UE_ISOCHRONOUS,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_OUT,
> +		.if_index =	1,
>  		.mh.bufsize =	0,	/* use "wMaxPacketSize * frames" */
>  		.mh.frames =	UBT_ISOC_NFRAMES,
>  		.mh.flags =	{ .short_xfer_ok = 1, },
> @@ -383,6 +358,7 @@
>  		.type =		UE_ISOCHRONOUS,
>  		.endpoint =	UE_ADDR_ANY,
>  		.direction =	UE_DIR_OUT,
> +		.if_index =	1,
>  		.mh.bufsize =	0,	/* use "wMaxPacketSize * frames" */
>  		.mh.frames =	UBT_ISOC_NFRAMES,
>  		.mh.flags =	{ .short_xfer_ok = 1, },
> @@ -450,7 +426,8 @@
>  	struct ubt_softc		*sc = device_get_softc(dev);
>  	struct usb2_endpoint_descriptor	*ed;
>  	uint16_t			wMaxPacketSize;
> -	uint8_t				alt_index, iface_index, i, j;
> +	uint8_t				alt_index, i, j;
> +	uint8_t				iface_index[2];
>  
>  	device_set_usb2_desc(dev);
>  
> @@ -483,28 +460,22 @@
>  
>  	/* state */
>  	sc->sc_debug = NG_UBT_WARN_LEVEL;
> -	sc->sc_flags = 0;
> +
>  	UBT_STAT_RESET(sc);
>  
>  	/* initialize locks */
> -	mtx_init(&sc->sc_mbufq_mtx, "ubt mbufq", NULL, MTX_DEF);
> -	mtx_init(&sc->sc_if_mtx[0], "ubt if0", NULL, MTX_DEF | MTX_RECURSE);
> -	mtx_init(&sc->sc_if_mtx[1], "ubt if1", NULL, MTX_DEF | MTX_RECURSE);
> +	mtx_init(&sc->sc_mtx, "UBT", NULL, MTX_DEF | MTX_RECURSE);
>  
>  	/* initialize packet queues */
>  	NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
>  	NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
>  	NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
>  
> -	/* initialize glue task */
> -	sc->sc_task_flags = 0;
> -	TASK_INIT(&sc->sc_task, 0, ubt_task, sc->sc_node);
> -
>  	/*
>  	 * Configure Bluetooth USB device. Discover all required USB
>  	 * interfaces and endpoints.
>  	 *
> -	 * Device is expected to be a high-speed device.
> +	 * Device is expected to be a full-speed device.
>  	 *
>  	 * USB device must present two interfaces:
>  	 * 1) Interface 0 that has 3 endpoints
> @@ -520,20 +491,11 @@
>  	 * configurations with different packet size.
>  	 */
>  
> -	bzero(&sc->sc_xfer, sizeof(sc->sc_xfer));
> -
>  	/*
>  	 * Interface 0
>  	 */
>  
> -	iface_index = 0;
> -	if (usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
> -			ubt_config, UBT_IF_0_N_TRANSFER,
> -			sc->sc_node, &sc->sc_if_mtx[0])) {
> -		device_printf(dev, "could not allocate transfers for " \
> -			"interface 0!\n");
> -		goto detach;
> -	}
> +	iface_index[0] = 0;
>  
>  	/*
>  	 * Interface 1
> @@ -580,13 +542,11 @@
>  		goto detach;
>  	}
>  
> -	iface_index = 1;
> -	if (usb2_transfer_setup(uaa->device, &iface_index,
> -			&sc->sc_xfer[UBT_IF_0_N_TRANSFER],
> -			&ubt_config[UBT_IF_0_N_TRANSFER], UBT_IF_1_N_TRANSFER,
> -			sc->sc_node, &sc->sc_if_mtx[1])) {
> -		device_printf(dev, "could not allocate transfers for " \
> -			"interface 1!\n");
> +	iface_index[1] = 1;
> +	if (usb2_transfer_setup(uaa->device, iface_index,
> +			sc->sc_xfer, ubt_config, UBT_N_TRANSFER,
> +			sc->sc_node, &sc->sc_mtx)) {
> +		device_printf(dev, "could not allocate transfers\n");
>  		goto detach;
>  	}
>  
> @@ -594,6 +554,10 @@
>  	for (i = 1; usb2_get_iface(uaa->device, i) != NULL; i ++)
>  		usb2_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
>  
> +	UBT_LOCK(sc);
> +	sc->sc_flags |= UBT_FLAG_READY;
> +	UBT_UNLOCK(sc);
> +
>  	return (0); /* success */
>  
>  detach:
> @@ -612,17 +576,33 @@
>  {
>  	struct ubt_softc	*sc = device_get_softc(dev);
>  	node_p			node = sc->sc_node;
> +	uint8_t			i;
> +
> +	UBT_LOCK(sc);
> +	sc->sc_flags &= ~UBT_FLAG_READY;
> +	UBT_UNLOCK(sc);
> +
> +	/* make sure that all USB transfers are stopped! */
> +	for (i = 0; i != UBT_N_TRANSFER; i++)
> +		usb2_transfer_drain(sc->sc_xfer[i]);
>  
>  	/* Destroy Netgraph node */
>  	if (node != NULL) {
>  		sc->sc_node = NULL;
>  
> -		NG_NODE_SET_PRIVATE(node, NULL);
>  		NG_NODE_REALLY_DIE(node);
> -		NG_NODE_REF(node);
>  		ng_rmnode_self(node);
> -	}
>  
> +		/* Need to wait until Netgraph has shutdown the node! */
> +		UBT_LOCK(sc);
> +		while (!(sc->sc_flags & UBT_FLAG_SHUTDOWN))
> +			usb2_pause_mtx(&sc->sc_mtx, 100);
> +		UBT_UNLOCK(sc);
> +
> +		/* Check if there is a leftover hook */
> +		if (sc->sc_hook != NULL)
> +			NG_NODE_UNREF(node);
> +	}
>  	/* Free USB transfers, if any */
>  	usb2_transfer_unsetup(sc->sc_xfer, UBT_N_TRANSFER);
>  
> @@ -630,15 +610,13 @@
>  		NG_NODE_UNREF(node);
>  
>  	/* Destroy queues */
> -	UBT_MBUFQ_LOCK(sc);
> +	UBT_LOCK(sc);
>  	NG_BT_MBUFQ_DESTROY(&sc->sc_cmdq);
>  	NG_BT_MBUFQ_DESTROY(&sc->sc_aclq);
>  	NG_BT_MBUFQ_DESTROY(&sc->sc_scoq);
> -	UBT_MBUFQ_UNLOCK(sc);
> +	UBT_UNLOCK(sc);
>  
> -	mtx_destroy(&sc->sc_if_mtx[0]);
> -	mtx_destroy(&sc->sc_if_mtx[1]);
> -	mtx_destroy(&sc->sc_mbufq_mtx);
> +	mtx_destroy(&sc->sc_mtx);
>  
>  	return (0);
>  } /* ubt_detach */
> @@ -657,37 +635,25 @@
>  	struct usb2_device_request	req;
>  	struct mbuf			*m;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  
>  	switch (USB_GET_STATE(xfer)) {
>  	case USB_ST_TRANSFERRED:
> -		if (xfer->error != 0)
> -			UBT_STAT_OERROR(sc);
> -		else {
> -			UBT_INFO(sc, "sent %d bytes to control pipe\n",
> -				xfer->actlen);
> +		UBT_INFO(sc, "sent %d bytes to control pipe\n",
> +		    xfer->actlen);
> +
> +		UBT_STAT_BYTES_SENT(sc, xfer->actlen);
> +		UBT_STAT_PCKTS_SENT(sc);
>  
> -			UBT_STAT_BYTES_SENT(sc, xfer->actlen);
> -			UBT_STAT_PCKTS_SENT(sc);
> -		}
>  		/* FALLTHROUGH */
>  
>  	case USB_ST_SETUP:
>  send_next:
>  		/* Get next command mbuf, if any */
> -		UBT_MBUFQ_LOCK(sc);
>  		NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
> -		UBT_MBUFQ_UNLOCK(sc);
> -
>  		if (m == NULL) {
>  			UBT_INFO(sc, "HCI command queue is empty\n");
> -			NG_NODE_UNREF(node);
> -			return;
> +			break;
>  		}
>  
>  		/* Initialize a USB control request and then schedule it */
> @@ -719,8 +685,6 @@
>  			UBT_STAT_OERROR(sc);
>  			goto send_next;
>  		}
> -
> -		NG_NODE_UNREF(node); /* cancelled */
>  		break;
>  	}
>  } /* ubt_ctrl_write_callback */
> @@ -740,19 +704,8 @@
>  	ng_hci_event_pkt_t	*hdr;
>  	int			error;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  
> -	if ((sc->sc_hook == NULL) || NG_HOOK_NOT_VALID(sc->sc_hook)) {
> -		UBT_INFO(sc, "no upstream hook\n");
> -		NG_NODE_UNREF(node);
> -		return; /* upstream hook is gone */
> -	}
> -
>  	m = NULL;
>  
>  	switch (USB_GET_STATE(xfer)) {
> @@ -836,8 +789,7 @@
>  			/* Try to clear stall first */
>  			sc->sc_flags |= UBT_FLAG_INTR_STALL;
>  			usb2_transfer_start(sc->sc_xfer[UBT_IF_0_INTR_CS_RD]);
> -		} else
> -			NG_NODE_UNREF(node); /* cancelled */
> +		}
>  		break;
>  	}
>  } /* ubt_intr_read_callback */
> @@ -855,11 +807,6 @@
>  	struct ubt_softc	*sc;
>  	struct usb2_xfer	*xfer_other;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  	xfer_other = sc->sc_xfer[UBT_IF_0_INTR_DT_RD];
>  
> @@ -867,8 +814,7 @@
>  		DPRINTF("stall cleared\n");
>  		sc->sc_flags &= ~UBT_FLAG_INTR_STALL;
>  		usb2_transfer_start(xfer_other);
> -	} else
> -		NG_NODE_UNREF(node); /* cant clear stall */
> +	}
>  } /* ubt_intr_read_clear_stall_callback */
>  
>  /*
> @@ -887,19 +833,7 @@
>  	uint16_t		len;
>  	int			error;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
> -
> -	if ((sc->sc_hook == NULL) || NG_HOOK_NOT_VALID(sc->sc_hook)) {
> -		UBT_INFO(sc, "no upstream hook\n");
> -		NG_NODE_UNREF(node);
> -		return; /* upstream hook is gone */
> -	}
> -
>  	m = NULL;
>  
>  	switch (USB_GET_STATE(xfer)) {
> @@ -983,8 +917,7 @@
>  			/* Try to clear stall first */
>  			sc->sc_flags |= UBT_FLAG_READ_STALL;
>  			usb2_transfer_start(sc->sc_xfer[UBT_IF_0_BULK_CS_RD]);
> -		} else
> -			NG_NODE_UNREF(node); /* cancelled */
> +		}
>  		break;
>  	}
>  } /* ubt_bulk_read_callback */
> @@ -1002,11 +935,6 @@
>  	struct ubt_softc	*sc;
>  	struct usb2_xfer	*xfer_other;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  	xfer_other = sc->sc_xfer[UBT_IF_0_BULK_DT_RD];
>  
> @@ -1014,8 +942,7 @@
>  		DPRINTF("stall cleared\n");
>  		sc->sc_flags &= ~UBT_FLAG_READ_STALL;
>  		usb2_transfer_start(xfer_other);
> -	} else
> -		NG_NODE_UNREF(node); /* cant clear stall */
> +	}
>  } /* ubt_bulk_read_clear_stall_callback */
>  
>  /*
> @@ -1031,36 +958,24 @@
>  	struct ubt_softc	*sc;
>  	struct mbuf		*m;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  
>  	switch (USB_GET_STATE(xfer)) {
>  	case USB_ST_TRANSFERRED:
> -		if (xfer->error != 0)
> -			UBT_STAT_OERROR(sc);
> -		else {
> -			UBT_INFO(sc, "sent %d bytes to bulk-out pipe\n",
> -				xfer->actlen);
> +		UBT_INFO(sc, "sent %d bytes to bulk-out pipe\n",
> +		    xfer->actlen);
> +
> +		UBT_STAT_BYTES_SENT(sc, xfer->actlen);
> +		UBT_STAT_PCKTS_SENT(sc);
>  
> -			UBT_STAT_BYTES_SENT(sc, xfer->actlen);
> -			UBT_STAT_PCKTS_SENT(sc);
> -		}
>  		/* FALLTHROUGH */
>  
>  	case USB_ST_SETUP:
>  		/* Get next mbuf, if any */
> -		UBT_MBUFQ_LOCK(sc);
>  		NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
> -		UBT_MBUFQ_UNLOCK(sc);
> -
>  		if (m == NULL) {
>  			UBT_INFO(sc, "ACL data queue is empty\n");
> -			NG_NODE_UNREF(node);
> -			return; /* transfer completed */
> +			break;
>  		}
>  
>  		/*
> @@ -1089,8 +1004,7 @@
>  			/* try to clear stall first */
>  			sc->sc_flags |= UBT_FLAG_WRITE_STALL;
>  			usb2_transfer_start(sc->sc_xfer[UBT_IF_0_BULK_CS_WR]);
> -		} else
> -			NG_NODE_UNREF(node); /* cancelled */
> +		}
>  		break;
>  	}
>  } /* ubt_bulk_write_callback */
> @@ -1108,11 +1022,6 @@
>  	struct ubt_softc	*sc;
>  	struct usb2_xfer	*xfer_other;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  	xfer_other = sc->sc_xfer[UBT_IF_0_BULK_DT_WR];
>  
> @@ -1120,8 +1029,7 @@
>  		DPRINTF("stall cleared\n");
>  		sc->sc_flags &= ~UBT_FLAG_WRITE_STALL;
>  		usb2_transfer_start(xfer_other);
> -	} else
> -		NG_NODE_UNREF(node); /* cant clear stall */
> +	}
>  } /* ubt_bulk_write_clear_stall_callback */
>  
>  /*
> @@ -1137,19 +1045,8 @@
>  	struct ubt_softc	*sc;
>  	int			n;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  
> -	if ((sc->sc_hook == NULL) || NG_HOOK_NOT_VALID(sc->sc_hook)) {
> -		UBT_INFO(sc, "no upstream hook\n");
> -		NG_NODE_UNREF(node);
> -		return; /* upstream hook is gone */
> -	}
> -
>  	switch (USB_GET_STATE(xfer)) {
>  	case USB_ST_TRANSFERRED:
>  		for (n = 0; n < xfer->nframes; n ++)
> @@ -1171,8 +1068,6 @@
>                          goto read_next;
>  			/* NOT REACHED */
>                  }
> -
> -		NG_NODE_UNREF(node); /* cancelled */
>  		break;
>  	}
>  } /* ubt_isoc_read_callback */
> @@ -1277,24 +1172,16 @@
>  	struct mbuf		*m;
>  	int			n, space, offset;
>  
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
>  	sc = NG_NODE_PRIVATE(node);
>  
>  	switch (USB_GET_STATE(xfer)) {
>  	case USB_ST_TRANSFERRED:
> -		if (xfer->error)
> -			UBT_STAT_OERROR(sc);
> -		else {
> -			UBT_INFO(sc, "sent %d bytes to isoc-out pipe\n",
> -				xfer->actlen);
> +		UBT_INFO(sc, "sent %d bytes to isoc-out pipe\n",
> +		    xfer->actlen);
> +
> +		UBT_STAT_BYTES_SENT(sc, xfer->actlen);
> +		UBT_STAT_PCKTS_SENT(sc);
>  
> -			UBT_STAT_BYTES_SENT(sc, xfer->actlen);
> -			UBT_STAT_PCKTS_SENT(sc);
> -		}
>  		/* FALLTHROUGH */
>  
>  	case USB_ST_SETUP:
> @@ -1305,10 +1192,7 @@
>  
>  		while (space > 0) {
>  			if (m == NULL) {
> -				UBT_MBUFQ_LOCK(sc);
>  				NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
> -				UBT_MBUFQ_UNLOCK(sc);
> -
>  				if (m == NULL)
>  					break;
>  			}
> @@ -1328,9 +1212,7 @@
>  
>  		/* Put whatever is left from mbuf back on queue */
>  		if (m != NULL) {
> -			UBT_MBUFQ_LOCK(sc);
>  			NG_BT_MBUFQ_PREPEND(&sc->sc_scoq, m);
> -			UBT_MBUFQ_UNLOCK(sc);
>  		}
>  
>  		/*
> @@ -1355,174 +1237,12 @@
>  			goto send_next;
>  			/* NOT REACHED */
>  		}
> -
> -		NG_NODE_UNREF(node); /* cancelled */
>  		break;
>  	}
>  }
>  
>  /****************************************************************************
>   ****************************************************************************
> - **                                 Glue 
> - ****************************************************************************
> - ****************************************************************************/
> -
> -/*
> - * Schedule glue task. Should be called with sc_mbufq_mtx held.
> - * Netgraph context.
> - */
> -
> -static int
> -ubt_task_schedule(ubt_softc_p sc, int action)
> -{
> -	mtx_assert(&sc->sc_mbufq_mtx, MA_OWNED);
> -
> -	if ((sc->sc_task_flags & action) == 0) {
> -		/*
> -		 * Try to handle corner case when "start all" and "stop all"
> -		 * actions can both be set before task is executed.
> -		 *
> -		 * Assume the following:
> -		 * 1) "stop all" after "start all" cancels "start all", and,
> -		 *    keeps "stop all"
> -		 *
> -		 * 2) "start all" after "stop all" is fine because task is
> -		 *    executing "stop all" first
> -		 */
> -
> -		if (action == UBT_FLAG_T_STOP_ALL &&
> -		    (sc->sc_task_flags & UBT_FLAG_T_START_ALL) != 0)
> -			sc->sc_task_flags &= ~UBT_FLAG_T_START_ALL;
> -
> -		sc->sc_task_flags |= action;
> -	}
> -
> -	if (sc->sc_task_flags & UBT_FLAG_T_PENDING)
> -		return (1);
> -
> -	if (taskqueue_enqueue(taskqueue_swi, &sc->sc_task) == 0) {
> -		NG_NODE_REF(sc->sc_node);
> -		sc->sc_task_flags |= UBT_FLAG_T_PENDING;
> -		return (1);
> -	}
> -
> -	/* XXX: i think this should never happen */
> -
> -	return (0);
> -} /* ubt_task_schedule */
> -
> -/*
> - * Glue task. Examines sc_task_flags and does things depending on it.
> - * Taskqueue context.
> - */
> -
> -static void
> -ubt_task(void *context, int pending)
> -{
> -	node_p		node = context;
> -	ubt_softc_p	sc;
> -	int		task_flags;
> -
> -	if (NG_NODE_NOT_VALID(node)) {
> -		NG_NODE_UNREF(node);
> -		return; /* netgraph node is gone */
> -	}
> -
> -	sc = NG_NODE_PRIVATE(node);
> -
> -	UBT_MBUFQ_LOCK(sc);
> -	task_flags = sc->sc_task_flags;
> -	sc->sc_task_flags = 0;
> -	UBT_MBUFQ_UNLOCK(sc);
> -
> -	/* Stop all USB transfers */
> -	if (task_flags & UBT_FLAG_T_STOP_ALL) {
> -		int	i;
> -
> -		/*
> -		 * Interface #0
> -		 */
> -
> -		mtx_lock(&sc->sc_if_mtx[0]);
> -
> -		for (i = UBT_IF_0_BULK_DT_WR; i < UBT_IF_0_N_TRANSFER; i ++)
> -			usb2_transfer_stop(sc->sc_xfer[i]);
> -
> -		mtx_unlock(&sc->sc_if_mtx[0]);
> -
> -		/*
> -		 * Interface #1
> -		 */
> -
> -		mtx_lock(&sc->sc_if_mtx[1]);
> -
> -		for (i = UBT_IF_1_ISOC_DT_RD1; i < UBT_N_TRANSFER; i ++) 
> -			usb2_transfer_stop(sc->sc_xfer[i]);
> -
> -		mtx_unlock(&sc->sc_if_mtx[1]);
> -	}
> -
> -	/* Start all incoming USB transfers */
> -	if (task_flags & UBT_FLAG_T_START_ALL) {
> -		/*
> -		 * Interface #0
> -		 */
> -
> -		mtx_lock(&sc->sc_if_mtx[0]);
> -		ubt_xfer_start(sc, UBT_IF_0_INTR_DT_RD);
> -		ubt_xfer_start(sc, UBT_IF_0_BULK_DT_RD);
> -		mtx_unlock(&sc->sc_if_mtx[0]);
> -
> -		/*
> -		 * Interface #1
> -		 * Start both read and write isoc. transfers by default.
> -		 * Get them going all the time even if we have nothing
> -		 * to send to avoid any delays.
> -		 */
> -
> -		mtx_lock(&sc->sc_if_mtx[1]);
> -		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD1);
> -		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_RD2);
> -		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR1);
> -		ubt_xfer_start(sc, UBT_IF_1_ISOC_DT_WR2);
> -		mtx_unlock(&sc->sc_if_mtx[1]);
> -	}
> -
> - 	/* Start outgoing control transfer */
> -	if (task_flags & UBT_FLAG_T_START_CTRL) {
> -		mtx_lock(&sc->sc_if_mtx[0]);
> -		ubt_xfer_start(sc, UBT_IF_0_CTRL_DT_WR);
> -		mtx_unlock(&sc->sc_if_mtx[0]);
> -	}
> -
> -	/* Start outgoing bulk transfer */
> -	if (task_flags & UBT_FLAG_T_START_BULK) {
> -		mtx_lock(&sc->sc_if_mtx[0]);
> -		ubt_xfer_start(sc, UBT_IF_0_BULK_DT_WR);
> -		mtx_unlock(&sc->sc_if_mtx[0]);
> -	}
> -
> -	NG_NODE_UNREF(node);
> -} /* ubt_task */
> -
> -/*
> - * Start USB transfer.
> - * Helper function called from ubt_task. Must be called with appropriate
> - * interface lock held.
> - * Taskqueue context.
> - */
> -
> -static void
> -ubt_xfer_start(ubt_softc_p sc, int transfer)
> -{
> -	if (!usb2_transfer_pending(sc->sc_xfer[transfer])) {
> -		NG_NODE_REF(sc->sc_node);
> -		usb2_transfer_start(sc->sc_xfer[transfer]);
> -	}
> -} /* ubt_xfer_start */
> -
> -/****************************************************************************
> - ****************************************************************************
>   **                        Netgraph specific
>   ****************************************************************************
>   ****************************************************************************/
> @@ -1546,13 +1266,18 @@
>  static int
>  ng_ubt_shutdown(node_p node)
>  {
> +	struct ubt_softc *sc = NG_NODE_PRIVATE(node);
> +
>  	if (node->nd_flags & NGF_REALLY_DIE) {
>  		/*
>                   * We came here because the USB device is being
>  		 * detached, so stop being persistant.
>                   */
> +		UBT_LOCK(sc);
> +		sc->sc_flags |= UBT_FLAG_SHUTDOWN;
> +		UBT_UNLOCK(sc);
> +
>  		NG_NODE_SET_PRIVATE(node, NULL);
> -		NG_NODE_UNREF(node);
>  	} else
>  		NG_NODE_REVIVE(node); /* tell ng_rmnode we are persisant */
>  
> @@ -1592,9 +1317,21 @@
>  
>  	NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
>  
> -	UBT_MBUFQ_LOCK(sc);
> -	ubt_task_schedule(sc, UBT_FLAG_T_START_ALL);
> -	UBT_MBUFQ_UNLOCK(sc);
> +	if (!(sc->sc_flags & UBT_FLAG_READY)) {
> +		/* called too early */
> +		return (EINVAL);
> +	}
> +
> +	NG_NODE_REF(sc->sc_node);
> +
> +	UBT_LOCK(sc);
> +	usb2_transfer_start(sc->sc_xfer[UBT_IF_0_INTR_DT_RD]);
> +	usb2_transfer_start(sc->sc_xfer[UBT_IF_0_BULK_DT_RD]);
> +	usb2_transfer_start(sc->sc_xfer[UBT_IF_1_ISOC_DT_RD1]);
> +	usb2_transfer_start(sc->sc_xfer[UBT_IF_1_ISOC_DT_RD2]);
> +	usb2_transfer_start(sc->sc_xfer[UBT_IF_1_ISOC_DT_WR1]);
> +	usb2_transfer_start(sc->sc_xfer[UBT_IF_1_ISOC_DT_WR2]);
> +	UBT_UNLOCK(sc);
>  
>  	return (0);
>  } /* ng_ubt_connect */
> @@ -1609,6 +1346,7 @@
>  {
>  	node_p			node = NG_HOOK_NODE(hook);
>  	struct ubt_softc	*sc;
> +	uint8_t			i;
>  
>  	if (NG_NODE_NOT_VALID(node))
>  		return (0);
> @@ -1618,19 +1356,25 @@
>  	if (hook != sc->sc_hook)
>  		return (EINVAL);
>  
> +	/* 
> +	 * Synchronously drain all USB transfers:
> +	 * Can take some milliseconds!
> +	 */
> +	for (i = 0; i != UBT_N_TRANSFER; i++)
> +		usb2_transfer_drain(sc->sc_xfer[i]);
> +
>  	sc->sc_hook = NULL;
>  
> -	UBT_MBUFQ_LOCK(sc);
> +	UBT_LOCK(sc);
>  
>  	/* Drain queues */
>  	NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
>  	NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
>  	NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
>  
> -	/* Kick off task to stop all USB xfers */
> -	ubt_task_schedule(sc, UBT_FLAG_T_STOP_ALL);
> +	UBT_UNLOCK(sc);
>  
> -	UBT_MBUFQ_UNLOCK(sc);
> +	NG_NODE_UNREF(node);
>  
>  	return (0);
>  } /* ng_ubt_disconnect */
> @@ -1664,7 +1408,6 @@
>  				"Refs: %d\n" \
>  				"Hook: %s\n" \
>  				"Flags: %#x\n" \
> -				"Task flags: %#x\n" \
>  				"Debug: %d\n" \
>  				"CMD queue: [have:%d,max:%d]\n" \
>  				"ACL queue: [have:%d,max:%d]\n" \
> @@ -1672,7 +1415,6 @@
>  				node->nd_refs,
>  				(sc->sc_hook != NULL) ? NG_UBT_HOOK:"",
>  				sc->sc_flags,
> -				sc->sc_task_flags,
>  				sc->sc_debug,
>  				sc->sc_cmdq.len,
>  				sc->sc_cmdq.maxlen,
> @@ -1823,7 +1565,8 @@
>  	struct ubt_softc	*sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
>  	struct mbuf		*m;
>  	struct ng_bt_mbufq	*q;
> -	int			action, error = 0;
> +	int			error = 0;
> +	uint8_t			xfer_action;
>  
>  	if (hook != sc->sc_hook) {
>  		error = EINVAL;
> @@ -1853,7 +1596,7 @@
>  				UBT_CTRL_BUFFER_SIZE, m->m_pkthdr.len);
>  
>  		q = &sc->sc_cmdq;
> -		action = UBT_FLAG_T_START_CTRL;
> +		xfer_action = UBT_IF_0_CTRL_DT_WR;
>  		break;
>  
>  	case NG_HCI_ACL_DATA_PKT:
> @@ -1863,12 +1606,12 @@
>  				UBT_BULK_WRITE_BUFFER_SIZE, m->m_pkthdr.len);
>  
>  		q = &sc->sc_aclq;
> -		action = UBT_FLAG_T_START_BULK;
> +		xfer_action = UBT_IF_0_BULK_DT_WR;
>  		break;
>  
>  	case NG_HCI_SCO_DATA_PKT:
>  		q = &sc->sc_scoq;
> -		action = 0;
> +		xfer_action = 255;
>  		break;
>  
>  	default:
> @@ -1881,10 +1624,10 @@
>  		/* NOT REACHED */
>  	}
>  
> -	UBT_MBUFQ_LOCK(sc);
> +	UBT_LOCK(sc);
>  	if (NG_BT_MBUFQ_FULL(q)) {
>  		NG_BT_MBUFQ_DROP(q);
> -		UBT_MBUFQ_UNLOCK(sc);
> +		UBT_UNLOCK(sc);
>  		
>  		UBT_ERR(sc, "Dropping HCI frame 0x%02x, len=%d. Queue full\n",
>  			*mtod(m, uint8_t *), m->m_pkthdr.len);
> @@ -1894,9 +1637,9 @@
>  		/* Loose HCI packet type, enqueue mbuf and kick off task */
>  		m_adj(m, sizeof(uint8_t));
>  		NG_BT_MBUFQ_ENQUEUE(q, m);
> -		ubt_task_schedule(sc, action);
> -
> -		UBT_MBUFQ_UNLOCK(sc);
> +		if (xfer_action != 255)
> +			usb2_transfer_start(sc->sc_xfer[xfer_action]);
> +		UBT_UNLOCK(sc);
>  	}
>  done:
>  	NG_FREE_ITEM(item);
> @@ -1962,4 +1705,3 @@
>  MODULE_DEPEND(ng_ubt, ng_hci, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION, NG_BLUETOOTH_VERSION);
>  MODULE_DEPEND(ng_ubt, usb2_bluetooth, 1, 1, 1);
>  MODULE_DEPEND(ng_ubt, usb2_core, 1, 1, 1);
> -
> diff -u ng_ubt2_var.h ng_ubt2_var.h
> --- ng_ubt2_var.h	Wed Jan 21 17:51:04 2009
> +++ ng_ubt2_var.h	Fri Jan 23 20:08:04 2009
> @@ -28,7 +28,7 @@
>   * SUCH DAMAGE.
>   *
>   * $Id: ng_ubt_var.h,v 1.2 2003/03/22 23:44:36 max Exp $
> - * $FreeBSD$
> + * $FreeBSD: src/sys/dev/usb2/bluetooth/ng_ubt2_var.h,v 1.2 2009/01/20 22:17:05 emax Exp $
>   */
>  
>  #ifndef _NG_UBT_VAR_H_
> @@ -47,8 +47,8 @@
>  #define	UBT_WARN(...)		UBT_DEBUG(NG_UBT_WARN_LEVEL, __VA_ARGS__)
>  #define	UBT_INFO(...)		UBT_DEBUG(NG_UBT_INFO_LEVEL, __VA_ARGS__)
>  
> -#define UBT_MBUFQ_LOCK(sc)	mtx_lock(&(sc)->sc_mbufq_mtx)
> -#define UBT_MBUFQ_UNLOCK(sc)	mtx_unlock(&(sc)->sc_mbufq_mtx)
> +#define UBT_LOCK(sc)	mtx_lock(&(sc)->sc_mtx)
> +#define UBT_UNLOCK(sc)	mtx_unlock(&(sc)->sc_mtx)
>  
>  /* Bluetooth USB control request type */
>  #define	UBT_HCI_REQUEST		0x20
> @@ -65,17 +65,14 @@
>  	UBT_IF_0_BULK_CS_WR,
>  	UBT_IF_0_BULK_CS_RD,
>  	UBT_IF_0_INTR_CS_RD,
> -	UBT_IF_0_N_TRANSFER,	/* number of interface 0's transfers */
>  	
>  	/* Interface #1 transfers */
> -	UBT_IF_1_ISOC_DT_RD1 = UBT_IF_0_N_TRANSFER,
> +	UBT_IF_1_ISOC_DT_RD1,
>  	UBT_IF_1_ISOC_DT_RD2,
>  	UBT_IF_1_ISOC_DT_WR1,
>  	UBT_IF_1_ISOC_DT_WR2,
>  
>  	UBT_N_TRANSFER,		/* total number of transfers */
> -
> -	UBT_IF_1_N_TRANSFER = UBT_N_TRANSFER - UBT_IF_1_ISOC_DT_RD1,
>  };
>  
>  /* USB device softc structure */
> @@ -89,6 +86,8 @@
>  #define	UBT_FLAG_READ_STALL	(1 << 0)	/* read transfer has stalled */
>  #define	UBT_FLAG_WRITE_STALL	(1 << 1)	/* write transfer has stalled */
>  #define	UBT_FLAG_INTR_STALL	(1 << 2)	/* inter transfer has stalled */
> +#define	UBT_FLAG_READY		(1 << 4)	/* set when we are ready */
> +#define	UBT_FLAG_SHUTDOWN	(1 << 5)	/* set when we are shutdown */
>  
>  	ng_ubt_node_stat_ep	sc_stat;	/* statistic */
>  #define	UBT_STAT_PCKTS_SENT(sc)		(sc)->sc_stat.pckts_sent ++
> @@ -100,11 +99,9 @@
>  #define	UBT_STAT_RESET(sc)	bzero(&(sc)->sc_stat, sizeof((sc)->sc_stat))
>  
>  	/* USB device specific */
> -	struct mtx		sc_if_mtx[2];	/* interface locks */
> +	struct mtx		sc_mtx;
>  	struct usb2_xfer	*sc_xfer[UBT_N_TRANSFER];
>  
> -	struct mtx		sc_mbufq_mtx;	/* lock for all queues */
> -
>  	/* HCI commands */
>  	struct ng_bt_mbufq	sc_cmdq;	/* HCI command queue */
>  #define	UBT_CTRL_BUFFER_SIZE	(sizeof(struct usb2_device_request) +	\
> @@ -123,17 +120,6 @@
>  	/* Netgraph specific */
>  	node_p			sc_node;	/* pointer back to node */
>  	hook_p			sc_hook;	/* upstream hook */
> -
> -	/* Glue */
> -	int			sc_task_flags;	/* task flags */
> -#define UBT_FLAG_T_PENDING	(1 << 0)	/* task pending */
> -#define UBT_FLAG_T_STOP_ALL	(1 << 1)	/* stop all xfers */
> -#define UBT_FLAG_T_START_ALL	(1 << 2)	/* start all read and isoc
> -						   write xfers */
> -#define UBT_FLAG_T_START_CTRL	(1 << 3)	/* start control xfer (write) */
> -#define UBT_FLAG_T_START_BULK	(1 << 4)	/* start bulk xfer (write) */
> -
> -	struct task		sc_task;
>  };
>  typedef struct ubt_softc	ubt_softc_t;
>  typedef struct ubt_softc *	ubt_softc_p;


-- 
Lars Engels
E-Mail: lars.engels at 0x20.net 	
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 195 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-current/attachments/20090123/221eb5e3/attachment-0002.pgp


More information about the freebsd-current mailing list