summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfei feng - Sun Microsystems - Beijing China <Fei.Feng@Sun.COM>2009-01-21 16:12:41 +0800
committerfei feng - Sun Microsystems - Beijing China <Fei.Feng@Sun.COM>2009-01-21 16:12:41 +0800
commit19d332fefbc61327bb6187d0eb818629f3b52c6f (patch)
tree472cb58f2a10d0f88b1181c06d8d89db3b13f74d
parent396fd709aa98a97b29636b0f9b6c4860c8bc37aa (diff)
downloadillumos-joyent-19d332fefbc61327bb6187d0eb818629f3b52c6f.tar.gz
6774031 iwk driver needs to support Ad-Hoc networking
-rw-r--r--usr/src/uts/common/io/iwk/iwk2.c808
-rw-r--r--usr/src/uts/common/io/iwk/iwk2_var.h25
-rw-r--r--usr/src/uts/common/io/net80211/net80211_input.c41
-rw-r--r--usr/src/uts/common/io/net80211/net80211_ioctl.c78
-rw-r--r--usr/src/uts/common/io/net80211/net80211_node.c10
-rw-r--r--usr/src/uts/common/io/net80211/net80211_output.c24
-rw-r--r--usr/src/uts/common/io/net80211/net80211_proto.c127
7 files changed, 965 insertions, 148 deletions
diff --git a/usr/src/uts/common/io/iwk/iwk2.c b/usr/src/uts/common/io/iwk/iwk2.c
index 6c3b147b4f..0abbd91775 100644
--- a/usr/src/uts/common/io/iwk/iwk2.c
+++ b/usr/src/uts/common/io/iwk/iwk2.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -308,6 +308,8 @@ static int iwk_rx_sens_init(iwk_sc_t *sc);
static int iwk_rx_sens(iwk_sc_t *sc);
static int iwk_cck_sens(iwk_sc_t *sc, uint32_t actual_rx_time);
static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time);
+static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
+ struct ieee80211_node *in, int subtype, int rssi, uint32_t rstamp);
static void iwk_write_event_log(iwk_sc_t *);
static void iwk_write_error_log(iwk_sc_t *);
@@ -335,6 +337,11 @@ static int iwk_m_getprop(void *arg, const char *pr_name,
static void iwk_destroy_locks(iwk_sc_t *sc);
static int iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type);
static void iwk_thread(iwk_sc_t *sc);
+static int iwk_run_state_config_ibss(ieee80211com_t *ic);
+static int iwk_run_state_config_sta(ieee80211com_t *ic);
+static int iwk_start_tx_beacon(ieee80211com_t *ic);
+static int iwk_clean_add_node_ibss(struct ieee80211com *ic,
+ uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2);
/*
* Supported rates for 802.11b/g modes (in 500Kbps unit).
@@ -561,6 +568,8 @@ iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
DDI_INTR_PRI(sc->sc_intr_pri));
mutex_init(&sc->sc_mt_lock, NULL, MUTEX_DRIVER,
DDI_INTR_PRI(sc->sc_intr_pri));
+ mutex_init(&sc->sc_ibss.node_tb_lock, NULL, MUTEX_DRIVER,
+ DDI_INTR_PRI(sc->sc_intr_pri));
cv_init(&sc->sc_fw_cv, NULL, CV_DRIVER, NULL);
cv_init(&sc->sc_cmd_cv, NULL, CV_DRIVER, NULL);
@@ -651,6 +660,10 @@ iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
* Support WPA/WPA2
*/
ic->ic_caps |= IEEE80211_C_WPA;
+ /*
+ * support Adhoc mode
+ */
+ ic->ic_caps |= IEEE80211_C_IBSS;
/* set supported .11b and .11g rates */
ic->ic_sup_rates[IEEE80211_MODE_11B] = iwk_rateset_11b;
@@ -665,6 +678,7 @@ iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ |
IEEE80211_CHAN_PASSIVE;
}
+ ic->ic_ibss_chan = &ic->ic_sup_channels[0];
ic->ic_xmit = iwk_send;
/*
@@ -685,6 +699,7 @@ iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
sc->sc_newstate = ic->ic_newstate;
ic->ic_newstate = iwk_newstate;
sc->sc_recv_mgmt = ic->ic_recv_mgmt;
+ ic->ic_recv_mgmt = iwk_recv_mgmt;
ic->ic_node_alloc = iwk_node_alloc;
ic->ic_node_free = iwk_node_free;
ic->ic_crypto.cs_key_set = iwk_key_set;
@@ -727,7 +742,7 @@ iwk_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_macaddr);
macp = mac_alloc(MAC_VERSION);
- if (err != DDI_SUCCESS) {
+ if (macp == NULL) {
cmn_err(CE_WARN,
"iwk_attach(): failed to do mac_alloc()\n");
goto attach_fail9;
@@ -1620,48 +1635,30 @@ iwk_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
}
IWK_DBG((IWK_DEBUG_80211, "iwk: associated."));
- /* none IBSS mode */
- if (ic->ic_opmode != IEEE80211_M_IBSS) {
- /* update adapter's configuration */
- if (sc->sc_assoc_id != in->in_associd) {
- cmn_err(CE_WARN,
- "associate ID mismatch: expected %d, "
- "got %d\n",
- in->in_associd, sc->sc_assoc_id);
- }
- sc->sc_config.assoc_id = in->in_associd & 0x3fff;
+ /* IBSS mode */
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
/*
- * short preamble/slot time are
- * negotiated when associating
+ * clean all nodes in ibss node table
+ * in order to be consistent with hardware
*/
- sc->sc_config.flags &=
- ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
- RXON_FLG_SHORT_SLOT_MSK);
-
- if (ic->ic_flags & IEEE80211_F_SHSLOT)
- sc->sc_config.flags |=
- LE_32(RXON_FLG_SHORT_SLOT_MSK);
-
- if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- sc->sc_config.flags |=
- LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
-
- sc->sc_config.filter_flags |=
- LE_32(RXON_FILTER_ASSOC_MSK);
-
- if (ic->ic_opmode != IEEE80211_M_STA)
- sc->sc_config.filter_flags |=
- LE_32(RXON_FILTER_BCON_AWARE_MSK);
+ err = iwk_run_state_config_ibss(ic);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_newstate(): "
+ "failed to update configuration "
+ "in IBSS mode\n");
+ mutex_exit(&sc->sc_glock);
+ return (err);
+ }
+ }
- IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x"
- " filter_flags %x\n",
- sc->sc_config.chan, sc->sc_config.flags,
- sc->sc_config.filter_flags));
- err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
- sizeof (iwk_rxon_cmd_t), 1);
+ /* none IBSS mode */
+ if (ic->ic_opmode != IEEE80211_M_IBSS) {
+ /* update adapter's configuration */
+ err = iwk_run_state_config_sta(ic);
if (err != IWK_SUCCESS) {
- cmn_err(CE_WARN, "could not update "
- "configuration\n");
+ cmn_err(CE_WARN, "iwk_newstate(): "
+ "failed to update configuration "
+ "in none IBSS mode\n");
mutex_exit(&sc->sc_glock);
return (err);
}
@@ -1678,9 +1675,24 @@ iwk_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
if (err) {
cmn_err(CE_WARN, "iwk_newstate(): "
"failed to set tx power table\n");
+ mutex_exit(&sc->sc_glock);
return (err);
}
+ if (ic->ic_opmode == IEEE80211_M_IBSS) {
+
+ /*
+ * allocate and transmit beacon frames
+ */
+ err = iwk_start_tx_beacon(ic);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_newstate(): "
+ "can't transmit beacon frames\n");
+ mutex_exit(&sc->sc_glock);
+ return (err);
+ }
+ }
+
/* start automatic rate control */
mutex_enter(&sc->sc_mt_lock);
if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
@@ -1758,6 +1770,7 @@ static int iwk_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
iwk_sc_t *sc = (iwk_sc_t *)ic;
iwk_add_sta_t node;
int err;
+ uint8_t index1;
switch (k->wk_cipher->ic_cipher) {
case IEEE80211_CIPHER_WEP:
@@ -1778,6 +1791,66 @@ static int iwk_key_set(ieee80211com_t *ic, const struct ieee80211_key *k,
if (IEEE80211_IS_MULTICAST(mac)) {
(void) memset(node.bssid, 0xff, 6);
node.id = IWK_BROADCAST_ID;
+ } else if (ic->ic_opmode == IEEE80211_M_IBSS) {
+ mutex_exit(&sc->sc_glock);
+ mutex_enter(&sc->sc_ibss.node_tb_lock);
+
+ /*
+ * search for node in ibss node table
+ */
+ for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT;
+ index1++) {
+ if (sc->sc_ibss.ibss_node_tb[index1].used &&
+ IEEE80211_ADDR_EQ(sc->sc_ibss.
+ ibss_node_tb[index1].node.bssid,
+ mac)) {
+ break;
+ }
+ }
+ if (index1 >= IWK_BROADCAST_ID) {
+ cmn_err(CE_WARN, "iwk_key_set(): "
+ "have no this node in hardware node table\n");
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+ return (0);
+ } else {
+ /*
+ * configure key for given node in hardware
+ */
+ if (k->wk_flags & IEEE80211_KEY_XMIT) {
+ sc->sc_ibss.ibss_node_tb[index1].
+ node.key_flags = 0;
+ sc->sc_ibss.ibss_node_tb[index1].
+ node.keyp = k->wk_keyix;
+ } else {
+ sc->sc_ibss.ibss_node_tb[index1].
+ node.key_flags = (1 << 14);
+ sc->sc_ibss.ibss_node_tb[index1].
+ node.keyp = k->wk_keyix + 4;
+ }
+
+ (void) memcpy(sc->sc_ibss.ibss_node_tb[index1].node.key,
+ k->wk_key, k->wk_keylen);
+ sc->sc_ibss.ibss_node_tb[index1].node.key_flags |=
+ (STA_KEY_FLG_CCMP | (1 << 3) | (k->wk_keyix << 8));
+ sc->sc_ibss.ibss_node_tb[index1].node.sta_mask =
+ STA_MODIFY_KEY_MASK;
+ sc->sc_ibss.ibss_node_tb[index1].node.control = 1;
+
+ mutex_enter(&sc->sc_glock);
+ err = iwk_cmd(sc, REPLY_ADD_STA,
+ &sc->sc_ibss.ibss_node_tb[index1].node,
+ sizeof (iwk_add_sta_t), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_key_set(): "
+ "failed to update IBSS node in hardware\n");
+ mutex_exit(&sc->sc_glock);
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+ return (0);
+ }
+ mutex_exit(&sc->sc_glock);
+ }
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+ return (1);
} else {
IEEE80211_ADDR_COPY(node.bssid, ic->ic_bss->in_bssid);
node.id = IWK_AP_ID;
@@ -2497,6 +2570,7 @@ iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
mblk_t *m, *m0;
int rate, hdrlen, len, len0, mblen, off, err = IWK_SUCCESS;
uint16_t masks = 0;
+ uint8_t index, index1, index2;
ring = &sc->sc_txq[0];
data = &ring->data[ring->cur];
@@ -2550,6 +2624,49 @@ iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
wh = (struct ieee80211_frame *)m->b_rptr;
+ if (ic->ic_opmode == IEEE80211_M_IBSS &&
+ (!(IEEE80211_IS_MULTICAST(wh->i_addr1)))) {
+ mutex_enter(&sc->sc_glock);
+ mutex_enter(&sc->sc_ibss.node_tb_lock);
+
+ /*
+ * search for node in ibss node table
+ */
+ for (index1 = IWK_STA_ID;
+ index1 < IWK_STATION_COUNT; index1++) {
+ if (sc->sc_ibss.ibss_node_tb[index1].used &&
+ IEEE80211_ADDR_EQ(sc->sc_ibss.
+ ibss_node_tb[index1].node.bssid,
+ wh->i_addr1)) {
+ break;
+ }
+ }
+
+ /*
+ * if don't find in ibss node table
+ */
+ if (index1 >= IWK_BROADCAST_ID) {
+ err = iwk_clean_add_node_ibss(ic,
+ wh->i_addr1, &index2);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_send(): "
+ "failed to clean all nodes "
+ "and add one node\n");
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+ mutex_exit(&sc->sc_glock);
+ freemsg(m);
+ sc->sc_tx_err++;
+ err = IWK_SUCCESS;
+ goto exit;
+ }
+ index = index2;
+ } else {
+ index = index1;
+ }
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+ mutex_exit(&sc->sc_glock);
+ }
+
in = ieee80211_find_txnode(ic, wh->i_addr1);
if (in == NULL) {
cmn_err(CE_WARN, "iwk_send(): failed to find tx node\n");
@@ -2640,7 +2757,9 @@ iwk_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
tx->sta_id = IWK_BROADCAST_ID;
} else {
- if (ic->ic_opmode != IEEE80211_M_IBSS)
+ if (ic->ic_opmode == IEEE80211_M_IBSS)
+ tx->sta_id = index;
+ else
tx->sta_id = IWK_AP_ID;
}
@@ -2740,7 +2859,15 @@ iwk_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
{
iwk_sc_t *sc = (iwk_sc_t *)arg;
ieee80211com_t *ic = &sc->sc_ic;
- int err;
+
+ enum ieee80211_opmode oldmod;
+ iwk_tx_power_table_cmd_t txpower;
+ iwk_add_sta_t node;
+ iwk_link_quality_cmd_t link_quality;
+ uint16_t masks = 0;
+ int i, err, err1;
+
+ oldmod = ic->ic_opmode;
mutex_enter(&sc->sc_glock);
if (sc->sc_flags & (IWK_F_SUSPEND | IWK_F_HW_ERR_RECOVER)) {
@@ -2752,6 +2879,125 @@ iwk_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
err = ieee80211_ioctl(ic, wq, mp);
+ /*
+ * return to STA mode
+ */
+ if ((0 == err || ENETRESET == err) && (oldmod != ic->ic_opmode) &&
+ (ic->ic_opmode == IEEE80211_M_STA)) {
+ /* configure rxon */
+ (void) memset(&sc->sc_config, 0, sizeof (iwk_rxon_cmd_t));
+ IEEE80211_ADDR_COPY(sc->sc_config.node_addr, ic->ic_macaddr);
+ IEEE80211_ADDR_COPY(sc->sc_config.wlap_bssid, ic->ic_macaddr);
+ sc->sc_config.chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
+ sc->sc_config.flags = (RXON_FLG_TSF2HOST_MSK |
+ RXON_FLG_AUTO_DETECT_MSK |
+ RXON_FLG_BAND_24G_MSK);
+ sc->sc_config.flags &= (~RXON_FLG_CCK_MSK);
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_STA:
+ sc->sc_config.dev_type = RXON_DEV_TYPE_ESS;
+ sc->sc_config.filter_flags |=
+ LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
+ RXON_FILTER_DIS_DECRYPT_MSK |
+ RXON_FILTER_DIS_GRP_DECRYPT_MSK);
+ break;
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
+ sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
+ sc->sc_config.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ sc->sc_config.filter_flags =
+ LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
+ RXON_FILTER_DIS_DECRYPT_MSK |
+ RXON_FILTER_DIS_GRP_DECRYPT_MSK);
+ break;
+ case IEEE80211_M_HOSTAP:
+ sc->sc_config.dev_type = RXON_DEV_TYPE_AP;
+ break;
+ case IEEE80211_M_MONITOR:
+ sc->sc_config.dev_type = RXON_DEV_TYPE_SNIFFER;
+ sc->sc_config.filter_flags |=
+ LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
+ RXON_FILTER_CTL2HOST_MSK |
+ RXON_FILTER_PROMISC_MSK);
+ break;
+ }
+ sc->sc_config.cck_basic_rates = 0x0f;
+ sc->sc_config.ofdm_basic_rates = 0xff;
+ sc->sc_config.ofdm_ht_single_stream_basic_rates = 0xff;
+ sc->sc_config.ofdm_ht_dual_stream_basic_rates = 0xff;
+ /* set antenna */
+ mutex_enter(&sc->sc_glock);
+ sc->sc_config.rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
+ LE_16((0x7 << RXON_RX_CHAIN_VALID_POS) |
+ (0x6 << RXON_RX_CHAIN_FORCE_SEL_POS) |
+ (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS));
+ err1 = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
+ sizeof (iwk_rxon_cmd_t), 1);
+ if (err1 != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_m_ioctl(): "
+ "failed to set configure command"
+ " please run (ifconfig unplumb and"
+ " ifconfig plumb)\n");
+ }
+ /*
+ * set Tx power for 2.4GHz channels
+ * (need further investigation. fix tx power at present)
+ */
+ (void) memset(&txpower, 0, sizeof (txpower));
+ txpower.band = 1; /* for 2.4G */
+ txpower.channel = sc->sc_config.chan;
+ txpower.channel_normal_width = 0;
+ for (i = 0; i < POWER_TABLE_NUM_HT_OFDM_ENTRIES; i++) {
+ txpower.tx_power.ht_ofdm_power[i].
+ s.ramon_tx_gain = 0x3f3f;
+ txpower.tx_power.ht_ofdm_power[i].
+ s.dsp_predis_atten = 110 | (110 << 8);
+ }
+ txpower.tx_power.ht_ofdm_power[POWER_TABLE_NUM_HT_OFDM_ENTRIES].
+ s.ramon_tx_gain = 0x3f3f;
+ txpower.tx_power.ht_ofdm_power[POWER_TABLE_NUM_HT_OFDM_ENTRIES].
+ s.dsp_predis_atten = 110 | (110 << 8);
+ err1 = iwk_cmd(sc, REPLY_TX_PWR_TABLE_CMD, &txpower,
+ sizeof (txpower), 1);
+ if (err1 != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_m_ioctl(): failed to set txpower"
+ " please run (ifconfig unplumb "
+ "and ifconfig plumb)\n");
+ }
+ /* add broadcast node so that we can send broadcast frame */
+ (void) memset(&node, 0, sizeof (node));
+ (void) memset(node.bssid, 0xff, 6);
+ node.id = IWK_BROADCAST_ID;
+ err1 = iwk_cmd(sc, REPLY_ADD_STA, &node, sizeof (node), 1);
+ if (err1 != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_m_ioctl(): "
+ "failed to add broadcast node\n");
+ }
+
+ /* TX_LINK_QUALITY cmd */
+ (void) memset(&link_quality, 0, sizeof (link_quality));
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+ masks |= RATE_MCS_CCK_MSK;
+ masks |= RATE_MCS_ANT_B_MSK;
+ masks &= ~RATE_MCS_ANT_A_MSK;
+ link_quality.rate_n_flags[i] =
+ iwk_rate_to_plcp(2) | masks;
+ }
+ link_quality.general_params.single_stream_ant_msk = 2;
+ link_quality.general_params.dual_stream_ant_msk = 3;
+ link_quality.agg_params.agg_dis_start_th = 3;
+ link_quality.agg_params.agg_time_limit = LE_16(4000);
+ link_quality.sta_id = IWK_BROADCAST_ID;
+ err1 = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD, &link_quality,
+ sizeof (link_quality), 1);
+ if (err1 != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_m_ioctl(): "
+ "failed to config link quality table\n");
+ }
+ mutex_exit(&sc->sc_glock);
+ ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+ }
+
if (err == ENETRESET) {
/*
* This is special for the hidden AP connection.
@@ -3252,7 +3498,7 @@ iwk_hw_set_before_auth(iwk_sc_t *sc)
return (err);
}
- /* TX_LINK_QUALITY cmd ? */
+ /* TX_LINK_QUALITY cmd */
(void) memset(&link_quality, 0, sizeof (link_quality));
rs = ic->ic_sup_rates[ieee80211_chan2mode(ic, ic->ic_curchan)];
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
@@ -3505,6 +3751,7 @@ iwk_config(iwk_sc_t *sc)
RXON_FILTER_DIS_DECRYPT_MSK |
RXON_FILTER_DIS_GRP_DECRYPT_MSK);
break;
+ case IEEE80211_M_IBSS:
case IEEE80211_M_AHDEMO:
sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
sc->sc_config.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
@@ -5488,6 +5735,79 @@ static int iwk_ofdm_sens(iwk_sc_t *sc, uint32_t actual_rx_time)
}
/*
+ * additional process to management frames
+ */
+static void iwk_recv_mgmt(struct ieee80211com *ic, mblk_t *mp,
+ struct ieee80211_node *in,
+ int subtype, int rssi, uint32_t rstamp)
+{
+ iwk_sc_t *sc = (iwk_sc_t *)ic;
+ struct ieee80211_frame *wh;
+ uint8_t index1, index2;
+ int err;
+
+ sc->sc_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
+
+ mutex_enter(&sc->sc_glock);
+ switch (subtype) {
+ case IEEE80211_FC0_SUBTYPE_BEACON:
+ if (sc->sc_ibss.ibss_beacon.syncbeacon && in == ic->ic_bss &&
+ ic->ic_state == IEEE80211_S_RUN) {
+ if (ieee80211_beacon_update(ic, in,
+ &sc->sc_ibss.ibss_beacon.iwk_boff,
+ sc->sc_ibss.ibss_beacon.mp, 0)) {
+ bcopy(sc->sc_ibss.ibss_beacon.mp->b_rptr,
+ sc->sc_ibss.ibss_beacon.beacon_cmd.
+ bcon_frame,
+ MBLKL(sc->sc_ibss.ibss_beacon.mp));
+ }
+ err = iwk_cmd(sc, REPLY_TX_BEACON,
+ &sc->sc_ibss.ibss_beacon.beacon_cmd,
+ sc->sc_ibss.ibss_beacon.beacon_cmd_len, 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_recv_mgmt(): "
+ "failed to TX beacon.\n");
+ }
+ sc->sc_ibss.ibss_beacon.syncbeacon = 0;
+ }
+ if (ic->ic_opmode == IEEE80211_M_IBSS &&
+ ic->ic_state == IEEE80211_S_RUN) {
+ wh = (struct ieee80211_frame *)mp->b_rptr;
+ mutex_enter(&sc->sc_ibss.node_tb_lock);
+ /*
+ * search for node in ibss node table
+ */
+ for (index1 = IWK_STA_ID; index1 < IWK_STATION_COUNT;
+ index1++) {
+ if (sc->sc_ibss.ibss_node_tb[index1].used &&
+ IEEE80211_ADDR_EQ(sc->sc_ibss.
+ ibss_node_tb[index1].node.bssid,
+ wh->i_addr2)) {
+ break;
+ }
+ }
+ /*
+ * if don't find in ibss node table
+ */
+ if (index1 >= IWK_BROADCAST_ID) {
+ err = iwk_clean_add_node_ibss(ic,
+ wh->i_addr2, &index2);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_recv_mgmt(): "
+ "failed to clean all nodes "
+ "and add one node\n");
+ }
+ }
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+ }
+ break;
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+ break;
+ }
+ mutex_exit(&sc->sc_glock);
+}
+
+/*
* 1) log_event_table_ptr indicates base of the event log. This traces
* a 256-entry history of uCode execution within a circular buffer.
* Its header format is:
@@ -5673,3 +5993,405 @@ static void iwk_write_error_log(iwk_sc_t *sc)
iwk_mac_access_exit(sc);
}
+
+static int
+iwk_run_state_config_ibss(ieee80211com_t *ic)
+{
+ iwk_sc_t *sc = (iwk_sc_t *)ic;
+ ieee80211_node_t *in = ic->ic_bss;
+ int i, err = IWK_SUCCESS;
+
+ mutex_enter(&sc->sc_ibss.node_tb_lock);
+
+ /*
+ * clean all nodes in ibss node table assure be
+ * consistent with hardware
+ */
+ for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) {
+ sc->sc_ibss.ibss_node_tb[i].used = 0;
+ (void) memset(&sc->sc_ibss.ibss_node_tb[i].node,
+ 0,
+ sizeof (iwk_add_sta_t));
+ }
+
+ sc->sc_ibss.node_number = 0;
+
+ mutex_exit(&sc->sc_ibss.node_tb_lock);
+
+ /*
+ * configure RX and TX
+ */
+ sc->sc_config.dev_type = RXON_DEV_TYPE_IBSS;
+
+ sc->sc_config.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ sc->sc_config.filter_flags =
+ LE_32(RXON_FILTER_ACCEPT_GRP_MSK |
+ RXON_FILTER_DIS_DECRYPT_MSK |
+ RXON_FILTER_DIS_GRP_DECRYPT_MSK);
+
+ sc->sc_config.assoc_id = 0;
+
+ IEEE80211_ADDR_COPY(sc->sc_config.bssid, in->in_bssid);
+ sc->sc_config.chan = ieee80211_chan2ieee(ic,
+ in->in_chan);
+
+ if (ic->ic_curmode == IEEE80211_MODE_11B) {
+ sc->sc_config.cck_basic_rates = 0x03;
+ sc->sc_config.ofdm_basic_rates = 0;
+ } else if ((in->in_chan != IEEE80211_CHAN_ANYC) &&
+ (IEEE80211_IS_CHAN_5GHZ(in->in_chan))) {
+ sc->sc_config.cck_basic_rates = 0;
+ sc->sc_config.ofdm_basic_rates = 0x15;
+
+ } else {
+ sc->sc_config.cck_basic_rates = 0x0f;
+ sc->sc_config.ofdm_basic_rates = 0xff;
+ }
+
+ sc->sc_config.flags &=
+ ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
+ RXON_FLG_SHORT_SLOT_MSK);
+
+ if (ic->ic_flags & IEEE80211_F_SHSLOT) {
+ sc->sc_config.flags |=
+ LE_32(RXON_FLG_SHORT_SLOT_MSK);
+ }
+
+ if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
+ sc->sc_config.flags |=
+ LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
+ }
+
+ sc->sc_config.filter_flags |=
+ LE_32(RXON_FILTER_ASSOC_MSK);
+
+ err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
+ sizeof (iwk_rxon_cmd_t), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_run_state_config_ibss(): "
+ "failed to update configuration.\n");
+ return (err);
+ }
+
+ return (err);
+
+}
+
+static int
+iwk_run_state_config_sta(ieee80211com_t *ic)
+{
+ iwk_sc_t *sc = (iwk_sc_t *)ic;
+ ieee80211_node_t *in = ic->ic_bss;
+ int err = IWK_SUCCESS;
+
+ /* update adapter's configuration */
+ if (sc->sc_assoc_id != in->in_associd) {
+ cmn_err(CE_WARN, "iwk_run_state_config_sta(): "
+ "associate ID mismatch: expected %d, "
+ "got %d\n",
+ in->in_associd, sc->sc_assoc_id);
+ }
+ sc->sc_config.assoc_id = in->in_associd & 0x3fff;
+
+ /*
+ * short preamble/slot time are
+ * negotiated when associating
+ */
+ sc->sc_config.flags &=
+ ~LE_32(RXON_FLG_SHORT_PREAMBLE_MSK |
+ RXON_FLG_SHORT_SLOT_MSK);
+
+ if (ic->ic_flags & IEEE80211_F_SHSLOT)
+ sc->sc_config.flags |=
+ LE_32(RXON_FLG_SHORT_SLOT_MSK);
+
+ if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
+ sc->sc_config.flags |=
+ LE_32(RXON_FLG_SHORT_PREAMBLE_MSK);
+
+ sc->sc_config.filter_flags |=
+ LE_32(RXON_FILTER_ASSOC_MSK);
+
+ if (ic->ic_opmode != IEEE80211_M_STA)
+ sc->sc_config.filter_flags |=
+ LE_32(RXON_FILTER_BCON_AWARE_MSK);
+
+ IWK_DBG((IWK_DEBUG_80211, "config chan %d flags %x"
+ " filter_flags %x\n",
+ sc->sc_config.chan, sc->sc_config.flags,
+ sc->sc_config.filter_flags));
+
+ err = iwk_cmd(sc, REPLY_RXON, &sc->sc_config,
+ sizeof (iwk_rxon_cmd_t), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_run_state_config_sta(): "
+ "failed to update configuration\n");
+ return (err);
+ }
+
+ return (err);
+}
+
+static int
+iwk_start_tx_beacon(ieee80211com_t *ic)
+{
+ iwk_sc_t *sc = (iwk_sc_t *)ic;
+ ieee80211_node_t *in = ic->ic_bss;
+ int err = IWK_SUCCESS;
+ iwk_tx_beacon_cmd_t *tx_beacon_p;
+ uint16_t masks = 0;
+ mblk_t *mp;
+ int rate;
+
+ /*
+ * allocate and transmit beacon frames
+ */
+ tx_beacon_p = &sc->sc_ibss.ibss_beacon.beacon_cmd;
+
+ (void) memset(tx_beacon_p, 0,
+ sizeof (iwk_tx_beacon_cmd_t));
+ rate = 0;
+ masks = 0;
+
+ tx_beacon_p->config.sta_id = IWK_BROADCAST_ID;
+ tx_beacon_p->config.stop_time.life_time =
+ LE_32(0xffffffff);
+
+ if (sc->sc_ibss.ibss_beacon.mp != NULL) {
+ freemsg(sc->sc_ibss.ibss_beacon.mp);
+ sc->sc_ibss.ibss_beacon.mp = NULL;
+ }
+
+ sc->sc_ibss.ibss_beacon.mp =
+ ieee80211_beacon_alloc(ic, in,
+ &sc->sc_ibss.ibss_beacon.iwk_boff);
+ if (sc->sc_ibss.ibss_beacon.mp == NULL) {
+ cmn_err(CE_WARN, "iwk_start_tx_beacon(): "
+ "failed to get beacon frame.\n");
+ return (IWK_FAIL);
+ }
+
+ mp = sc->sc_ibss.ibss_beacon.mp;
+
+ ASSERT(mp->b_cont == NULL);
+
+ bcopy(mp->b_rptr, tx_beacon_p->bcon_frame, MBLKL(mp));
+
+ tx_beacon_p->config.len = (uint16_t)(MBLKL(mp));
+ sc->sc_ibss.ibss_beacon.beacon_cmd_len =
+ sizeof (iwk_tx_cmd_t) +
+ 4 + tx_beacon_p->config.len;
+
+ /*
+ * beacons are sent at 1M
+ */
+ rate = in->in_rates.ir_rates[0];
+ rate &= IEEE80211_RATE_VAL;
+
+ if (2 == rate || 4 == rate || 11 == rate ||
+ 22 == rate) {
+ masks |= RATE_MCS_CCK_MSK;
+ }
+
+ masks |= RATE_MCS_ANT_B_MSK;
+
+ tx_beacon_p->config.rate.r.rate_n_flags =
+ (iwk_rate_to_plcp(rate) | masks);
+
+
+ tx_beacon_p->config.tx_flags =
+ (TX_CMD_FLG_SEQ_CTL_MSK | TX_CMD_FLG_TSF_MSK);
+
+ if (ic->ic_bss->in_tstamp.tsf != 0) {
+ sc->sc_ibss.ibss_beacon.syncbeacon = 1;
+ } else {
+ if (ieee80211_beacon_update(ic, in,
+ &sc->sc_ibss.ibss_beacon.iwk_boff,
+ mp, 0)) {
+ bcopy(mp->b_rptr,
+ tx_beacon_p->bcon_frame,
+ MBLKL(mp));
+ }
+
+ err = iwk_cmd(sc, REPLY_TX_BEACON,
+ tx_beacon_p,
+ sc->sc_ibss.ibss_beacon.beacon_cmd_len,
+ 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_start_tx_beacon(): "
+ "failed to TX beacon.\n");
+ return (err);
+ }
+
+ sc->sc_ibss.ibss_beacon.syncbeacon = 0;
+ }
+
+ return (err);
+}
+
+static int
+iwk_clean_add_node_ibss(struct ieee80211com *ic,
+ uint8_t addr[IEEE80211_ADDR_LEN], uint8_t *index2)
+{
+ iwk_sc_t *sc = (iwk_sc_t *)ic;
+ uint8_t index;
+ iwk_add_sta_t bc_node;
+ iwk_link_quality_cmd_t bc_link_quality;
+ iwk_link_quality_cmd_t link_quality;
+ uint16_t bc_masks = 0;
+ uint16_t masks = 0;
+ int i, rate;
+ struct ieee80211_rateset rs;
+ iwk_ibss_node_t *ibss_node_p;
+ int err = IWK_SUCCESS;
+
+ /*
+ * find a location that is not
+ * used in ibss node table
+ */
+ for (index = IWK_STA_ID;
+ index < IWK_STATION_COUNT; index++) {
+ if (!sc->sc_ibss.ibss_node_tb[index].used) {
+ break;
+ }
+ }
+
+ /*
+ * if have too many nodes in hardware, clean up
+ */
+ if (index < IWK_BROADCAST_ID &&
+ sc->sc_ibss.node_number >= 25) {
+ if (iwk_cmd(sc, REPLY_REMOVE_ALL_STA,
+ NULL, 0, 1) != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
+ "failed to remove all nodes in hardware\n");
+ return (IWK_FAIL);
+ }
+
+ for (i = IWK_STA_ID; i < IWK_STATION_COUNT; i++) {
+ sc->sc_ibss.ibss_node_tb[i].used = 0;
+ (void) memset(&sc->sc_ibss.ibss_node_tb[i].node,
+ 0, sizeof (iwk_add_sta_t));
+ }
+
+ sc->sc_ibss.node_number = 0;
+
+ /*
+ * add broadcast node so that we
+ * can send broadcast frame
+ */
+ (void) memset(&bc_node, 0, sizeof (bc_node));
+ (void) memset(bc_node.bssid, 0xff, 6);
+ bc_node.id = IWK_BROADCAST_ID;
+
+ err = iwk_cmd(sc, REPLY_ADD_STA, &bc_node, sizeof (bc_node), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
+ "failed to add broadcast node\n");
+ return (err);
+ }
+
+ /* TX_LINK_QUALITY cmd */
+ (void) memset(&bc_link_quality, 0, sizeof (bc_link_quality));
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+ bc_masks |= RATE_MCS_CCK_MSK;
+ bc_masks |= RATE_MCS_ANT_B_MSK;
+ bc_masks &= ~RATE_MCS_ANT_A_MSK;
+ bc_link_quality.rate_n_flags[i] =
+ iwk_rate_to_plcp(2) | bc_masks;
+ }
+
+ bc_link_quality.general_params.single_stream_ant_msk = 2;
+ bc_link_quality.general_params.dual_stream_ant_msk = 3;
+ bc_link_quality.agg_params.agg_dis_start_th = 3;
+ bc_link_quality.agg_params.agg_time_limit = LE_16(4000);
+ bc_link_quality.sta_id = IWK_BROADCAST_ID;
+
+ err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD,
+ &bc_link_quality, sizeof (bc_link_quality), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
+ "failed to config link quality table\n");
+ return (err);
+ }
+ }
+
+ if (index >= IWK_BROADCAST_ID) {
+ cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
+ "the count of node in hardware is too much\n");
+ return (IWK_FAIL);
+ }
+
+ /*
+ * add a node into hardware
+ */
+ ibss_node_p = &sc->sc_ibss.ibss_node_tb[index];
+
+ ibss_node_p->used = 1;
+
+ (void) memset(&ibss_node_p->node, 0,
+ sizeof (iwk_add_sta_t));
+
+ IEEE80211_ADDR_COPY(ibss_node_p->node.bssid, addr);
+ ibss_node_p->node.id = index;
+ ibss_node_p->node.control = 0;
+ ibss_node_p->node.flags = 0;
+
+ err = iwk_cmd(sc, REPLY_ADD_STA, &ibss_node_p->node,
+ sizeof (iwk_add_sta_t), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
+ "failed to add IBSS node\n");
+ ibss_node_p->used = 0;
+ (void) memset(&ibss_node_p->node, 0,
+ sizeof (iwk_add_sta_t));
+ return (err);
+ }
+
+ sc->sc_ibss.node_number++;
+
+ (void) memset(&link_quality, 0, sizeof (link_quality));
+
+ rs = ic->ic_sup_rates[ieee80211_chan2mode(ic,
+ ic->ic_curchan)];
+
+ for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+ if (i < rs.ir_nrates) {
+ rate = rs.
+ ir_rates[rs.ir_nrates - i];
+ } else {
+ rate = 2;
+ }
+
+ if (2 == rate || 4 == rate ||
+ 11 == rate || 22 == rate) {
+ masks |= RATE_MCS_CCK_MSK;
+ }
+
+ masks |= RATE_MCS_ANT_B_MSK;
+ masks &= ~RATE_MCS_ANT_A_MSK;
+
+ link_quality.rate_n_flags[i] =
+ iwk_rate_to_plcp(rate) | masks;
+ }
+
+ link_quality.general_params.single_stream_ant_msk = 2;
+ link_quality.general_params.dual_stream_ant_msk = 3;
+ link_quality.agg_params.agg_dis_start_th = 3;
+ link_quality.agg_params.agg_time_limit = LE_16(4000);
+ link_quality.sta_id = ibss_node_p->node.id;
+
+ err = iwk_cmd(sc, REPLY_TX_LINK_QUALITY_CMD,
+ &link_quality, sizeof (link_quality), 1);
+ if (err != IWK_SUCCESS) {
+ cmn_err(CE_WARN, "iwk_clean_add_node_ibss(): "
+ "failed to set up TX link quality\n");
+ ibss_node_p->used = 0;
+ (void) memset(ibss_node_p->node.bssid, 0, 6);
+ return (err);
+ }
+
+ *index2 = index;
+
+ return (err);
+}
diff --git a/usr/src/uts/common/io/iwk/iwk2_var.h b/usr/src/uts/common/io/iwk/iwk2_var.h
index 37c0ff1b2b..28a8dcb574 100644
--- a/usr/src/uts/common/io/iwk/iwk2_var.h
+++ b/usr/src/uts/common/io/iwk/iwk2_var.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -90,6 +90,28 @@ typedef struct iwk_amrr {
int recovery;
} iwk_amrr_t;
+typedef struct iwk_ibss_node {
+ iwk_add_sta_t node;
+ int8_t used;
+} iwk_ibss_node_t;
+
+typedef struct iwk_ibss_beacon {
+ /* for update beacon frame dynamically */
+ struct ieee80211_beacon_offsets iwk_boff;
+ uint32_t beacon_cmd_len;
+ iwk_tx_beacon_cmd_t beacon_cmd;
+ uint8_t syncbeacon;
+ /* beacon frame allocated from net80211 module */
+ mblk_t *mp;
+} iwk_ibss_beacon_t;
+
+typedef struct iwk_ibss {
+ iwk_ibss_node_t ibss_node_tb[IWK_STATION_COUNT];
+ uint32_t node_number;
+ kmutex_t node_tb_lock;
+ iwk_ibss_beacon_t ibss_beacon;
+} iwk_ibss_t;
+
typedef struct iwk_softc {
struct ieee80211com sc_ic;
dev_info_t *sc_dip;
@@ -174,6 +196,7 @@ typedef struct iwk_softc {
uint32_t sc_tx_err;
uint32_t sc_rx_err;
uint32_t sc_tx_retries;
+ iwk_ibss_t sc_ibss;
} iwk_sc_t;
#define IWK_F_ATTACHED (1 << 0)
diff --git a/usr/src/uts/common/io/net80211/net80211_input.c b/usr/src/uts/common/io/net80211/net80211_input.c
index eb95149ea6..1e80f1596e 100644
--- a/usr/src/uts/common/io/net80211/net80211_input.c
+++ b/usr/src/uts/common/io/net80211/net80211_input.c
@@ -1,11 +1,11 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2001 Atsushi Onoe
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +73,7 @@ ieee80211_input(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
uint8_t tid;
ASSERT(in != NULL);
+ in->in_inact = in->in_inact_reload;
type = (uint8_t)-1; /* undefined */
len = MBLKL(mp);
if (len < sizeof (struct ieee80211_frame_min)) {
@@ -179,7 +180,6 @@ ieee80211_input(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
}
in->in_rxseqs[tid] = rxseq;
}
- in->in_inact = 0;
}
switch (type) {
@@ -879,24 +879,21 @@ ieee80211_recv_beacon(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
return;
}
- if (scan.capinfo & IEEE80211_CAPINFO_IBSS) {
+ if (ic->ic_opmode == IEEE80211_M_IBSS &&
+ scan.capinfo & IEEE80211_CAPINFO_IBSS) {
if (!IEEE80211_ADDR_EQ(wh->i_addr2, in->in_macaddr)) {
/*
* Create a new entry in the neighbor table.
*/
in = ieee80211_add_neighbor(ic, wh, &scan);
- } else if (in->in_capinfo == 0) {
- /*
- * Update faked node created on transmit.
- * Note this also updates the tsf.
- */
- ieee80211_init_neighbor(in, wh, &scan);
} else {
/*
- * Record tsf for potential resync.
+ * Copy data from beacon to neighbor table.
+ * Some of this information might change after
+ * ieee80211_add_neighbor(), so we just copy
+ * everything over to be safe.
*/
- bcopy(scan.tstamp, in->in_tstamp.data,
- sizeof (in->in_tstamp));
+ ieee80211_init_neighbor(in, wh, &scan);
}
if (in != NULL) {
in->in_rssi = (uint8_t)rssi;
@@ -969,14 +966,20 @@ ieee80211_recv_mgmt(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
frm += frm[1] + 2;
}
IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, break);
+ if (xrates != NULL) {
+ IEEE80211_VERIFY_ELEMENT(xrates,
+ IEEE80211_RATE_MAXSIZE - rates[1], break);
+ }
IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, break);
IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, break);
- if ((ic->ic_flags & IEEE80211_F_HIDESSID) && ssid[1] == 0) {
- ieee80211_dbg(IEEE80211_MSG_INPUT,
- "ieee80211_recv_mgmt: ignore %s, "
- "no ssid with ssid suppression enabled",
- IEEE80211_SUBTYPE_NAME(subtype));
- break;
+ if (ic->ic_flags & IEEE80211_F_HIDESSID) {
+ if (ssid == NULL || ssid[1] == 0) {
+ ieee80211_dbg(IEEE80211_MSG_INPUT,
+ "ieee80211_recv_mgmt: ignore %s, "
+ "no ssid with ssid suppression enabled",
+ IEEE80211_SUBTYPE_NAME(subtype));
+ break;
+ }
}
if (in == ic->ic_bss) {
diff --git a/usr/src/uts/common/io/net80211/net80211_ioctl.c b/usr/src/uts/common/io/net80211/net80211_ioctl.c
index 44935e0979..bcc2f7aba4 100644
--- a/usr/src/uts/common/io/net80211/net80211_ioctl.c
+++ b/usr/src/uts/common/io/net80211/net80211_ioctl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -462,6 +462,9 @@ wifi_cfg_bsstype(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp)
wl_get_bsstype(ic, ow_opmode);
break;
case WLAN_SET_PARAM:
+ if (*iw_opmode == ic->ic_opmode)
+ break;
+
err = wl_set_bsstype(ic, iw_opmode);
break;
default:
@@ -477,6 +480,64 @@ wifi_cfg_bsstype(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp)
}
static int
+wifi_cfg_createibss(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp)
+{
+ mblk_t *omp;
+ wldp_t *inp = (wldp_t *)(*mp)->b_rptr;
+ wldp_t *outp;
+ wl_create_ibss_t *iw_ibss = (wl_create_ibss_t *)inp->wldp_buf;
+ wl_create_ibss_t *ow_ibss;
+ int err = 0;
+
+ if ((omp = wifi_getoutmsg(*mp, cmd, sizeof (wl_create_ibss_t))) == NULL)
+ return (ENOMEM);
+ outp = (wldp_t *)omp->b_rptr;
+ ow_ibss = (wl_create_ibss_t *)outp->wldp_buf;
+
+ switch (cmd) {
+ case WLAN_GET_PARAM:
+ *ow_ibss = (ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0;
+ break;
+ case WLAN_SET_PARAM:
+ ieee80211_dbg(IEEE80211_MSG_CONFIG, "wifi_cfg_createibss: "
+ "set createibss=%u\n", *iw_ibss);
+ if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) {
+ outp->wldp_result = WL_LACK_FEATURE;
+ err = ENOTSUP;
+ break;
+ }
+ if (*iw_ibss) { /* create ibss */
+ if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
+ ic->ic_flags |= IEEE80211_F_IBSSON;
+ ic->ic_opmode = IEEE80211_M_IBSS;
+ /*
+ * Yech, slot time may change depending on the
+ * operating mode so reset it to be sure
+ * everything is setup appropriately.
+ */
+ ieee80211_reset_erp(ic);
+ err = ENETRESET;
+ }
+ } else {
+ if (ic->ic_flags & IEEE80211_F_IBSSON) {
+ ic->ic_flags &= ~IEEE80211_F_IBSSON;
+ err = ENETRESET;
+ }
+ }
+ break;
+ default:
+ ieee80211_err("wifi_cfg_bsstype: unknown command %x\n", cmd);
+ outp->wldp_result = WL_NOTSUPPORTED;
+ err = EINVAL;
+ break;
+ }
+
+ freemsg(*mp);
+ *mp = omp;
+ return (err);
+}
+
+static int
wifi_cfg_linkstatus(struct ieee80211com *ic, uint32_t cmd, mblk_t **mp)
{
mblk_t *omp;
@@ -682,6 +743,8 @@ wifi_read_ap(void *arg, struct ieee80211_node *in)
if ((uint8_t *)conf > end)
return;
+ conf->wl_ess_conf_length = sizeof (struct wl_ess_conf);
+
/* skip newly allocated NULL bss node */
if (IEEE80211_ADDR_EQ(in->in_macaddr, ic->ic_macaddr))
return;
@@ -875,6 +938,8 @@ wifi_loaddefdata(struct ieee80211com *ic)
bzero(ic->ic_nw_keys[i].wk_key, IEEE80211_KEYBUF_SIZE);
}
ic->ic_curmode = IEEE80211_MODE_AUTO;
+ ic->ic_flags &= ~IEEE80211_F_IBSSON;
+ ic->ic_opmode = IEEE80211_M_STA;
}
static int
@@ -1244,6 +1309,9 @@ wifi_cfg_getset(struct ieee80211com *ic, mblk_t **mp, uint32_t cmd)
case WL_BSS_TYPE:
err = wifi_cfg_bsstype(ic, cmd, mp);
break;
+ case WL_CREATE_IBSS:
+ err = wifi_cfg_createibss(ic, cmd, mp);
+ break;
case WL_DESIRED_RATES:
err = wifi_cfg_desrates(ic, cmd, mp);
break;
@@ -1492,11 +1560,9 @@ wl_set_bsstype(struct ieee80211com *ic, const void *wldp_buf)
err = ENOTSUP;
break;
}
- if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) {
- ic->ic_flags |= IEEE80211_F_IBSSON;
- ic->ic_opmode = IEEE80211_M_IBSS;
- err = ENETRESET;
- }
+
+ ic->ic_opmode = IEEE80211_M_IBSS;
+ err = ENETRESET;
break;
default:
ieee80211_err("wl_set_bsstype: "
diff --git a/usr/src/uts/common/io/net80211/net80211_node.c b/usr/src/uts/common/io/net80211/net80211_node.c
index cc7e0f92ff..9998725830 100644
--- a/usr/src/uts/common/io/net80211/net80211_node.c
+++ b/usr/src/uts/common/io/net80211/net80211_node.c
@@ -1,11 +1,11 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2001 Atsushi Onoe
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Node management routines
*/
@@ -162,6 +160,7 @@ ieee80211_node_authorize(ieee80211_node_t *in)
in->in_flags |= IEEE80211_NODE_AUTH;
in->in_inact_reload = im->im_inact_run;
+ in->in_inact = in->in_inact_reload;
}
/*
@@ -392,6 +391,9 @@ ieee80211_reset_bss(ieee80211com_t *ic)
ieee80211_node_t *in;
ieee80211_node_t *obss;
+ ieee80211_node_table_reset(&ic->ic_sta);
+ ieee80211_reset_erp(ic);
+
in = ieee80211_alloc_node(ic, &ic->ic_scan, ic->ic_macaddr);
ASSERT(in != NULL);
obss = ic->ic_bss;
diff --git a/usr/src/uts/common/io/net80211/net80211_output.c b/usr/src/uts/common/io/net80211/net80211_output.c
index abd42cfdb5..26f07541db 100644
--- a/usr/src/uts/common/io/net80211/net80211_output.c
+++ b/usr/src/uts/common/io/net80211/net80211_output.c
@@ -1,11 +1,11 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2001 Atsushi Onoe
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,9 +35,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
/*
* Send out 802.11 frames
*/
@@ -402,18 +399,21 @@ ieee80211_send_mgmt(ieee80211com_t *ic, ieee80211_node_t *in, int type, int arg)
if (mp == NULL)
return (ENOMEM);
- bzero(frm, 8); /* timestamp is set by hardware/driver */
+ bzero(frm, 8); /* timestamp should be filled later */
frm += 8;
- *(uint16_t *)frm = LE_16(in->in_intval);
+ *(uint16_t *)frm = LE_16(ic->ic_bss->in_intval);
frm += 2;
capinfo = ieee80211_get_capinfo(ic);
*(uint16_t *)frm = LE_16(capinfo);
frm += 2;
- frm = ieee80211_add_ssid(frm, in->in_essid, in->in_esslen);
+ /* ssid */
+ frm = ieee80211_add_ssid(frm, ic->ic_bss->in_essid,
+ ic->ic_bss->in_esslen);
+ /* supported rates */
frm = ieee80211_add_rates(frm, &in->in_rates);
- if (ic->ic_phytype == IEEE80211_T_FH) {
+ if (IEEE80211_IS_CHAN_FHSS(ic->ic_curchan)) {
*frm++ = IEEE80211_ELEMID_FHPARMS;
*frm++ = IEEE80211_FH_LEN;
*frm++ = in->in_fhdwell & 0x00ff;
@@ -434,7 +434,12 @@ ieee80211_send_mgmt(ieee80211com_t *ic, ieee80211_node_t *in, int type, int arg)
*frm++ = IEEE80211_IBSS_LEN;
*frm++ = 0; *frm++ = 0; /* ATIM window */
}
+ /* ERP */
+ if (IEEE80211_IS_CHAN_ANYG(ic->ic_curchan))
+ frm = ieee80211_add_erp(frm, ic);
+ /* Extended supported rates */
frm = ieee80211_add_xrates(frm, &in->in_rates);
+ mp->b_wptr = frm;
break;
case IEEE80211_FC0_SUBTYPE_AUTH:
@@ -593,6 +598,7 @@ ieee80211_send_mgmt(ieee80211com_t *ic, ieee80211_node_t *in, int type, int arg)
frm = ieee80211_add_rates(frm, &in->in_rates);
frm = ieee80211_add_xrates(frm, &in->in_rates);
+ mp->b_wptr = frm;
break;
case IEEE80211_FC0_SUBTYPE_DISASSOC:
diff --git a/usr/src/uts/common/io/net80211/net80211_proto.c b/usr/src/uts/common/io/net80211/net80211_proto.c
index da81c9f1ad..b98720f6c5 100644
--- a/usr/src/uts/common/io/net80211/net80211_proto.c
+++ b/usr/src/uts/common/io/net80211/net80211_proto.c
@@ -1,11 +1,11 @@
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2001 Atsushi Onoe
- * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,8 +35,6 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* IEEE 802.11 protocol support
*/
@@ -106,49 +104,49 @@ ieee80211_dump_pkt(const uint8_t *buf, int32_t len, int32_t rate, int32_t rssi)
switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
case IEEE80211_FC1_DIR_NODS:
(void) snprintf(buf2, sizeof (buf2), "NODS %s",
- ieee80211_macaddr_sprintf(wh->i_addr2));
+ ieee80211_macaddr_sprintf(wh->i_addr2));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "->%s",
- ieee80211_macaddr_sprintf(wh->i_addr1));
+ ieee80211_macaddr_sprintf(wh->i_addr1));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "(%s)",
- ieee80211_macaddr_sprintf(wh->i_addr3));
+ ieee80211_macaddr_sprintf(wh->i_addr3));
(void) strncat(buf1, buf2, sizeof (buf2));
break;
case IEEE80211_FC1_DIR_TODS:
(void) snprintf(buf2, sizeof (buf2), "TODS %s",
- ieee80211_macaddr_sprintf(wh->i_addr2));
+ ieee80211_macaddr_sprintf(wh->i_addr2));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "->%s",
- ieee80211_macaddr_sprintf(wh->i_addr3));
+ ieee80211_macaddr_sprintf(wh->i_addr3));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "(%s)",
- ieee80211_macaddr_sprintf(wh->i_addr1));
+ ieee80211_macaddr_sprintf(wh->i_addr1));
(void) strncat(buf1, buf2, sizeof (buf2));
break;
case IEEE80211_FC1_DIR_FROMDS:
(void) snprintf(buf2, sizeof (buf2), "FRDS %s",
- ieee80211_macaddr_sprintf(wh->i_addr3));
+ ieee80211_macaddr_sprintf(wh->i_addr3));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "->%s",
- ieee80211_macaddr_sprintf(wh->i_addr1));
+ ieee80211_macaddr_sprintf(wh->i_addr1));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "(%s)",
- ieee80211_macaddr_sprintf(wh->i_addr2));
+ ieee80211_macaddr_sprintf(wh->i_addr2));
(void) strncat(buf1, buf2, sizeof (buf2));
break;
case IEEE80211_FC1_DIR_DSTODS:
(void) snprintf(buf2, sizeof (buf2), "DSDS %s",
- ieee80211_macaddr_sprintf((uint8_t *)&wh[1]));
+ ieee80211_macaddr_sprintf((uint8_t *)&wh[1]));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "->%s ",
- ieee80211_macaddr_sprintf(wh->i_addr3));
+ ieee80211_macaddr_sprintf(wh->i_addr3));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "%s",
- ieee80211_macaddr_sprintf(wh->i_addr2));
+ ieee80211_macaddr_sprintf(wh->i_addr2));
(void) strncat(buf1, buf2, sizeof (buf2));
(void) snprintf(buf2, sizeof (buf2), "->%s",
- ieee80211_macaddr_sprintf(wh->i_addr1));
+ ieee80211_macaddr_sprintf(wh->i_addr1));
(void) strncat(buf1, buf2, sizeof (buf2));
break;
}
@@ -161,13 +159,13 @@ ieee80211_dump_pkt(const uint8_t *buf, int32_t len, int32_t rate, int32_t rssi)
break;
case IEEE80211_FC0_TYPE_MGT:
(void) snprintf(buf2, sizeof (buf2), "%s",
- ieee80211_mgt_subtype_name[
- (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
- >> IEEE80211_FC0_SUBTYPE_SHIFT]);
+ ieee80211_mgt_subtype_name[
+ (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
+ >> IEEE80211_FC0_SUBTYPE_SHIFT]);
break;
default:
(void) snprintf(buf2, sizeof (buf2), "type#%d",
- wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
+ wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
break;
}
(void) strncat(buf1, buf2, sizeof (buf2));
@@ -194,7 +192,7 @@ ieee80211_dump_pkt(const uint8_t *buf, int32_t len, int32_t rate, int32_t rssi)
(void) strncat(buf1, buf2, 3);
}
ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_dump_pkt(): %s",
- buf1);
+ buf1);
}
}
@@ -327,7 +325,7 @@ ieee80211_reset_erp(ieee80211com_t *ic)
* the driver is capable of doing it.
*/
ieee80211_set_shortslottime(ic,
- ic->ic_curmode == IEEE80211_MODE_11A);
+ ic->ic_curmode == IEEE80211_MODE_11A);
/*
* Set short preamble and ERP barker-preamble flags.
*/
@@ -424,7 +422,7 @@ ieee80211_beacon_miss(ieee80211com_t *ic)
if (ic->ic_flags & IEEE80211_F_SCAN)
return;
ieee80211_dbg(IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
- "%s\n", "beacon miss");
+ "%s\n", "beacon miss");
/*
* Our handling is only meaningful for stations that are
@@ -446,9 +444,9 @@ ieee80211_beacon_miss(ieee80211com_t *ic)
*/
IEEE80211_UNLOCK(ic);
(void) ieee80211_send_probereq(ic->ic_bss, ic->ic_macaddr,
- ic->ic_bss->in_bssid, ic->ic_bss->in_bssid,
- ic->ic_bss->in_essid, ic->ic_bss->in_esslen,
- ic->ic_opt_ie, ic->ic_opt_ie_len);
+ ic->ic_bss->in_bssid, ic->ic_bss->in_bssid,
+ ic->ic_bss->in_essid, ic->ic_bss->in_esslen,
+ ic->ic_opt_ie, ic->ic_opt_ie_len);
return;
}
im->im_bmiss_count = 0;
@@ -470,8 +468,8 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
IEEE80211_LOCK(ic);
ostate = ic->ic_state;
ieee80211_dbg(IEEE80211_MSG_STATE, "ieee80211_newstate(): "
- "%s -> %s\n",
- ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
+ "%s -> %s\n",
+ ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
ic->ic_state = nstate;
in = ic->ic_bss;
im->im_swbmiss_period = 0; /* Reset software beacon miss period */
@@ -490,16 +488,23 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
case IEEE80211_S_ASSOC:
if (ic->ic_opmode == IEEE80211_M_STA) {
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_DEAUTH,
- IEEE80211_REASON_AUTH_LEAVE);
+ IEEE80211_FC0_SUBTYPE_DEAUTH,
+ IEEE80211_REASON_AUTH_LEAVE);
}
break;
case IEEE80211_S_RUN:
- if (ic->ic_opmode == IEEE80211_M_STA) {
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_STA:
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_DISASSOC,
- IEEE80211_REASON_ASSOC_LEAVE);
+ IEEE80211_FC0_SUBTYPE_DISASSOC,
+ IEEE80211_REASON_ASSOC_LEAVE);
ieee80211_sta_leave(ic, in);
+ break;
+ case IEEE80211_M_IBSS:
+ ieee80211_notify_node_leave(ic, in);
+ break;
+ default:
+ break;
}
break;
}
@@ -510,20 +515,9 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
case IEEE80211_S_SCAN:
switch (ostate) {
case IEEE80211_S_INIT:
- if (ic->ic_opmode == IEEE80211_M_IBSS &&
- ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
- /*
- * AP operation and we already have a channel;
- * bypass the scan and startup immediately.
- */
- ieee80211_create_ibss(ic, ic->ic_des_chan);
- } else {
- IEEE80211_UNLOCK(ic);
- ieee80211_begin_scan(ic,
- (arg == 0) ? B_FALSE : B_TRUE);
- return (0);
- }
- break;
+ IEEE80211_UNLOCK(ic);
+ ieee80211_begin_scan(ic, (arg == 0) ? B_FALSE : B_TRUE);
+ return (0);
case IEEE80211_S_SCAN:
/*
* Scan next. If doing an active scan and the
@@ -535,18 +529,18 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
!IEEE80211_IS_CHAN_PASSIVE(ic->ic_curchan)) {
IEEE80211_UNLOCK(ic);
(void) ieee80211_send_probereq(in,
- ic->ic_macaddr, wifi_bcastaddr,
- wifi_bcastaddr,
- ic->ic_des_essid, ic->ic_des_esslen,
- ic->ic_opt_ie, ic->ic_opt_ie_len);
+ ic->ic_macaddr, wifi_bcastaddr,
+ wifi_bcastaddr,
+ ic->ic_des_essid, ic->ic_des_esslen,
+ ic->ic_opt_ie, ic->ic_opt_ie_len);
return (0);
}
break;
case IEEE80211_S_RUN:
/* beacon miss */
ieee80211_dbg(IEEE80211_MSG_STATE,
- "no recent beacons from %s, rescanning\n",
- ieee80211_macaddr_sprintf(in->in_macaddr));
+ "no recent beacons from %s, rescanning\n",
+ ieee80211_macaddr_sprintf(in->in_macaddr));
IEEE80211_UNLOCK(ic);
ieee80211_sta_leave(ic, in);
IEEE80211_LOCK(ic);
@@ -556,7 +550,7 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
case IEEE80211_S_ASSOC:
/* timeout restart scan */
in = ieee80211_find_node(&ic->ic_scan,
- ic->ic_bss->in_macaddr);
+ ic->ic_bss->in_macaddr);
if (in != NULL) {
in->in_fails++;
ieee80211_unref_node(&in);
@@ -565,12 +559,13 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
}
break;
case IEEE80211_S_AUTH:
+ ASSERT(ic->ic_opmode == IEEE80211_M_STA);
switch (ostate) {
case IEEE80211_S_INIT:
case IEEE80211_S_SCAN:
IEEE80211_UNLOCK(ic);
IEEE80211_SEND_MGMT(ic, in, IEEE80211_FC0_SUBTYPE_AUTH,
- 1);
+ 1);
return (0);
case IEEE80211_S_AUTH:
case IEEE80211_S_ASSOC:
@@ -578,7 +573,7 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
case IEEE80211_FC0_SUBTYPE_AUTH:
IEEE80211_UNLOCK(ic);
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_AUTH, 2);
+ IEEE80211_FC0_SUBTYPE_AUTH, 2);
return (0);
case IEEE80211_FC0_SUBTYPE_DEAUTH:
/* ignore and retry scan on timeout */
@@ -591,37 +586,38 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
ic->ic_state = ostate; /* stay RUN */
IEEE80211_UNLOCK(ic);
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_AUTH, 2);
+ IEEE80211_FC0_SUBTYPE_AUTH, 2);
return (0);
case IEEE80211_FC0_SUBTYPE_DEAUTH:
IEEE80211_UNLOCK(ic);
ieee80211_sta_leave(ic, in);
/* try to re-auth */
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_AUTH, 1);
+ IEEE80211_FC0_SUBTYPE_AUTH, 1);
return (0);
}
break;
}
break;
case IEEE80211_S_ASSOC:
+ ASSERT(ic->ic_opmode == IEEE80211_M_STA);
switch (ostate) {
case IEEE80211_S_INIT:
case IEEE80211_S_SCAN:
case IEEE80211_S_ASSOC:
ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_newstate: "
- "invalid transition\n");
+ "invalid transition\n");
break;
case IEEE80211_S_AUTH:
IEEE80211_UNLOCK(ic);
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
+ IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
return (0);
case IEEE80211_S_RUN:
IEEE80211_UNLOCK(ic);
ieee80211_sta_leave(ic, in);
IEEE80211_SEND_MGMT(ic, in,
- IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
+ IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
return (0);
}
break;
@@ -629,18 +625,17 @@ ieee80211_newstate(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
switch (ostate) {
case IEEE80211_S_INIT:
ieee80211_err("ieee80211_newstate: "
- "invalid transition\n");
+ "invalid transition\n");
break;
case IEEE80211_S_AUTH:
ieee80211_err("ieee80211_newstate: "
- "invalid transition\n");
+ "invalid transition\n");
break;
case IEEE80211_S_SCAN: /* adhoc/hostap mode */
case IEEE80211_S_ASSOC: /* infra mode */
ASSERT(in->in_txrate < in->in_rates.ir_nrates);
im->im_mgt_timer = 0;
- if (ic->ic_opmode == IEEE80211_M_STA)
- ieee80211_notify_node_join(ic, in);
+ ieee80211_notify_node_join(ic, in);
/*
* We can send data now; update the fastpath with our