Date: Wed, 8 Mar 2017 22:49:22 +0000 (UTC) From: Andriy Voskoboinyk <avos@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r314923 - head/sys/dev/iwn Message-ID: <201703082249.v28MnMlc096658@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: avos Date: Wed Mar 8 22:49:22 2017 New Revision: 314923 URL: https://svnweb.freebsd.org/changeset/base/314923 Log: iwn: add promiscuous mode support. Tested with Intel 6205, STA / MONITOR modes. Modified: head/sys/dev/iwn/if_iwn.c head/sys/dev/iwn/if_iwnreg.h head/sys/dev/iwn/if_iwnvar.h Modified: head/sys/dev/iwn/if_iwn.c ============================================================================== --- head/sys/dev/iwn/if_iwn.c Wed Mar 8 22:39:45 2017 (r314922) +++ head/sys/dev/iwn/if_iwn.c Wed Mar 8 22:49:22 2017 (r314923) @@ -249,6 +249,8 @@ static int iwn_set_link_quality(struct i struct ieee80211_node *); static int iwn_add_broadcast_node(struct iwn_softc *, int); static int iwn_updateedca(struct ieee80211com *); +static void iwn_set_promisc(struct iwn_softc *); +static void iwn_update_promisc(struct ieee80211com *); static void iwn_update_mcast(struct ieee80211com *); static void iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t); static int iwn_set_critical_temp(struct iwn_softc *); @@ -278,6 +280,9 @@ static int iwn_set_pslevel(struct iwn_so static int iwn_send_btcoex(struct iwn_softc *); static int iwn_send_advanced_btcoex(struct iwn_softc *); static int iwn5000_runtime_calib(struct iwn_softc *); +static int iwn_check_bss_filter(struct iwn_softc *); +static int iwn4965_rxon_assoc(struct iwn_softc *, int); +static int iwn5000_rxon_assoc(struct iwn_softc *, int); static int iwn_send_rxon(struct iwn_softc *, int, int); static int iwn_config(struct iwn_softc *); static int iwn_scan(struct iwn_softc *, struct ieee80211vap *, @@ -662,6 +667,7 @@ iwn_attach(device_t dev) ic->ic_addba_stop = iwn_ampdu_tx_stop; ic->ic_newassoc = iwn_newassoc; ic->ic_wme.wme_update = iwn_updateedca; + ic->ic_update_promisc = iwn_update_promisc; ic->ic_update_mcast = iwn_update_mcast; ic->ic_scan_start = iwn_scan_start; ic->ic_scan_end = iwn_scan_end; @@ -1227,6 +1233,7 @@ iwn4965_attach(struct iwn_softc *sc, uin ops->set_txpower = iwn4965_set_txpower; ops->init_gains = iwn4965_init_gains; ops->set_gains = iwn4965_set_gains; + ops->rxon_assoc = iwn4965_rxon_assoc; ops->add_node = iwn4965_add_node; ops->tx_done = iwn4965_tx_done; ops->ampdu_tx_start = iwn4965_ampdu_tx_start; @@ -1271,6 +1278,7 @@ iwn5000_attach(struct iwn_softc *sc, uin ops->set_txpower = iwn5000_set_txpower; ops->init_gains = iwn5000_init_gains; ops->set_gains = iwn5000_set_gains; + ops->rxon_assoc = iwn5000_rxon_assoc; ops->add_node = iwn5000_add_node; ops->tx_done = iwn5000_tx_done; ops->ampdu_tx_start = iwn5000_ampdu_tx_start; @@ -5428,6 +5436,43 @@ iwn_updateedca(struct ieee80211com *ic) } static void +iwn_set_promisc(struct iwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t promisc_filter; + + promisc_filter = IWN_FILTER_CTL | IWN_FILTER_PROMISC; + if (ic->ic_promisc > 0 || ic->ic_opmode == IEEE80211_M_MONITOR) + sc->rxon->filter |= htole32(promisc_filter); + else + sc->rxon->filter &= ~htole32(promisc_filter); +} + +static void +iwn_update_promisc(struct ieee80211com *ic) +{ + struct iwn_softc *sc = ic->ic_softc; + int error; + + if (ic->ic_opmode == IEEE80211_M_MONITOR) + return; /* nothing to do */ + + IWN_LOCK(sc); + if (!(sc->sc_flags & IWN_FLAG_RUNNING)) { + IWN_UNLOCK(sc); + return; + } + + iwn_set_promisc(sc); + if ((error = iwn_send_rxon(sc, 1, 1)) != 0) { + device_printf(sc->sc_dev, + "%s: could not send RXON, error %d\n", + __func__, error); + } + IWN_UNLOCK(sc); +} + +static void iwn_update_mcast(struct ieee80211com *ic) { /* Ignore */ @@ -6535,6 +6580,52 @@ iwn_get_rxon_ht_flags(struct iwn_softc * } static int +iwn_check_bss_filter(struct iwn_softc *sc) +{ + return ((sc->rxon->filter & htole32(IWN_FILTER_BSS)) != 0); +} + +static int +iwn4965_rxon_assoc(struct iwn_softc *sc, int async) +{ + struct iwn4965_rxon_assoc cmd; + struct iwn_rxon *rxon = sc->rxon; + + cmd.flags = rxon->flags; + cmd.filter = rxon->filter; + cmd.ofdm_mask = rxon->ofdm_mask; + cmd.cck_mask = rxon->cck_mask; + cmd.ht_single_mask = rxon->ht_single_mask; + cmd.ht_dual_mask = rxon->ht_dual_mask; + cmd.rxchain = rxon->rxchain; + cmd.reserved = 0; + + return (iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &cmd, sizeof(cmd), async)); +} + +static int +iwn5000_rxon_assoc(struct iwn_softc *sc, int async) +{ + struct iwn5000_rxon_assoc cmd; + struct iwn_rxon *rxon = sc->rxon; + + cmd.flags = rxon->flags; + cmd.filter = rxon->filter; + cmd.ofdm_mask = rxon->ofdm_mask; + cmd.cck_mask = rxon->cck_mask; + cmd.reserved1 = 0; + cmd.ht_single_mask = rxon->ht_single_mask; + cmd.ht_dual_mask = rxon->ht_dual_mask; + cmd.ht_triple_mask = rxon->ht_triple_mask; + cmd.reserved2 = 0; + cmd.rxchain = rxon->rxchain; + cmd.acquisition = rxon->acquisition; + cmd.reserved3 = 0; + + return (iwn_cmd(sc, IWN_CMD_RXON_ASSOC, &cmd, sizeof(cmd), async)); +} + +static int iwn_send_rxon(struct iwn_softc *sc, int assoc, int async) { struct iwn_ops *ops = &sc->ops; @@ -6542,33 +6633,46 @@ iwn_send_rxon(struct iwn_softc *sc, int IWN_LOCK_ASSERT(sc); - if (sc->sc_is_scanning) - device_printf(sc->sc_dev, - "%s: is_scanning set, before RXON\n", - __func__); - error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, async); - if (error != 0) { - device_printf(sc->sc_dev, "%s: RXON command failed\n", - __func__); - return (error); - } + if (assoc && iwn_check_bss_filter(sc) != 0) { + error = ops->rxon_assoc(sc, async); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: RXON_ASSOC command failed, error %d\n", + __func__, error); + return (error); + } + } else { + if (sc->sc_is_scanning) + device_printf(sc->sc_dev, + "%s: is_scanning set, before RXON\n", + __func__); - /* - * Reconfiguring RXON clears the firmware nodes table so we must - * add the broadcast node again. - */ - if ((sc->rxon->filter & htole32(IWN_FILTER_BSS)) == 0) { - if ((error = iwn_add_broadcast_node(sc, async)) != 0) { + error = iwn_cmd(sc, IWN_CMD_RXON, sc->rxon, sc->rxonsz, async); + if (error != 0) { device_printf(sc->sc_dev, - "%s: could not add broadcast node\n", __func__); + "%s: RXON command failed, error %d\n", + __func__, error); + return (error); + } + + /* + * Reconfiguring RXON clears the firmware nodes table so + * we must add the broadcast node again. + */ + if (iwn_check_bss_filter(sc) == 0 && + (error = iwn_add_broadcast_node(sc, async)) != 0) { + device_printf(sc->sc_dev, + "%s: could not add broadcast node, error %d\n", + __func__, error); return (error); } } /* Configuration has changed, set TX power accordingly. */ if ((error = ops->set_txpower(sc, async)) != 0) { - device_printf(sc->sc_dev, "%s: could not set TX power\n", - __func__); + device_printf(sc->sc_dev, + "%s: could not set TX power, error %d\n", + __func__, error); return (error); } @@ -6669,20 +6773,20 @@ iwn_config(struct iwn_softc *sc) sc->rxon->flags = htole32(IWN_RXON_TSF | IWN_RXON_CTS_TO_SELF); if (IEEE80211_IS_CHAN_2GHZ(ic->ic_curchan)) sc->rxon->flags |= htole32(IWN_RXON_AUTO | IWN_RXON_24GHZ); + + sc->rxon->filter = htole32(IWN_FILTER_MULTICAST); switch (ic->ic_opmode) { case IEEE80211_M_STA: sc->rxon->mode = IWN_MODE_STA; - sc->rxon->filter = htole32(IWN_FILTER_MULTICAST); break; case IEEE80211_M_MONITOR: sc->rxon->mode = IWN_MODE_MONITOR; - sc->rxon->filter = htole32(IWN_FILTER_MULTICAST | - IWN_FILTER_CTL | IWN_FILTER_PROMISC); break; default: /* Should not get there. */ break; } + iwn_set_promisc(sc); sc->rxon->cck_mask = 0x0f; /* not yet negotiated */ sc->rxon->ofdm_mask = 0xff; /* not yet negotiated */ sc->rxon->ht_single_mask = 0xff; Modified: head/sys/dev/iwn/if_iwnreg.h ============================================================================== --- head/sys/dev/iwn/if_iwnreg.h Wed Mar 8 22:39:45 2017 (r314922) +++ head/sys/dev/iwn/if_iwnreg.h Wed Mar 8 22:49:22 2017 (r314923) @@ -617,6 +617,34 @@ struct iwn_rxon { #define IWN4965_RXONSZ (sizeof (struct iwn_rxon) - 6) #define IWN5000_RXONSZ (sizeof (struct iwn_rxon)) +/* Structure for command IWN_CMD_RXON_ASSOC (4965AGN only.) */ +struct iwn4965_rxon_assoc { + uint32_t flags; + uint32_t filter; + uint8_t ofdm_mask; + uint8_t cck_mask; + uint8_t ht_single_mask; + uint8_t ht_dual_mask; + uint16_t rxchain; + uint16_t reserved; +} __packed; + +/* Structure for command IWN_CMD_RXON_ASSOC (5000 Series only.) */ +struct iwn5000_rxon_assoc { + uint32_t flags; + uint32_t filter; + uint8_t ofdm_mask; + uint8_t cck_mask; + uint16_t reserved1; + uint8_t ht_single_mask; + uint8_t ht_dual_mask; + uint8_t ht_triple_mask; + uint8_t reserved2; + uint16_t rxchain; + uint16_t acquisition; + uint32_t reserved3; +} __packed; + /* Structure for command IWN_CMD_ASSOCIATE. */ struct iwn_assoc { uint32_t flags; Modified: head/sys/dev/iwn/if_iwnvar.h ============================================================================== --- head/sys/dev/iwn/if_iwnvar.h Wed Mar 8 22:39:45 2017 (r314922) +++ head/sys/dev/iwn/if_iwnvar.h Wed Mar 8 22:49:22 2017 (r314923) @@ -209,6 +209,7 @@ struct iwn_ops { int (*set_txpower)(struct iwn_softc *, int); int (*init_gains)(struct iwn_softc *); int (*set_gains)(struct iwn_softc *); + int (*rxon_assoc)(struct iwn_softc *, int); int (*add_node)(struct iwn_softc *, struct iwn_node_info *, int); void (*tx_done)(struct iwn_softc *, struct iwn_rx_desc *,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703082249.v28MnMlc096658>