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 > _at__at_ -28,7 +28,7 _at__at_ > * 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 $ > */ > > /* > _at__at_ -37,22 +37,12 _at__at_ > * 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 > _at__at_ -67,26 +57,6 _at__at_ > * 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 > _at__at_ -111,7 +81,6 _at__at_ > #include <dev/usb2/core/usb2_transfer.h> > > #include <sys/mbuf.h> > -#include <sys/taskqueue.h> > > #include <netgraph/ng_message.h> > #include <netgraph/netgraph.h> > _at__at_ -128,10 +97,6 _at__at_ > 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; > _at__at_ -279,6 +244,7 _at__at_ > .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, > _at__at_ -288,6 +254,7 _at__at_ > .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, > _at__at_ -297,6 +264,7 _at__at_ > .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, > _at__at_ -306,6 +274,7 _at__at_ > .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 */ > _at__at_ -315,6 +284,7 _at__at_ > .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 */ > _at__at_ -325,6 +295,7 _at__at_ > .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 */ > _at__at_ -338,6 +309,7 _at__at_ > .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 */ > _at__at_ -353,6 +325,7 _at__at_ > .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, }, > _at__at_ -363,6 +336,7 _at__at_ > .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, }, > _at__at_ -373,6 +347,7 _at__at_ > .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, }, > _at__at_ -383,6 +358,7 _at__at_ > .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, }, > _at__at_ -450,7 +426,8 _at__at_ > 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); > > _at__at_ -483,28 +460,22 _at__at_ > > /* 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 > _at__at_ -520,20 +491,11 _at__at_ > * 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 > _at__at_ -580,13 +542,11 _at__at_ > 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; > } > > _at__at_ -594,6 +554,10 _at__at_ > 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: > _at__at_ -612,17 +576,33 _at__at_ > { > 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); > > _at__at_ -630,15 +610,13 _at__at_ > 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 */ > _at__at_ -657,37 +635,25 _at__at_ > 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 */ > _at__at_ -719,8 +685,6 _at__at_ > UBT_STAT_OERROR(sc); > goto send_next; > } > - > - NG_NODE_UNREF(node); /* cancelled */ > break; > } > } /* ubt_ctrl_write_callback */ > _at__at_ -740,19 +704,8 _at__at_ > 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)) { > _at__at_ -836,8 +789,7 _at__at_ > /* 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 */ > _at__at_ -855,11 +807,6 _at__at_ > 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]; > > _at__at_ -867,8 +814,7 _at__at_ > 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 */ > > /* > _at__at_ -887,19 +833,7 _at__at_ > 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)) { > _at__at_ -983,8 +917,7 _at__at_ > /* 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 */ > _at__at_ -1002,11 +935,6 _at__at_ > 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]; > > _at__at_ -1014,8 +942,7 _at__at_ > 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 */ > > /* > _at__at_ -1031,36 +958,24 _at__at_ > 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; > } > > /* > _at__at_ -1089,8 +1004,7 _at__at_ > /* 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 */ > _at__at_ -1108,11 +1022,6 _at__at_ > 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]; > > _at__at_ -1120,8 +1029,7 _at__at_ > 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 */ > > /* > _at__at_ -1137,19 +1045,8 _at__at_ > 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 ++) > _at__at_ -1171,8 +1068,6 _at__at_ > goto read_next; > /* NOT REACHED */ > } > - > - NG_NODE_UNREF(node); /* cancelled */ > break; > } > } /* ubt_isoc_read_callback */ > _at__at_ -1277,24 +1172,16 _at__at_ > 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: > _at__at_ -1305,10 +1192,7 _at__at_ > > 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; > } > _at__at_ -1328,9 +1212,7 _at__at_ > > /* 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); > } > > /* > _at__at_ -1355,174 +1237,12 _at__at_ > 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 > **************************************************************************** > ****************************************************************************/ > _at__at_ -1546,13 +1266,18 _at__at_ > 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 */ > > _at__at_ -1592,9 +1317,21 _at__at_ > > 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 */ > _at__at_ -1609,6 +1346,7 _at__at_ > { > node_p node = NG_HOOK_NODE(hook); > struct ubt_softc *sc; > + uint8_t i; > > if (NG_NODE_NOT_VALID(node)) > return (0); > _at__at_ -1618,19 +1356,25 _at__at_ > 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 */ > _at__at_ -1664,7 +1408,6 _at__at_ > "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" \ > _at__at_ -1672,7 +1415,6 _at__at_ > 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, > _at__at_ -1823,7 +1565,8 _at__at_ > 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; > _at__at_ -1853,7 +1596,7 _at__at_ > 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: > _at__at_ -1863,12 +1606,12 _at__at_ > 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: > _at__at_ -1881,10 +1624,10 _at__at_ > /* 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); > _at__at_ -1894,9 +1637,9 _at__at_ > /* 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); > _at__at_ -1962,4 +1705,3 _at__at_ > 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 > _at__at_ -28,7 +28,7 _at__at_ > * 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_ > _at__at_ -47,8 +47,8 _at__at_ > #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 > _at__at_ -65,17 +65,14 _at__at_ > 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 */ > _at__at_ -89,6 +86,8 _at__at_ > #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 ++ > _at__at_ -100,11 +99,9 _at__at_ > #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) + \ > _at__at_ -123,17 +120,6 _at__at_ > /* 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
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:40 UTC