diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 382 |
1 files changed, 182 insertions, 200 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 0db5d34a06b6..cef0c9e79aba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -258,12 +258,11 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | |||
258 | } | 258 | } |
259 | 259 | ||
260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | 260 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
261 | struct sk_buff *skb, const u8 *ht_oper_ie, | 261 | struct sk_buff *skb, u8 ap_ht_param, |
262 | struct ieee80211_supported_band *sband, | 262 | struct ieee80211_supported_band *sband, |
263 | struct ieee80211_channel *channel, | 263 | struct ieee80211_channel *channel, |
264 | enum ieee80211_smps_mode smps) | 264 | enum ieee80211_smps_mode smps) |
265 | { | 265 | { |
266 | struct ieee80211_ht_operation *ht_oper; | ||
267 | u8 *pos; | 266 | u8 *pos; |
268 | u32 flags = channel->flags; | 267 | u32 flags = channel->flags; |
269 | u16 cap; | 268 | u16 cap; |
@@ -271,21 +270,13 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
271 | 270 | ||
272 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); | 271 | BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap)); |
273 | 272 | ||
274 | if (!ht_oper_ie) | ||
275 | return; | ||
276 | |||
277 | if (ht_oper_ie[1] < sizeof(struct ieee80211_ht_operation)) | ||
278 | return; | ||
279 | |||
280 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | 273 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); |
281 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | 274 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); |
282 | 275 | ||
283 | ht_oper = (struct ieee80211_ht_operation *)(ht_oper_ie + 2); | ||
284 | |||
285 | /* determine capability flags */ | 276 | /* determine capability flags */ |
286 | cap = ht_cap.cap; | 277 | cap = ht_cap.cap; |
287 | 278 | ||
288 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 279 | switch (ap_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
289 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 280 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
290 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | 281 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { |
291 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 282 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -509,7 +500,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
509 | } | 500 | } |
510 | 501 | ||
511 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 502 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
512 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_operation_ie, | 503 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
513 | sband, local->oper_channel, ifmgd->ap_smps); | 504 | sband, local->oper_channel, ifmgd->ap_smps); |
514 | 505 | ||
515 | /* if present, add any custom non-vendor IEs that go after HT */ | 506 | /* if present, add any custom non-vendor IEs that go after HT */ |
@@ -550,6 +541,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
550 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | 541 | memcpy(pos, assoc_data->ie + offset, noffset - offset); |
551 | } | 542 | } |
552 | 543 | ||
544 | drv_mgd_prepare_tx(local, sdata); | ||
545 | |||
553 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 546 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
554 | ieee80211_tx_skb(sdata, skb); | 547 | ieee80211_tx_skb(sdata, skb); |
555 | } | 548 | } |
@@ -589,6 +582,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
589 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) | 582 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) |
590 | IEEE80211_SKB_CB(skb)->flags |= | 583 | IEEE80211_SKB_CB(skb)->flags |= |
591 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | 584 | IEEE80211_TX_INTFL_DONT_ENCRYPT; |
585 | |||
586 | drv_mgd_prepare_tx(local, sdata); | ||
587 | |||
592 | ieee80211_tx_skb(sdata, skb); | 588 | ieee80211_tx_skb(sdata, skb); |
593 | } | 589 | } |
594 | } | 590 | } |
@@ -911,9 +907,6 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata) | |||
911 | if (!mgd->associated) | 907 | if (!mgd->associated) |
912 | return false; | 908 | return false; |
913 | 909 | ||
914 | if (!mgd->associated->beacon_ies) | ||
915 | return false; | ||
916 | |||
917 | if (mgd->flags & (IEEE80211_STA_BEACON_POLL | | 910 | if (mgd->flags & (IEEE80211_STA_BEACON_POLL | |
918 | IEEE80211_STA_CONNECTION_POLL)) | 911 | IEEE80211_STA_CONNECTION_POLL)) |
919 | return false; | 912 | return false; |
@@ -939,11 +932,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
939 | return; | 932 | return; |
940 | } | 933 | } |
941 | 934 | ||
942 | if (!list_empty(&local->work_list)) { | ||
943 | local->ps_sdata = NULL; | ||
944 | goto change; | ||
945 | } | ||
946 | |||
947 | list_for_each_entry(sdata, &local->interfaces, list) { | 935 | list_for_each_entry(sdata, &local->interfaces, list) { |
948 | if (!ieee80211_sdata_running(sdata)) | 936 | if (!ieee80211_sdata_running(sdata)) |
949 | continue; | 937 | continue; |
@@ -1016,7 +1004,6 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1016 | local->ps_sdata = NULL; | 1004 | local->ps_sdata = NULL; |
1017 | } | 1005 | } |
1018 | 1006 | ||
1019 | change: | ||
1020 | ieee80211_change_ps(local); | 1007 | ieee80211_change_ps(local); |
1021 | } | 1008 | } |
1022 | 1009 | ||
@@ -1121,7 +1108,7 @@ void ieee80211_dynamic_ps_timer(unsigned long data) | |||
1121 | } | 1108 | } |
1122 | 1109 | ||
1123 | /* MLME */ | 1110 | /* MLME */ |
1124 | static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | 1111 | static bool ieee80211_sta_wmm_params(struct ieee80211_local *local, |
1125 | struct ieee80211_sub_if_data *sdata, | 1112 | struct ieee80211_sub_if_data *sdata, |
1126 | u8 *wmm_param, size_t wmm_param_len) | 1113 | u8 *wmm_param, size_t wmm_param_len) |
1127 | { | 1114 | { |
@@ -1132,23 +1119,23 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1132 | u8 *pos, uapsd_queues = 0; | 1119 | u8 *pos, uapsd_queues = 0; |
1133 | 1120 | ||
1134 | if (!local->ops->conf_tx) | 1121 | if (!local->ops->conf_tx) |
1135 | return; | 1122 | return false; |
1136 | 1123 | ||
1137 | if (local->hw.queues < IEEE80211_NUM_ACS) | 1124 | if (local->hw.queues < IEEE80211_NUM_ACS) |
1138 | return; | 1125 | return false; |
1139 | 1126 | ||
1140 | if (!wmm_param) | 1127 | if (!wmm_param) |
1141 | return; | 1128 | return false; |
1142 | 1129 | ||
1143 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) | 1130 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) |
1144 | return; | 1131 | return false; |
1145 | 1132 | ||
1146 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) | 1133 | if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED) |
1147 | uapsd_queues = ifmgd->uapsd_queues; | 1134 | uapsd_queues = ifmgd->uapsd_queues; |
1148 | 1135 | ||
1149 | count = wmm_param[6] & 0x0f; | 1136 | count = wmm_param[6] & 0x0f; |
1150 | if (count == ifmgd->wmm_last_param_set) | 1137 | if (count == ifmgd->wmm_last_param_set) |
1151 | return; | 1138 | return false; |
1152 | ifmgd->wmm_last_param_set = count; | 1139 | ifmgd->wmm_last_param_set = count; |
1153 | 1140 | ||
1154 | pos = wmm_param + 8; | 1141 | pos = wmm_param + 8; |
@@ -1156,7 +1143,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1156 | 1143 | ||
1157 | memset(¶ms, 0, sizeof(params)); | 1144 | memset(¶ms, 0, sizeof(params)); |
1158 | 1145 | ||
1159 | local->wmm_acm = 0; | 1146 | sdata->wmm_acm = 0; |
1160 | for (; left >= 4; left -= 4, pos += 4) { | 1147 | for (; left >= 4; left -= 4, pos += 4) { |
1161 | int aci = (pos[0] >> 5) & 0x03; | 1148 | int aci = (pos[0] >> 5) & 0x03; |
1162 | int acm = (pos[0] >> 4) & 0x01; | 1149 | int acm = (pos[0] >> 4) & 0x01; |
@@ -1167,21 +1154,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1167 | case 1: /* AC_BK */ | 1154 | case 1: /* AC_BK */ |
1168 | queue = 3; | 1155 | queue = 3; |
1169 | if (acm) | 1156 | if (acm) |
1170 | local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ | 1157 | sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */ |
1171 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) | 1158 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) |
1172 | uapsd = true; | 1159 | uapsd = true; |
1173 | break; | 1160 | break; |
1174 | case 2: /* AC_VI */ | 1161 | case 2: /* AC_VI */ |
1175 | queue = 1; | 1162 | queue = 1; |
1176 | if (acm) | 1163 | if (acm) |
1177 | local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ | 1164 | sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */ |
1178 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) | 1165 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) |
1179 | uapsd = true; | 1166 | uapsd = true; |
1180 | break; | 1167 | break; |
1181 | case 3: /* AC_VO */ | 1168 | case 3: /* AC_VO */ |
1182 | queue = 0; | 1169 | queue = 0; |
1183 | if (acm) | 1170 | if (acm) |
1184 | local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ | 1171 | sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */ |
1185 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) | 1172 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) |
1186 | uapsd = true; | 1173 | uapsd = true; |
1187 | break; | 1174 | break; |
@@ -1189,7 +1176,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1189 | default: | 1176 | default: |
1190 | queue = 2; | 1177 | queue = 2; |
1191 | if (acm) | 1178 | if (acm) |
1192 | local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ | 1179 | sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */ |
1193 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) | 1180 | if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) |
1194 | uapsd = true; | 1181 | uapsd = true; |
1195 | break; | 1182 | break; |
@@ -1201,23 +1188,21 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
1201 | params.txop = get_unaligned_le16(pos + 2); | 1188 | params.txop = get_unaligned_le16(pos + 2); |
1202 | params.uapsd = uapsd; | 1189 | params.uapsd = uapsd; |
1203 | 1190 | ||
1204 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 1191 | mlme_dbg(sdata, |
1205 | wiphy_debug(local->hw.wiphy, | 1192 | "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d\n", |
1206 | "WMM queue=%d aci=%d acm=%d aifs=%d " | 1193 | queue, aci, acm, |
1207 | "cWmin=%d cWmax=%d txop=%d uapsd=%d\n", | 1194 | params.aifs, params.cw_min, params.cw_max, |
1208 | queue, aci, acm, | 1195 | params.txop, params.uapsd); |
1209 | params.aifs, params.cw_min, params.cw_max, | ||
1210 | params.txop, params.uapsd); | ||
1211 | #endif | ||
1212 | sdata->tx_conf[queue] = params; | 1196 | sdata->tx_conf[queue] = params; |
1213 | if (drv_conf_tx(local, sdata, queue, ¶ms)) | 1197 | if (drv_conf_tx(local, sdata, queue, ¶ms)) |
1214 | wiphy_debug(local->hw.wiphy, | 1198 | sdata_err(sdata, |
1215 | "failed to set TX queue parameters for queue %d\n", | 1199 | "failed to set TX queue parameters for queue %d\n", |
1216 | queue); | 1200 | queue); |
1217 | } | 1201 | } |
1218 | 1202 | ||
1219 | /* enable WMM or activate new settings */ | 1203 | /* enable WMM or activate new settings */ |
1220 | sdata->vif.bss_conf.qos = true; | 1204 | sdata->vif.bss_conf.qos = true; |
1205 | return true; | ||
1221 | } | 1206 | } |
1222 | 1207 | ||
1223 | static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) | 1208 | static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) |
@@ -1284,13 +1269,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1284 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 1269 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1285 | 1270 | ||
1286 | bss_info_changed |= BSS_CHANGED_ASSOC; | 1271 | bss_info_changed |= BSS_CHANGED_ASSOC; |
1287 | /* set timing information */ | ||
1288 | bss_conf->beacon_int = cbss->beacon_interval; | ||
1289 | bss_conf->last_tsf = cbss->tsf; | ||
1290 | |||
1291 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | ||
1292 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 1272 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
1293 | cbss->capability, bss->has_erp_value, bss->erp_value); | 1273 | bss_conf->assoc_capability, bss->has_erp_value, bss->erp_value); |
1294 | 1274 | ||
1295 | sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( | 1275 | sdata->u.mgd.beacon_timeout = usecs_to_jiffies(ieee80211_tu_to_usec( |
1296 | IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); | 1276 | IEEE80211_BEACON_LOSS_COUNT * bss_conf->beacon_int)); |
@@ -1380,6 +1360,21 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1380 | } | 1360 | } |
1381 | mutex_unlock(&local->sta_mtx); | 1361 | mutex_unlock(&local->sta_mtx); |
1382 | 1362 | ||
1363 | /* | ||
1364 | * if we want to get out of ps before disassoc (why?) we have | ||
1365 | * to do it before sending disassoc, as otherwise the null-packet | ||
1366 | * won't be valid. | ||
1367 | */ | ||
1368 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1369 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
1370 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
1371 | } | ||
1372 | local->ps_sdata = NULL; | ||
1373 | |||
1374 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | ||
1375 | if (tx) | ||
1376 | drv_flush(local, false); | ||
1377 | |||
1383 | /* deauthenticate/disassociate now */ | 1378 | /* deauthenticate/disassociate now */ |
1384 | if (tx || frame_buf) | 1379 | if (tx || frame_buf) |
1385 | ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, | 1380 | ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, |
@@ -1411,12 +1406,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1411 | del_timer_sync(&local->dynamic_ps_timer); | 1406 | del_timer_sync(&local->dynamic_ps_timer); |
1412 | cancel_work_sync(&local->dynamic_ps_enable_work); | 1407 | cancel_work_sync(&local->dynamic_ps_enable_work); |
1413 | 1408 | ||
1414 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1415 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
1416 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
1417 | } | ||
1418 | local->ps_sdata = NULL; | ||
1419 | |||
1420 | /* Disable ARP filtering */ | 1409 | /* Disable ARP filtering */ |
1421 | if (sdata->vif.bss_conf.arp_filter_enabled) { | 1410 | if (sdata->vif.bss_conf.arp_filter_enabled) { |
1422 | sdata->vif.bss_conf.arp_filter_enabled = false; | 1411 | sdata->vif.bss_conf.arp_filter_enabled = false; |
@@ -1581,11 +1570,12 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1581 | goto out; | 1570 | goto out; |
1582 | } | 1571 | } |
1583 | 1572 | ||
1584 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
1585 | if (beacon) | 1573 | if (beacon) |
1586 | net_dbg_ratelimited("%s: detected beacon loss from AP - sending probe request\n", | 1574 | mlme_dbg_ratelimited(sdata, |
1587 | sdata->name); | 1575 | "detected beacon loss from AP - sending probe request\n"); |
1588 | #endif | 1576 | |
1577 | ieee80211_cqm_rssi_notify(&sdata->vif, | ||
1578 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); | ||
1589 | 1579 | ||
1590 | /* | 1580 | /* |
1591 | * The driver/our work has already reported this event or the | 1581 | * The driver/our work has already reported this event or the |
@@ -1627,6 +1617,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1627 | { | 1617 | { |
1628 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 1618 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
1629 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1619 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1620 | struct cfg80211_bss *cbss; | ||
1630 | struct sk_buff *skb; | 1621 | struct sk_buff *skb; |
1631 | const u8 *ssid; | 1622 | const u8 *ssid; |
1632 | int ssid_len; | 1623 | int ssid_len; |
@@ -1636,16 +1627,22 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1636 | 1627 | ||
1637 | ASSERT_MGD_MTX(ifmgd); | 1628 | ASSERT_MGD_MTX(ifmgd); |
1638 | 1629 | ||
1639 | if (!ifmgd->associated) | 1630 | if (ifmgd->associated) |
1631 | cbss = ifmgd->associated; | ||
1632 | else if (ifmgd->auth_data) | ||
1633 | cbss = ifmgd->auth_data->bss; | ||
1634 | else if (ifmgd->assoc_data) | ||
1635 | cbss = ifmgd->assoc_data->bss; | ||
1636 | else | ||
1640 | return NULL; | 1637 | return NULL; |
1641 | 1638 | ||
1642 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); | 1639 | ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); |
1643 | if (WARN_ON_ONCE(ssid == NULL)) | 1640 | if (WARN_ON_ONCE(ssid == NULL)) |
1644 | ssid_len = 0; | 1641 | ssid_len = 0; |
1645 | else | 1642 | else |
1646 | ssid_len = ssid[1]; | 1643 | ssid_len = ssid[1]; |
1647 | 1644 | ||
1648 | skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid, | 1645 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, |
1649 | (u32) -1, ssid + 2, ssid_len, | 1646 | (u32) -1, ssid + 2, ssid_len, |
1650 | NULL, 0, true); | 1647 | NULL, 0, true); |
1651 | 1648 | ||
@@ -1668,8 +1665,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1668 | 1665 | ||
1669 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1666 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1670 | 1667 | ||
1671 | printk(KERN_DEBUG "%s: Connection to AP %pM lost.\n", | 1668 | sdata_info(sdata, "Connection to AP %pM lost\n", bssid); |
1672 | sdata->name, bssid); | ||
1673 | 1669 | ||
1674 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 1670 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
1675 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1671 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
@@ -1765,6 +1761,7 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | |||
1765 | if (!elems.challenge) | 1761 | if (!elems.challenge) |
1766 | return; | 1762 | return; |
1767 | auth_data->expected_transaction = 4; | 1763 | auth_data->expected_transaction = 4; |
1764 | drv_mgd_prepare_tx(sdata->local, sdata); | ||
1768 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, | 1765 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, |
1769 | elems.challenge - 2, elems.challenge_len + 2, | 1766 | elems.challenge - 2, elems.challenge_len + 2, |
1770 | auth_data->bss->bssid, auth_data->bss->bssid, | 1767 | auth_data->bss->bssid, auth_data->bss->bssid, |
@@ -1803,9 +1800,10 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1803 | return RX_MGMT_NONE; | 1800 | return RX_MGMT_NONE; |
1804 | 1801 | ||
1805 | if (status_code != WLAN_STATUS_SUCCESS) { | 1802 | if (status_code != WLAN_STATUS_SUCCESS) { |
1806 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | 1803 | sdata_info(sdata, "%pM denied authentication (status %d)\n", |
1807 | sdata->name, mgmt->sa, status_code); | 1804 | mgmt->sa, status_code); |
1808 | goto out; | 1805 | ieee80211_destroy_auth_data(sdata, false); |
1806 | return RX_MGMT_CFG80211_RX_AUTH; | ||
1809 | } | 1807 | } |
1810 | 1808 | ||
1811 | switch (ifmgd->auth_data->algorithm) { | 1809 | switch (ifmgd->auth_data->algorithm) { |
@@ -1826,8 +1824,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1826 | return RX_MGMT_NONE; | 1824 | return RX_MGMT_NONE; |
1827 | } | 1825 | } |
1828 | 1826 | ||
1829 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); | 1827 | sdata_info(sdata, "authenticated\n"); |
1830 | out: | ||
1831 | ifmgd->auth_data->done = true; | 1828 | ifmgd->auth_data->done = true; |
1832 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; | 1829 | ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; |
1833 | run_again(ifmgd, ifmgd->auth_data->timeout); | 1830 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -1840,8 +1837,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1840 | goto out_err; | 1837 | goto out_err; |
1841 | } | 1838 | } |
1842 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { | 1839 | if (sta_info_move_state(sta, IEEE80211_STA_AUTH)) { |
1843 | printk(KERN_DEBUG "%s: failed moving %pM to auth\n", | 1840 | sdata_info(sdata, "failed moving %pM to auth\n", bssid); |
1844 | sdata->name, bssid); | ||
1845 | goto out_err; | 1841 | goto out_err; |
1846 | } | 1842 | } |
1847 | mutex_unlock(&sdata->local->sta_mtx); | 1843 | mutex_unlock(&sdata->local->sta_mtx); |
@@ -1875,8 +1871,8 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1875 | 1871 | ||
1876 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1872 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1877 | 1873 | ||
1878 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 1874 | sdata_info(sdata, "deauthenticated from %pM (Reason: %u)\n", |
1879 | sdata->name, bssid, reason_code); | 1875 | bssid, reason_code); |
1880 | 1876 | ||
1881 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 1877 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
1882 | 1878 | ||
@@ -1906,8 +1902,8 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1906 | 1902 | ||
1907 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1903 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1908 | 1904 | ||
1909 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 1905 | sdata_info(sdata, "disassociated from %pM (Reason: %u)\n", |
1910 | sdata->name, mgmt->sa, reason_code); | 1906 | mgmt->sa, reason_code); |
1911 | 1907 | ||
1912 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 1908 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
1913 | 1909 | ||
@@ -1999,17 +1995,15 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
1999 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | 1995 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); |
2000 | 1996 | ||
2001 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1997 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
2002 | printk(KERN_DEBUG | 1998 | sdata_info(sdata, "invalid AID value 0x%x; bits 15:14 not set\n", |
2003 | "%s: invalid AID value 0x%x; bits 15:14 not set\n", | 1999 | aid); |
2004 | sdata->name, aid); | ||
2005 | aid &= ~(BIT(15) | BIT(14)); | 2000 | aid &= ~(BIT(15) | BIT(14)); |
2006 | 2001 | ||
2007 | ifmgd->broken_ap = false; | 2002 | ifmgd->broken_ap = false; |
2008 | 2003 | ||
2009 | if (aid == 0 || aid > IEEE80211_MAX_AID) { | 2004 | if (aid == 0 || aid > IEEE80211_MAX_AID) { |
2010 | printk(KERN_DEBUG | 2005 | sdata_info(sdata, "invalid AID value %d (out of range), turn off PS\n", |
2011 | "%s: invalid AID value %d (out of range), turn off PS\n", | 2006 | aid); |
2012 | sdata->name, aid); | ||
2013 | aid = 0; | 2007 | aid = 0; |
2014 | ifmgd->broken_ap = true; | 2008 | ifmgd->broken_ap = true; |
2015 | } | 2009 | } |
@@ -2018,8 +2012,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2018 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2012 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
2019 | 2013 | ||
2020 | if (!elems.supp_rates) { | 2014 | if (!elems.supp_rates) { |
2021 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 2015 | sdata_info(sdata, "no SuppRates element in AssocResp\n"); |
2022 | sdata->name); | ||
2023 | return false; | 2016 | return false; |
2024 | } | 2017 | } |
2025 | 2018 | ||
@@ -2059,9 +2052,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2059 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) | 2052 | if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) |
2060 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); | 2053 | err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); |
2061 | if (err) { | 2054 | if (err) { |
2062 | printk(KERN_DEBUG | 2055 | sdata_info(sdata, |
2063 | "%s: failed to move station %pM to desired state\n", | 2056 | "failed to move station %pM to desired state\n", |
2064 | sdata->name, sta->sta.addr); | 2057 | sta->sta.addr); |
2065 | WARN_ON(__sta_info_destroy(sta)); | 2058 | WARN_ON(__sta_info_destroy(sta)); |
2066 | mutex_unlock(&sdata->local->sta_mtx); | 2059 | mutex_unlock(&sdata->local->sta_mtx); |
2067 | return false; | 2060 | return false; |
@@ -2144,10 +2137,10 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2144 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 2137 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
2145 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 2138 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
2146 | 2139 | ||
2147 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | 2140 | sdata_info(sdata, |
2148 | "status=%d aid=%d)\n", | 2141 | "RX %sssocResp from %pM (capab=0x%x status=%d aid=%d)\n", |
2149 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | 2142 | reassoc ? "Rea" : "A", mgmt->sa, |
2150 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 2143 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
2151 | 2144 | ||
2152 | pos = mgmt->u.assoc_resp.variable; | 2145 | pos = mgmt->u.assoc_resp.variable; |
2153 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 2146 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
@@ -2158,9 +2151,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2158 | u32 tu, ms; | 2151 | u32 tu, ms; |
2159 | tu = get_unaligned_le32(elems.timeout_int + 1); | 2152 | tu = get_unaligned_le32(elems.timeout_int + 1); |
2160 | ms = tu * 1024 / 1000; | 2153 | ms = tu * 1024 / 1000; |
2161 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | 2154 | sdata_info(sdata, |
2162 | "comeback duration %u TU (%u ms)\n", | 2155 | "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n", |
2163 | sdata->name, mgmt->sa, tu, ms); | 2156 | mgmt->sa, tu, ms); |
2164 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); | 2157 | assoc_data->timeout = jiffies + msecs_to_jiffies(ms); |
2165 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 2158 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
2166 | run_again(ifmgd, assoc_data->timeout); | 2159 | run_again(ifmgd, assoc_data->timeout); |
@@ -2170,8 +2163,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2170 | *bss = assoc_data->bss; | 2163 | *bss = assoc_data->bss; |
2171 | 2164 | ||
2172 | if (status_code != WLAN_STATUS_SUCCESS) { | 2165 | if (status_code != WLAN_STATUS_SUCCESS) { |
2173 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | 2166 | sdata_info(sdata, "%pM denied association (code=%d)\n", |
2174 | sdata->name, mgmt->sa, status_code); | 2167 | mgmt->sa, status_code); |
2175 | ieee80211_destroy_assoc_data(sdata, false); | 2168 | ieee80211_destroy_assoc_data(sdata, false); |
2176 | } else { | 2169 | } else { |
2177 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { | 2170 | if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { |
@@ -2180,7 +2173,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2180 | cfg80211_put_bss(*bss); | 2173 | cfg80211_put_bss(*bss); |
2181 | return RX_MGMT_CFG80211_ASSOC_TIMEOUT; | 2174 | return RX_MGMT_CFG80211_ASSOC_TIMEOUT; |
2182 | } | 2175 | } |
2183 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | 2176 | sdata_info(sdata, "associated\n"); |
2184 | 2177 | ||
2185 | /* | 2178 | /* |
2186 | * destroy assoc_data afterwards, as otherwise an idle | 2179 | * destroy assoc_data afterwards, as otherwise an idle |
@@ -2280,7 +2273,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
2280 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && | 2273 | if (ifmgd->auth_data && !ifmgd->auth_data->bss->proberesp_ies && |
2281 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { | 2274 | ether_addr_equal(mgmt->bssid, ifmgd->auth_data->bss->bssid)) { |
2282 | /* got probe response, continue with auth */ | 2275 | /* got probe response, continue with auth */ |
2283 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | 2276 | sdata_info(sdata, "direct probe responded\n"); |
2284 | ifmgd->auth_data->tries = 0; | 2277 | ifmgd->auth_data->tries = 0; |
2285 | ifmgd->auth_data->timeout = jiffies; | 2278 | ifmgd->auth_data->timeout = jiffies; |
2286 | run_again(ifmgd, ifmgd->auth_data->timeout); | 2279 | run_again(ifmgd, ifmgd->auth_data->timeout); |
@@ -2416,10 +2409,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2416 | } | 2409 | } |
2417 | 2410 | ||
2418 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { | 2411 | if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { |
2419 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2412 | mlme_dbg_ratelimited(sdata, |
2420 | net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n", | 2413 | "cancelling probereq poll due to a received beacon\n"); |
2421 | sdata->name); | ||
2422 | #endif | ||
2423 | mutex_lock(&local->mtx); | 2414 | mutex_lock(&local->mtx); |
2424 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; | 2415 | ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; |
2425 | ieee80211_run_deferred_scan(local); | 2416 | ieee80211_run_deferred_scan(local); |
@@ -2445,14 +2436,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2445 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, | 2436 | directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, |
2446 | ifmgd->aid); | 2437 | ifmgd->aid); |
2447 | 2438 | ||
2448 | if (ncrc != ifmgd->beacon_crc || !ifmgd->beacon_crc_valid) { | ||
2449 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | ||
2450 | true); | ||
2451 | |||
2452 | ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
2453 | elems.wmm_param_len); | ||
2454 | } | ||
2455 | |||
2456 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { | 2439 | if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { |
2457 | if (directed_tim) { | 2440 | if (directed_tim) { |
2458 | if (local->hw.conf.dynamic_ps_timeout > 0) { | 2441 | if (local->hw.conf.dynamic_ps_timeout > 0) { |
@@ -2483,6 +2466,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2483 | ifmgd->beacon_crc = ncrc; | 2466 | ifmgd->beacon_crc = ncrc; |
2484 | ifmgd->beacon_crc_valid = true; | 2467 | ifmgd->beacon_crc_valid = true; |
2485 | 2468 | ||
2469 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, | ||
2470 | true); | ||
2471 | |||
2472 | if (ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, | ||
2473 | elems.wmm_param_len)) | ||
2474 | changed |= BSS_CHANGED_QOS; | ||
2475 | |||
2486 | if (elems.erp_info && elems.erp_info_len >= 1) { | 2476 | if (elems.erp_info && elems.erp_info_len >= 1) { |
2487 | erp_valid = true; | 2477 | erp_valid = true; |
2488 | erp_value = elems.erp_info[0]; | 2478 | erp_value = elems.erp_info[0]; |
@@ -2642,8 +2632,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2642 | auth_data->tries++; | 2632 | auth_data->tries++; |
2643 | 2633 | ||
2644 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | 2634 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { |
2645 | printk(KERN_DEBUG "%s: authentication with %pM timed out\n", | 2635 | sdata_info(sdata, "authentication with %pM timed out\n", |
2646 | sdata->name, auth_data->bss->bssid); | 2636 | auth_data->bss->bssid); |
2647 | 2637 | ||
2648 | /* | 2638 | /* |
2649 | * Most likely AP is not in the range so remove the | 2639 | * Most likely AP is not in the range so remove the |
@@ -2654,10 +2644,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2654 | return -ETIMEDOUT; | 2644 | return -ETIMEDOUT; |
2655 | } | 2645 | } |
2656 | 2646 | ||
2647 | drv_mgd_prepare_tx(local, sdata); | ||
2648 | |||
2657 | if (auth_data->bss->proberesp_ies) { | 2649 | if (auth_data->bss->proberesp_ies) { |
2658 | printk(KERN_DEBUG "%s: send auth to %pM (try %d/%d)\n", | 2650 | sdata_info(sdata, "send auth to %pM (try %d/%d)\n", |
2659 | sdata->name, auth_data->bss->bssid, auth_data->tries, | 2651 | auth_data->bss->bssid, auth_data->tries, |
2660 | IEEE80211_AUTH_MAX_TRIES); | 2652 | IEEE80211_AUTH_MAX_TRIES); |
2661 | 2653 | ||
2662 | auth_data->expected_transaction = 2; | 2654 | auth_data->expected_transaction = 2; |
2663 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, | 2655 | ieee80211_send_auth(sdata, 1, auth_data->algorithm, |
@@ -2667,9 +2659,9 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2667 | } else { | 2659 | } else { |
2668 | const u8 *ssidie; | 2660 | const u8 *ssidie; |
2669 | 2661 | ||
2670 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d/%i)\n", | 2662 | sdata_info(sdata, "direct probe to %pM (try %d/%i)\n", |
2671 | sdata->name, auth_data->bss->bssid, auth_data->tries, | 2663 | auth_data->bss->bssid, auth_data->tries, |
2672 | IEEE80211_AUTH_MAX_TRIES); | 2664 | IEEE80211_AUTH_MAX_TRIES); |
2673 | 2665 | ||
2674 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); | 2666 | ssidie = ieee80211_bss_get_ie(auth_data->bss, WLAN_EID_SSID); |
2675 | if (!ssidie) | 2667 | if (!ssidie) |
@@ -2697,8 +2689,8 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2697 | 2689 | ||
2698 | assoc_data->tries++; | 2690 | assoc_data->tries++; |
2699 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { | 2691 | if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) { |
2700 | printk(KERN_DEBUG "%s: association with %pM timed out\n", | 2692 | sdata_info(sdata, "association with %pM timed out\n", |
2701 | sdata->name, assoc_data->bss->bssid); | 2693 | assoc_data->bss->bssid); |
2702 | 2694 | ||
2703 | /* | 2695 | /* |
2704 | * Most likely AP is not in the range so remove the | 2696 | * Most likely AP is not in the range so remove the |
@@ -2709,9 +2701,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2709 | return -ETIMEDOUT; | 2701 | return -ETIMEDOUT; |
2710 | } | 2702 | } |
2711 | 2703 | ||
2712 | printk(KERN_DEBUG "%s: associate with %pM (try %d/%d)\n", | 2704 | sdata_info(sdata, "associate with %pM (try %d/%d)\n", |
2713 | sdata->name, assoc_data->bss->bssid, assoc_data->tries, | 2705 | assoc_data->bss->bssid, assoc_data->tries, |
2714 | IEEE80211_ASSOC_MAX_TRIES); | 2706 | IEEE80211_ASSOC_MAX_TRIES); |
2715 | ieee80211_send_assoc(sdata); | 2707 | ieee80211_send_assoc(sdata); |
2716 | 2708 | ||
2717 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 2709 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
@@ -2784,45 +2776,31 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2784 | ieee80211_reset_ap_probe(sdata); | 2776 | ieee80211_reset_ap_probe(sdata); |
2785 | else if (ifmgd->nullfunc_failed) { | 2777 | else if (ifmgd->nullfunc_failed) { |
2786 | if (ifmgd->probe_send_count < max_tries) { | 2778 | if (ifmgd->probe_send_count < max_tries) { |
2787 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2779 | mlme_dbg(sdata, |
2788 | wiphy_debug(local->hw.wiphy, | 2780 | "No ack for nullfunc frame to AP %pM, try %d/%i\n", |
2789 | "%s: No ack for nullfunc frame to" | 2781 | bssid, ifmgd->probe_send_count, |
2790 | " AP %pM, try %d/%i\n", | 2782 | max_tries); |
2791 | sdata->name, bssid, | ||
2792 | ifmgd->probe_send_count, max_tries); | ||
2793 | #endif | ||
2794 | ieee80211_mgd_probe_ap_send(sdata); | 2783 | ieee80211_mgd_probe_ap_send(sdata); |
2795 | } else { | 2784 | } else { |
2796 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2785 | mlme_dbg(sdata, |
2797 | wiphy_debug(local->hw.wiphy, | 2786 | "No ack for nullfunc frame to AP %pM, disconnecting.\n", |
2798 | "%s: No ack for nullfunc frame to" | 2787 | bssid); |
2799 | " AP %pM, disconnecting.\n", | ||
2800 | sdata->name, bssid); | ||
2801 | #endif | ||
2802 | ieee80211_sta_connection_lost(sdata, bssid, | 2788 | ieee80211_sta_connection_lost(sdata, bssid, |
2803 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | 2789 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); |
2804 | } | 2790 | } |
2805 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) | 2791 | } else if (time_is_after_jiffies(ifmgd->probe_timeout)) |
2806 | run_again(ifmgd, ifmgd->probe_timeout); | 2792 | run_again(ifmgd, ifmgd->probe_timeout); |
2807 | else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { | 2793 | else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) { |
2808 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2794 | mlme_dbg(sdata, |
2809 | wiphy_debug(local->hw.wiphy, | 2795 | "Failed to send nullfunc to AP %pM after %dms, disconnecting\n", |
2810 | "%s: Failed to send nullfunc to AP %pM" | 2796 | bssid, probe_wait_ms); |
2811 | " after %dms, disconnecting.\n", | ||
2812 | sdata->name, | ||
2813 | bssid, probe_wait_ms); | ||
2814 | #endif | ||
2815 | ieee80211_sta_connection_lost(sdata, bssid, | 2797 | ieee80211_sta_connection_lost(sdata, bssid, |
2816 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); | 2798 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); |
2817 | } else if (ifmgd->probe_send_count < max_tries) { | 2799 | } else if (ifmgd->probe_send_count < max_tries) { |
2818 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2800 | mlme_dbg(sdata, |
2819 | wiphy_debug(local->hw.wiphy, | 2801 | "No probe response from AP %pM after %dms, try %d/%i\n", |
2820 | "%s: No probe response from AP %pM" | 2802 | bssid, probe_wait_ms, |
2821 | " after %dms, try %d/%i\n", | 2803 | ifmgd->probe_send_count, max_tries); |
2822 | sdata->name, | ||
2823 | bssid, probe_wait_ms, | ||
2824 | ifmgd->probe_send_count, max_tries); | ||
2825 | #endif | ||
2826 | ieee80211_mgd_probe_ap_send(sdata); | 2804 | ieee80211_mgd_probe_ap_send(sdata); |
2827 | } else { | 2805 | } else { |
2828 | /* | 2806 | /* |
@@ -2937,11 +2915,8 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | |||
2937 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; | 2915 | sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; |
2938 | mutex_lock(&ifmgd->mtx); | 2916 | mutex_lock(&ifmgd->mtx); |
2939 | if (ifmgd->associated) { | 2917 | if (ifmgd->associated) { |
2940 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2918 | mlme_dbg(sdata, |
2941 | wiphy_debug(sdata->local->hw.wiphy, | 2919 | "driver requested disconnect after resume\n"); |
2942 | "%s: driver requested disconnect after resume.\n", | ||
2943 | sdata->name); | ||
2944 | #endif | ||
2945 | ieee80211_sta_connection_lost(sdata, | 2920 | ieee80211_sta_connection_lost(sdata, |
2946 | ifmgd->associated->bssid, | 2921 | ifmgd->associated->bssid, |
2947 | WLAN_REASON_UNSPECIFIED); | 2922 | WLAN_REASON_UNSPECIFIED); |
@@ -2999,7 +2974,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2999 | /* scan finished notification */ | 2974 | /* scan finished notification */ |
3000 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | 2975 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) |
3001 | { | 2976 | { |
3002 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 2977 | struct ieee80211_sub_if_data *sdata; |
3003 | 2978 | ||
3004 | /* Restart STA timers */ | 2979 | /* Restart STA timers */ |
3005 | rcu_read_lock(); | 2980 | rcu_read_lock(); |
@@ -3029,7 +3004,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3029 | struct ieee80211_local *local = sdata->local; | 3004 | struct ieee80211_local *local = sdata->local; |
3030 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3005 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3031 | struct ieee80211_bss *bss = (void *)cbss->priv; | 3006 | struct ieee80211_bss *bss = (void *)cbss->priv; |
3032 | struct sta_info *sta; | 3007 | struct sta_info *sta = NULL; |
3033 | bool have_sta = false; | 3008 | bool have_sta = false; |
3034 | int err; | 3009 | int err; |
3035 | int ht_cfreq; | 3010 | int ht_cfreq; |
@@ -3082,13 +3057,11 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3082 | * since we look at probe response/beacon data here | 3057 | * since we look at probe response/beacon data here |
3083 | * it should be OK. | 3058 | * it should be OK. |
3084 | */ | 3059 | */ |
3085 | printk(KERN_DEBUG | 3060 | sdata_info(sdata, |
3086 | "%s: Wrong control channel: center-freq: %d" | 3061 | "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", |
3087 | " ht-cfreq: %d ht->primary_chan: %d" | 3062 | cbss->channel->center_freq, |
3088 | " band: %d. Disabling HT.\n", | 3063 | ht_cfreq, ht_oper->primary_chan, |
3089 | sdata->name, cbss->channel->center_freq, | 3064 | cbss->channel->band); |
3090 | ht_cfreq, ht_oper->primary_chan, | ||
3091 | cbss->channel->band); | ||
3092 | ht_oper = NULL; | 3065 | ht_oper = NULL; |
3093 | } | 3066 | } |
3094 | } | 3067 | } |
@@ -3112,9 +3085,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3112 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { | 3085 | if (!ieee80211_set_channel_type(local, sdata, channel_type)) { |
3113 | /* can only fail due to HT40+/- mismatch */ | 3086 | /* can only fail due to HT40+/- mismatch */ |
3114 | channel_type = NL80211_CHAN_HT20; | 3087 | channel_type = NL80211_CHAN_HT20; |
3115 | printk(KERN_DEBUG | 3088 | sdata_info(sdata, |
3116 | "%s: disabling 40 MHz due to multi-vif mismatch\n", | 3089 | "disabling 40 MHz due to multi-vif mismatch\n"); |
3117 | sdata->name); | ||
3118 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3090 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; |
3119 | WARN_ON(!ieee80211_set_channel_type(local, sdata, | 3091 | WARN_ON(!ieee80211_set_channel_type(local, sdata, |
3120 | channel_type)); | 3092 | channel_type)); |
@@ -3123,7 +3095,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3123 | local->oper_channel = cbss->channel; | 3095 | local->oper_channel = cbss->channel; |
3124 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 3096 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
3125 | 3097 | ||
3126 | if (!have_sta) { | 3098 | if (sta) { |
3127 | u32 rates = 0, basic_rates = 0; | 3099 | u32 rates = 0, basic_rates = 0; |
3128 | bool have_higher_than_11mbit; | 3100 | bool have_higher_than_11mbit; |
3129 | int min_rate = INT_MAX, min_rate_index = -1; | 3101 | int min_rate = INT_MAX, min_rate_index = -1; |
@@ -3143,9 +3115,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3143 | * we can connect -- with a warning. | 3115 | * we can connect -- with a warning. |
3144 | */ | 3116 | */ |
3145 | if (!basic_rates && min_rate_index >= 0) { | 3117 | if (!basic_rates && min_rate_index >= 0) { |
3146 | printk(KERN_DEBUG | 3118 | sdata_info(sdata, |
3147 | "%s: No basic rates, using min rate instead.\n", | 3119 | "No basic rates, using min rate instead\n"); |
3148 | sdata->name); | ||
3149 | basic_rates = BIT(min_rate_index); | 3120 | basic_rates = BIT(min_rate_index); |
3150 | } | 3121 | } |
3151 | 3122 | ||
@@ -3161,9 +3132,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3161 | 3132 | ||
3162 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); | 3133 | memcpy(ifmgd->bssid, cbss->bssid, ETH_ALEN); |
3163 | 3134 | ||
3164 | /* tell driver about BSSID and basic rates */ | 3135 | /* set timing information */ |
3136 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; | ||
3137 | sdata->vif.bss_conf.sync_tsf = cbss->tsf; | ||
3138 | sdata->vif.bss_conf.sync_device_ts = bss->device_ts; | ||
3139 | |||
3140 | /* tell driver about BSSID, basic rates and timing */ | ||
3165 | ieee80211_bss_info_change_notify(sdata, | 3141 | ieee80211_bss_info_change_notify(sdata, |
3166 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES); | 3142 | BSS_CHANGED_BSSID | BSS_CHANGED_BASIC_RATES | |
3143 | BSS_CHANGED_BEACON_INT); | ||
3167 | 3144 | ||
3168 | if (assoc) | 3145 | if (assoc) |
3169 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 3146 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
@@ -3171,9 +3148,9 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3171 | err = sta_info_insert(sta); | 3148 | err = sta_info_insert(sta); |
3172 | sta = NULL; | 3149 | sta = NULL; |
3173 | if (err) { | 3150 | if (err) { |
3174 | printk(KERN_DEBUG | 3151 | sdata_info(sdata, |
3175 | "%s: failed to insert STA entry for the AP (error %d)\n", | 3152 | "failed to insert STA entry for the AP (error %d)\n", |
3176 | sdata->name, err); | 3153 | err); |
3177 | return err; | 3154 | return err; |
3178 | } | 3155 | } |
3179 | } else | 3156 | } else |
@@ -3251,8 +3228,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
3251 | if (ifmgd->associated) | 3228 | if (ifmgd->associated) |
3252 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 3229 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
3253 | 3230 | ||
3254 | printk(KERN_DEBUG "%s: authenticate with %pM\n", | 3231 | sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid); |
3255 | sdata->name, req->bss->bssid); | ||
3256 | 3232 | ||
3257 | err = ieee80211_prep_connection(sdata, req->bss, false); | 3233 | err = ieee80211_prep_connection(sdata, req->bss, false); |
3258 | if (err) | 3234 | if (err) |
@@ -3287,7 +3263,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3287 | struct ieee80211_bss *bss = (void *)req->bss->priv; | 3263 | struct ieee80211_bss *bss = (void *)req->bss->priv; |
3288 | struct ieee80211_mgd_assoc_data *assoc_data; | 3264 | struct ieee80211_mgd_assoc_data *assoc_data; |
3289 | struct ieee80211_supported_band *sband; | 3265 | struct ieee80211_supported_band *sband; |
3290 | const u8 *ssidie; | 3266 | const u8 *ssidie, *ht_ie; |
3291 | int i, err; | 3267 | int i, err; |
3292 | 3268 | ||
3293 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 3269 | ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
@@ -3335,11 +3311,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3335 | * We can set this to true for non-11n hardware, that'll be checked | 3311 | * We can set this to true for non-11n hardware, that'll be checked |
3336 | * separately along with the peer capabilities. | 3312 | * separately along with the peer capabilities. |
3337 | */ | 3313 | */ |
3338 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) | 3314 | for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) { |
3339 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 3315 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
3340 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3316 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3341 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) | 3317 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3342 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3318 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3319 | netdev_info(sdata->dev, | ||
3320 | "disabling HT due to WEP/TKIP use\n"); | ||
3321 | } | ||
3322 | } | ||
3343 | 3323 | ||
3344 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3324 | if (req->flags & ASSOC_REQ_DISABLE_HT) |
3345 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3325 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
@@ -3347,8 +3327,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3347 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3327 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
3348 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3328 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3349 | if (!sband->ht_cap.ht_supported || | 3329 | if (!sband->ht_cap.ht_supported || |
3350 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) | 3330 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3351 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3331 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3332 | netdev_info(sdata->dev, | ||
3333 | "disabling HT as WMM/QoS is not supported\n"); | ||
3334 | } | ||
3352 | 3335 | ||
3353 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3336 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
3354 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, | 3337 | memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, |
@@ -3374,8 +3357,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3374 | (local->hw.queues >= IEEE80211_NUM_ACS); | 3357 | (local->hw.queues >= IEEE80211_NUM_ACS); |
3375 | assoc_data->supp_rates = bss->supp_rates; | 3358 | assoc_data->supp_rates = bss->supp_rates; |
3376 | assoc_data->supp_rates_len = bss->supp_rates_len; | 3359 | assoc_data->supp_rates_len = bss->supp_rates_len; |
3377 | assoc_data->ht_operation_ie = | 3360 | |
3378 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); | 3361 | ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION); |
3362 | if (ht_ie && ht_ie[1] >= sizeof(struct ieee80211_ht_operation)) | ||
3363 | assoc_data->ap_ht_param = | ||
3364 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | ||
3365 | else | ||
3366 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | ||
3379 | 3367 | ||
3380 | if (bss->wmm_used && bss->uapsd_supported && | 3368 | if (bss->wmm_used && bss->uapsd_supported && |
3381 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3369 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
@@ -3422,8 +3410,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3422 | * Wait up to one beacon interval ... | 3410 | * Wait up to one beacon interval ... |
3423 | * should this be more if we miss one? | 3411 | * should this be more if we miss one? |
3424 | */ | 3412 | */ |
3425 | printk(KERN_DEBUG "%s: waiting for beacon from %pM\n", | 3413 | sdata_info(sdata, "waiting for beacon from %pM\n", |
3426 | sdata->name, ifmgd->bssid); | 3414 | ifmgd->bssid); |
3427 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); | 3415 | assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); |
3428 | } else { | 3416 | } else { |
3429 | assoc_data->have_beacon = true; | 3417 | assoc_data->have_beacon = true; |
@@ -3442,8 +3430,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3442 | corrupt_type = "beacon"; | 3430 | corrupt_type = "beacon"; |
3443 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) | 3431 | } else if (bss->corrupt_data & IEEE80211_BSS_CORRUPT_PROBE_RESP) |
3444 | corrupt_type = "probe response"; | 3432 | corrupt_type = "probe response"; |
3445 | printk(KERN_DEBUG "%s: associating with AP with corrupt %s\n", | 3433 | sdata_info(sdata, "associating with AP with corrupt %s\n", |
3446 | sdata->name, corrupt_type); | 3434 | corrupt_type); |
3447 | } | 3435 | } |
3448 | 3436 | ||
3449 | err = 0; | 3437 | err = 0; |
@@ -3472,9 +3460,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3472 | return 0; | 3460 | return 0; |
3473 | } | 3461 | } |
3474 | 3462 | ||
3475 | printk(KERN_DEBUG | 3463 | sdata_info(sdata, |
3476 | "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 3464 | "deauthenticating from %pM by local choice (reason=%d)\n", |
3477 | sdata->name, req->bssid, req->reason_code); | 3465 | req->bssid, req->reason_code); |
3478 | 3466 | ||
3479 | if (ifmgd->associated && | 3467 | if (ifmgd->associated && |
3480 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) | 3468 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) |
@@ -3516,8 +3504,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
3516 | return -ENOLINK; | 3504 | return -ENOLINK; |
3517 | } | 3505 | } |
3518 | 3506 | ||
3519 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 3507 | sdata_info(sdata, |
3520 | sdata->name, req->bss->bssid, req->reason_code); | 3508 | "disassociating from %pM by local choice (reason=%d)\n", |
3509 | req->bss->bssid, req->reason_code); | ||
3521 | 3510 | ||
3522 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 3511 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
3523 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, | 3512 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, |
@@ -3558,10 +3547,3 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
3558 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 3547 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
3559 | } | 3548 | } |
3560 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 3549 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
3561 | |||
3562 | unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif) | ||
3563 | { | ||
3564 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
3565 | return sdata->dev->operstate; | ||
3566 | } | ||
3567 | EXPORT_SYMBOL(ieee80211_get_operstate); | ||