svn commit: r314923 - head/sys/dev/iwn
Andriy Voskoboinyk
avos at FreeBSD.org
Wed Mar 8 22:49:23 UTC 2017
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 *,
More information about the svn-src-head
mailing list