The athn(4) USB driver supports dual-band and uses the same broken pattern
as run(4). See http://marc.info/?l=openbsd-tech&m=143660130627359&w=2

Index: if_athn_usb.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_athn_usb.c,v
retrieving revision 1.35
diff -u -p -r1.35 if_athn_usb.c
--- if_athn_usb.c       9 Jul 2015 13:48:54 -0000       1.35
+++ if_athn_usb.c       11 Jul 2015 08:07:22 -0000
@@ -570,16 +570,20 @@ athn_usb_task(void *arg)
        struct athn_usb_softc *usc = arg;
        struct athn_usb_host_cmd_ring *ring = &usc->cmdq;
        struct athn_usb_host_cmd *cmd;
-       int s;
+       int s, generation;
 
        /* Process host commands. */
        s = splusb();
+       generation = ring->generation;
        while (ring->next != ring->cur) {
                cmd = &ring->cmd[ring->next];
                splx(s);
                /* Invoke callback. */
                cmd->cb(usc, cmd->data);
                s = splusb();
+               /* Abort this task if interface was stopped meanwhile. */
+               if (generation != ring->generation)
+                       break;
                ring->queued--;
                ring->next = (ring->next + 1) % ATHN_USB_HOST_CMD_RING_COUNT;
        }
@@ -594,12 +598,12 @@ athn_usb_do_async(struct athn_usb_softc 
        struct athn_usb_host_cmd *cmd;
        int s;
 
+       s = splusb();
        if (ring->queued == ATHN_USB_HOST_CMD_RING_COUNT) {
                printf("%s: host cmd queue overrun\n", usc->usb_dev.dv_xname);
+               splx(s);
                return; /* XXX */
        }
-       
-       s = splusb();
        cmd = &ring->cmd[ring->cur];
        cmd->cb = cb;
        KASSERT(len <= sizeof(cmd->data));
@@ -2365,6 +2369,10 @@ athn_usb_stop(struct ifnet *ifp)
        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 
        s = splusb();
+
+       /* Abort athn_usb_task thread. */
+       usc->cmdq.generation++;
+
        ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 
        /* Wait for all async commands to complete. */
Index: if_athn_usb.h
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_athn_usb.h,v
retrieving revision 1.6
diff -u -p -r1.6 if_athn_usb.h
--- if_athn_usb.h       2 Mar 2015 14:46:02 -0000       1.6
+++ if_athn_usb.h       11 Jul 2015 08:04:25 -0000
@@ -412,6 +412,7 @@ struct athn_usb_host_cmd_ring {
        int                             cur;
        int                             next;
        int                             queued;
+       int                             generation;
 };
 
 struct athn_usb_softc {

Reply via email to