Author: bschmidt
Date: Tue Oct 12 16:52:13 2010
New Revision: 213729
URL: http://svn.freebsd.org/changeset/base/213729

Log:
  Fix monitor mode which is implemented by doing a firmware scan. This
  is a port of stable/6, seems like the code got lost during the
  background scan changes in r170530.
  
  Pointed out by:       danfe
  MFC after:    2 weeks

Modified:
  head/sys/dev/iwi/if_iwi.c
  head/sys/dev/iwi/if_iwivar.h

Modified: head/sys/dev/iwi/if_iwi.c
==============================================================================
--- head/sys/dev/iwi/if_iwi.c   Tue Oct 12 16:23:50 2010        (r213728)
+++ head/sys/dev/iwi/if_iwi.c   Tue Oct 12 16:52:13 2010        (r213729)
@@ -180,6 +180,7 @@ static void iwi_release_fw_dma(struct iw
 static int     iwi_config(struct iwi_softc *);
 static int     iwi_get_firmware(struct iwi_softc *, enum ieee80211_opmode);
 static void    iwi_put_firmware(struct iwi_softc *);
+static void    iwi_monitor_scan(void *, int);
 static int     iwi_scanchan(struct iwi_softc *, unsigned long, int);
 static void    iwi_scan_start(struct ieee80211com *);
 static void    iwi_scan_end(struct ieee80211com *);
@@ -292,6 +293,7 @@ iwi_attach(device_t dev)
        TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc);
        TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc);
        TASK_INIT(&sc->sc_wmetask, 0, iwi_update_wme, sc);
+       TASK_INIT(&sc->sc_monitortask, 0, iwi_monitor_scan, sc);
 
        callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
        callout_init_mtx(&sc->sc_rftimer, &sc->sc_mtx, 0);
@@ -460,6 +462,7 @@ iwi_detach(device_t dev)
        ieee80211_draintask(ic, &sc->sc_radiofftask);
        ieee80211_draintask(ic, &sc->sc_restarttask);
        ieee80211_draintask(ic, &sc->sc_disassoctask);
+       ieee80211_draintask(ic, &sc->sc_monitortask);
 
        iwi_stop(sc);
 
@@ -988,7 +991,8 @@ iwi_newstate(struct ieee80211vap *vap, e
                         * This is all totally bogus and needs to be redone.
                         */
                        iwi_auth_and_assoc(sc, vap);
-               }
+               } else if (vap->iv_opmode == IEEE80211_M_MONITOR)
+                       ieee80211_runtask(ic, &sc->sc_monitortask);
                break;
        case IEEE80211_S_ASSOC:
                /*
@@ -1407,6 +1411,18 @@ iwi_notification_intr(struct iwi_softc *
 
                IWI_STATE_END(sc, IWI_FW_SCANNING);
 
+               /*
+                * Monitor mode works by doing a passive scan to set
+                * the channel and enable rx.  Because we don't want
+                * to abort a scan lest the firmware crash we scan
+                * for a short period of time and automatically restart
+                * the scan when notified the sweep has completed.
+                */
+               if (vap->iv_opmode == IEEE80211_M_MONITOR) {
+                       ieee80211_runtask(ic, &sc->sc_monitortask);
+                       break;
+               }
+
                if (scan->status == IWI_SCAN_COMPLETED) {
                        /* NB: don't need to defer, net80211 does it for us */
                        ieee80211_scan_next(vap);
@@ -2557,6 +2573,11 @@ iwi_config(struct iwi_softc *sc)
        config.answer_pbreq = (ic->ic_opmode == IEEE80211_M_IBSS) ? 1 : 0;
        config.disable_unicast_decryption = 1;
        config.disable_multicast_decryption = 1;
+       if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+               config.allow_invalid_frames = 1;
+               config.allow_beacon_and_probe_resp = 1;
+               config.allow_mgt = 1;
+       }
        DPRINTF(("Configuring adapter\n"));
        error = iwi_cmd(sc, IWI_CMD_SET_CONFIG, &config, sizeof config);
        if (error != 0)
@@ -2642,6 +2663,17 @@ scan_band(const struct ieee80211_channel
        return IEEE80211_IS_CHAN_5GHZ(c) ?  IWI_CHAN_5GHZ : IWI_CHAN_2GHZ;
 }
 
+static void
+iwi_monitor_scan(void *arg, int npending)
+{
+       struct iwi_softc *sc = arg;
+       IWI_LOCK_DECL;
+
+       IWI_LOCK(sc);
+       (void) iwi_scanchan(sc, 2000, 0);
+       IWI_UNLOCK(sc);
+}
+
 /*
  * Start a scan on the current channel or all channels.
  */

Modified: head/sys/dev/iwi/if_iwivar.h
==============================================================================
--- head/sys/dev/iwi/if_iwivar.h        Tue Oct 12 16:23:50 2010        
(r213728)
+++ head/sys/dev/iwi/if_iwivar.h        Tue Oct 12 16:52:13 2010        
(r213729)
@@ -193,6 +193,7 @@ struct iwi_softc {
        struct task             sc_restarttask; /* restart adapter processing */
        struct task             sc_disassoctask;
        struct task             sc_wmetask;     /* set wme parameters */
+       struct task             sc_monitortask;
 
        unsigned int            sc_softled : 1, /* enable LED gpio status */
                                sc_ledstate: 1, /* LED on/off state */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to