Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb some more urtwn fixes:



details:   https://anonhg.NetBSD.org/src/rev/6ce29919babe
branches:  trunk
changeset: 784204:6ce29919babe
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Jan 21 23:42:45 2013 +0000

description:
some more urtwn fixes:
 - support manual roaming (used by wpa_supplicant)
 - simplify ioctl handler
 - add our own reset callback
 - acquire KERNEL_LOCK before using net80211 or the network stack
 - clear IFF_OACTIVE even in the event of an endpoint stall

diffstat:

 sys/dev/usb/if_urtwn.c |  90 ++++++++++++++++++++++++++-----------------------
 1 files changed, 48 insertions(+), 42 deletions(-)

diffs (223 lines):

diff -r c0340f2e95f3 -r 6ce29919babe sys/dev/usb/if_urtwn.c
--- a/sys/dev/usb/if_urtwn.c    Mon Jan 21 21:38:02 2013 +0000
+++ b/sys/dev/usb/if_urtwn.c    Mon Jan 21 23:42:45 2013 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_urtwn.c,v 1.15 2013/01/21 16:52:56 christos Exp $   */
+/*     $NetBSD: if_urtwn.c,v 1.16 2013/01/21 23:42:45 jmcneill Exp $   */
 /*     $OpenBSD: if_urtwn.c,v 1.20 2011/11/26 06:39:33 ckuethe Exp $   */
 
 /*-
@@ -22,7 +22,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.15 2013/01/21 16:52:56 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_urtwn.c,v 1.16 2013/01/21 23:42:45 jmcneill Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -243,6 +243,7 @@
 static void    urtwn_temp_calib(struct urtwn_softc *);
 static int     urtwn_init(struct ifnet *);
 static void    urtwn_stop(struct ifnet *, int);
+static int     urtwn_reset(struct ifnet *);
 static void    urtwn_chip_stop(struct urtwn_softc *);
 
 /* Aliases. */
@@ -378,7 +379,9 @@
 
        if_attach(ifp);
        ieee80211_ifattach(ic);
+
        /* override default methods */
+       ic->ic_reset = urtwn_reset;
        ic->ic_wme.wme_update = urtwn_wme_update;
 
        /* Override state transition machine. */
@@ -685,8 +688,10 @@
                cmd = &ring->cmd[ring->next];
                mutex_spin_exit(&sc->sc_task_mtx);
                splx(s);
-               /* Invoke callback. */
+               /* Invoke callback with kernel lock held. */
+               KERNEL_LOCK(1, curlwp);
                cmd->cb(sc, cmd->data);
+               KERNEL_UNLOCK_ONE(curlwp);
                s = splusb();
                mutex_spin_enter(&sc->sc_task_mtx);
                ring->queued--;
@@ -1475,14 +1480,17 @@
 urtwn_next_scan(void *arg)
 {
        struct urtwn_softc *sc = arg;
+       int s;
 
        DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
        if (sc->sc_dying)
                return;
 
+       s = splnet();
        if (sc->sc_ic.ic_state == IEEE80211_S_SCAN)
                ieee80211_next_scan(&sc->sc_ic);
+       splx(s);
 }
 
 static int
@@ -2072,7 +2080,9 @@
                }
 
                /* Process 802.11 frame. */
+               KERNEL_LOCK(1, curlwp);
                urtwn_rx_frame(sc, buf, pktlen);
+               KERNEL_UNLOCK_ONE(curlwp);
 
                /* Next chunk is 128-byte aligned. */
                totlen = roundup2(totlen, 128);
@@ -2103,23 +2113,26 @@
        TAILQ_INSERT_TAIL(&sc->tx_free_list, data, next);
        mutex_exit(&sc->sc_tx_mtx);
 
+       s = splnet();
+       sc->tx_timer = 0;
+       ifp->if_flags &= ~IFF_OACTIVE;
+       ifp->if_opackets++;
+
        if (__predict_false(status != USBD_NORMAL_COMPLETION)) {
                if (status != USBD_NOT_STARTED && status != USBD_CANCELLED) {
                        if (status == USBD_STALLED)
                                usbd_clear_endpoint_stall_async(data->pipe);
                        ifp->if_oerrors++;
                }
+               splx(s);
                return;
        }
 
-       ifp->if_opackets++;
-
-       s = splnet();
-       sc->tx_timer = 0;
-       ifp->if_flags &= ~IFF_OACTIVE;
+       KERNEL_LOCK(1, curlwp);
+       urtwn_start(ifp);
+       KERNEL_UNLOCK_ONE(curlwp);
+
        splx(s);
-
-       urtwn_start(ifp);
 }
 
 static int
@@ -2415,7 +2428,6 @@
 {
        struct urtwn_softc *sc = ifp->if_softc;
        struct ieee80211com *ic = &sc->sc_ic;
-       struct ifaddr *ifa;
        int s, error = 0;
 
        DPRINTFN(DBG_FN, ("%s: %s: cmd=0x%08lx, data=%p\n",
@@ -2424,14 +2436,6 @@
        s = splnet();
 
        switch (cmd) {
-       case SIOCSIFADDR:
-               ifa = (struct ifaddr *)data;
-               ifp->if_flags |= IFF_UP;
-#ifdef INET
-               if (ifa->ifa_addr->sa_family == AF_INET)
-                       arp_ifinit(ifp, ifa);
-#endif
-               /*FALLTHROUGH*/
        case SIOCSIFFLAGS:
                if ((error = ifioctl_common(ifp, cmd, data)) != 0)
                        break;
@@ -2457,28 +2461,14 @@
                }
                break;
 
-       case SIOCS80211CHANNEL:
-               error = ieee80211_ioctl(ic, cmd, data);
-               if (error == ENETRESET &&
-                   ic->ic_opmode == IEEE80211_M_MONITOR) {
-                       if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
-                           (IFF_UP | IFF_RUNNING)) {
-                               mutex_enter(&sc->sc_write_mtx);
-                               urtwn_set_chan(sc, ic->ic_curchan,
-                                   IEEE80211_HTINFO_2NDCHAN_NONE);
-                               mutex_exit(&sc->sc_write_mtx);
-                       }
-                       error = 0;
-               }
-               break;
-
        default:
                error = ieee80211_ioctl(ic, cmd, data);
                break;
        }
        if (error == ENETRESET) {
                if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) ==
-                   (IFF_UP | IFF_RUNNING)) {
+                   (IFF_UP | IFF_RUNNING) &&
+                   ic->ic_roaming != IEEE80211_ROAMING_MANUAL) {
                        urtwn_init(ifp);
                }
                error = 0;
@@ -3805,12 +3795,14 @@
        ifp->if_flags &= ~IFF_OACTIVE;
        ifp->if_flags |= IFF_RUNNING;
 
+       mutex_exit(&sc->sc_write_mtx);
+
        if (ic->ic_opmode == IEEE80211_M_MONITOR)
                ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
-       else
+       else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
                ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-
-       mutex_exit(&sc->sc_write_mtx);
+       urtwn_wait_async(sc);
+
        return (0);
 
  fail:
@@ -3829,15 +3821,15 @@
 
        DPRINTFN(DBG_FN, ("%s: %s\n", device_xname(sc->sc_dev), __func__));
 
-       sc->tx_timer = 0;
-       ifp->if_timer = 0;
-       ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-
        s = splusb();
        ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
        urtwn_wait_async(sc);
        splx(s);
 
+       sc->tx_timer = 0;
+       ifp->if_timer = 0;
+       ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+
        callout_stop(&sc->sc_scan_to);
        callout_stop(&sc->sc_calib_to);
 
@@ -3858,6 +3850,20 @@
                urtwn_chip_stop(sc);
 }
 
+static int
+urtwn_reset(struct ifnet *ifp)
+{
+       struct urtwn_softc *sc = ifp->if_softc;
+       struct ieee80211com *ic = &sc->sc_ic;
+
+       if (ic->ic_opmode != IEEE80211_M_MONITOR)
+               return ENETRESET;
+
+       urtwn_set_chan(sc, ic->ic_curchan, IEEE80211_HTINFO_2NDCHAN_NONE);
+
+       return 0;
+}
+
 static void
 urtwn_chip_stop(struct urtwn_softc *sc)
 {



Home | Main Index | Thread Index | Old Index