aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c139
1 files changed, 85 insertions, 54 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b1b1bb368f70..ecb4c84c1bb3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -209,6 +209,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
209 channel_type = NL80211_CHAN_HT20; 209 channel_type = NL80211_CHAN_HT20;
210 210
211 if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && 211 if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
212 !ieee80111_cfg_override_disables_ht40(sdata) &&
212 (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && 213 (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
213 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { 214 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
214 switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 215 switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
@@ -818,7 +819,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
818 } 819 }
819 820
820 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && 821 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
821 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { 822 !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
822 netif_tx_stop_all_queues(sdata->dev); 823 netif_tx_stop_all_queues(sdata->dev);
823 824
824 if (drv_tx_frames_pending(local)) 825 if (drv_tx_frames_pending(local))
@@ -1120,6 +1121,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1120 1121
1121 /* on the next assoc, re-program HT parameters */ 1122 /* on the next assoc, re-program HT parameters */
1122 sdata->ht_opmode_valid = false; 1123 sdata->ht_opmode_valid = false;
1124 memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
1125 memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
1123 1126
1124 local->power_constr_level = 0; 1127 local->power_constr_level = 0;
1125 1128
@@ -1359,9 +1362,6 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1359 ieee80211_set_disassoc(sdata, true, true); 1362 ieee80211_set_disassoc(sdata, true, true);
1360 mutex_unlock(&ifmgd->mtx); 1363 mutex_unlock(&ifmgd->mtx);
1361 1364
1362 mutex_lock(&local->mtx);
1363 ieee80211_recalc_idle(local);
1364 mutex_unlock(&local->mtx);
1365 /* 1365 /*
1366 * must be outside lock due to cfg80211, 1366 * must be outside lock due to cfg80211,
1367 * but that's not a problem. 1367 * but that's not a problem.
@@ -1370,6 +1370,10 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1370 IEEE80211_STYPE_DEAUTH, 1370 IEEE80211_STYPE_DEAUTH,
1371 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, 1371 WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY,
1372 NULL, true); 1372 NULL, true);
1373
1374 mutex_lock(&local->mtx);
1375 ieee80211_recalc_idle(local);
1376 mutex_unlock(&local->mtx);
1373} 1377}
1374 1378
1375void ieee80211_beacon_connection_loss_work(struct work_struct *work) 1379void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -1377,6 +1381,16 @@ void ieee80211_beacon_connection_loss_work(struct work_struct *work)
1377 struct ieee80211_sub_if_data *sdata = 1381 struct ieee80211_sub_if_data *sdata =
1378 container_of(work, struct ieee80211_sub_if_data, 1382 container_of(work, struct ieee80211_sub_if_data,
1379 u.mgd.beacon_connection_loss_work); 1383 u.mgd.beacon_connection_loss_work);
1384 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1385 struct sta_info *sta;
1386
1387 if (ifmgd->associated) {
1388 rcu_read_lock();
1389 sta = sta_info_get(sdata, ifmgd->bssid);
1390 if (sta)
1391 sta->beacon_loss_count++;
1392 rcu_read_unlock();
1393 }
1380 1394
1381 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) 1395 if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
1382 __ieee80211_connection_loss(sdata); 1396 __ieee80211_connection_loss(sdata);
@@ -1468,6 +1482,47 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1468 return RX_MGMT_CFG80211_DISASSOC; 1482 return RX_MGMT_CFG80211_DISASSOC;
1469} 1483}
1470 1484
1485static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
1486 u8 *supp_rates, unsigned int supp_rates_len,
1487 u32 *rates, u32 *basic_rates,
1488 bool *have_higher_than_11mbit,
1489 int *min_rate, int *min_rate_index)
1490{
1491 int i, j;
1492
1493 for (i = 0; i < supp_rates_len; i++) {
1494 int rate = (supp_rates[i] & 0x7f) * 5;
1495 bool is_basic = !!(supp_rates[i] & 0x80);
1496
1497 if (rate > 110)
1498 *have_higher_than_11mbit = true;
1499
1500 /*
1501 * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009
1502 * 7.3.2.2 as a magic value instead of a rate. Hence, skip it.
1503 *
1504 * Note: Even through the membership selector and the basic
1505 * rate flag share the same bit, they are not exactly
1506 * the same.
1507 */
1508 if (!!(supp_rates[i] & 0x80) &&
1509 (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
1510 continue;
1511
1512 for (j = 0; j < sband->n_bitrates; j++) {
1513 if (sband->bitrates[j].bitrate == rate) {
1514 *rates |= BIT(j);
1515 if (is_basic)
1516 *basic_rates |= BIT(j);
1517 if (rate < *min_rate) {
1518 *min_rate = rate;
1519 *min_rate_index = j;
1520 }
1521 break;
1522 }
1523 }
1524 }
1525}
1471 1526
1472static bool ieee80211_assoc_success(struct ieee80211_work *wk, 1527static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1473 struct ieee80211_mgmt *mgmt, size_t len) 1528 struct ieee80211_mgmt *mgmt, size_t len)
@@ -1484,7 +1539,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1484 struct ieee802_11_elems elems; 1539 struct ieee802_11_elems elems;
1485 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 1540 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1486 u32 changed = 0; 1541 u32 changed = 0;
1487 int i, j, err; 1542 int err;
1488 bool have_higher_than_11mbit = false; 1543 bool have_higher_than_11mbit = false;
1489 u16 ap_ht_cap_flags; 1544 u16 ap_ht_cap_flags;
1490 int min_rate = INT_MAX, min_rate_index = -1; 1545 int min_rate = INT_MAX, min_rate_index = -1;
@@ -1532,57 +1587,23 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1532 return false; 1587 return false;
1533 } 1588 }
1534 1589
1535 set_sta_flag(sta, WLAN_STA_AUTH); 1590 sta_info_move_state(sta, IEEE80211_STA_AUTH);
1536 set_sta_flag(sta, WLAN_STA_ASSOC); 1591 sta_info_move_state(sta, IEEE80211_STA_ASSOC);
1537 set_sta_flag(sta, WLAN_STA_ASSOC_AP);
1538 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) 1592 if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
1539 set_sta_flag(sta, WLAN_STA_AUTHORIZED); 1593 sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
1540 1594
1541 rates = 0; 1595 rates = 0;
1542 basic_rates = 0; 1596 basic_rates = 0;
1543 sband = local->hw.wiphy->bands[wk->chan->band]; 1597 sband = local->hw.wiphy->bands[wk->chan->band];
1544 1598
1545 for (i = 0; i < elems.supp_rates_len; i++) { 1599 ieee80211_get_rates(sband, elems.supp_rates, elems.supp_rates_len,
1546 int rate = (elems.supp_rates[i] & 0x7f) * 5; 1600 &rates, &basic_rates, &have_higher_than_11mbit,
1547 bool is_basic = !!(elems.supp_rates[i] & 0x80); 1601 &min_rate, &min_rate_index);
1548 1602
1549 if (rate > 110) 1603 ieee80211_get_rates(sband, elems.ext_supp_rates,
1550 have_higher_than_11mbit = true; 1604 elems.ext_supp_rates_len, &rates, &basic_rates,
1551 1605 &have_higher_than_11mbit,
1552 for (j = 0; j < sband->n_bitrates; j++) { 1606 &min_rate, &min_rate_index);
1553 if (sband->bitrates[j].bitrate == rate) {
1554 rates |= BIT(j);
1555 if (is_basic)
1556 basic_rates |= BIT(j);
1557 if (rate < min_rate) {
1558 min_rate = rate;
1559 min_rate_index = j;
1560 }
1561 break;
1562 }
1563 }
1564 }
1565
1566 for (i = 0; i < elems.ext_supp_rates_len; i++) {
1567 int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
1568 bool is_basic = !!(elems.ext_supp_rates[i] & 0x80);
1569
1570 if (rate > 110)
1571 have_higher_than_11mbit = true;
1572
1573 for (j = 0; j < sband->n_bitrates; j++) {
1574 if (sband->bitrates[j].bitrate == rate) {
1575 rates |= BIT(j);
1576 if (is_basic)
1577 basic_rates |= BIT(j);
1578 if (rate < min_rate) {
1579 min_rate = rate;
1580 min_rate_index = j;
1581 }
1582 break;
1583 }
1584 }
1585 }
1586 1607
1587 /* 1608 /*
1588 * some buggy APs don't advertise basic_rates. use the lowest 1609 * some buggy APs don't advertise basic_rates. use the lowest
@@ -1605,7 +1626,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
1605 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 1626 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
1606 1627
1607 if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) 1628 if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
1608 ieee80211_ht_cap_ie_to_sta_ht_cap(sband, 1629 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
1609 elems.ht_cap_elem, &sta->sta.ht_cap); 1630 elems.ht_cap_elem, &sta->sta.ht_cap);
1610 1631
1611 ap_ht_cap_flags = sta->sta.ht_cap.cap; 1632 ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -1974,7 +1995,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1974 1995
1975 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 1996 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1976 1997
1977 ieee80211_ht_cap_ie_to_sta_ht_cap(sband, 1998 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
1978 elems.ht_cap_elem, &sta->sta.ht_cap); 1999 elems.ht_cap_elem, &sta->sta.ht_cap);
1979 2000
1980 ap_ht_cap_flags = sta->sta.ht_cap.cap; 2001 ap_ht_cap_flags = sta->sta.ht_cap.cap;
@@ -2128,9 +2149,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2128 2149
2129 ieee80211_set_disassoc(sdata, true, true); 2150 ieee80211_set_disassoc(sdata, true, true);
2130 mutex_unlock(&ifmgd->mtx); 2151 mutex_unlock(&ifmgd->mtx);
2131 mutex_lock(&local->mtx);
2132 ieee80211_recalc_idle(local);
2133 mutex_unlock(&local->mtx);
2134 /* 2152 /*
2135 * must be outside lock due to cfg80211, 2153 * must be outside lock due to cfg80211,
2136 * but that's not a problem. 2154 * but that's not a problem.
@@ -2138,6 +2156,11 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2138 ieee80211_send_deauth_disassoc(sdata, bssid, 2156 ieee80211_send_deauth_disassoc(sdata, bssid,
2139 IEEE80211_STYPE_DEAUTH, reason, 2157 IEEE80211_STYPE_DEAUTH, reason,
2140 NULL, true); 2158 NULL, true);
2159
2160 mutex_lock(&local->mtx);
2161 ieee80211_recalc_idle(local);
2162 mutex_unlock(&local->mtx);
2163
2141 mutex_lock(&ifmgd->mtx); 2164 mutex_lock(&ifmgd->mtx);
2142} 2165}
2143 2166
@@ -2358,6 +2381,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2358 (unsigned long) sdata); 2381 (unsigned long) sdata);
2359 2382
2360 ifmgd->flags = 0; 2383 ifmgd->flags = 0;
2384 ifmgd->powersave = sdata->wdev.ps;
2361 2385
2362 mutex_init(&ifmgd->mtx); 2386 mutex_init(&ifmgd->mtx);
2363 2387
@@ -2632,6 +2656,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2632 ifmgd->flags |= IEEE80211_STA_DISABLE_11N; 2656 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
2633 2657
2634 2658
2659 if (req->flags & ASSOC_REQ_DISABLE_HT)
2660 ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
2661
2662 memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
2663 memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask,
2664 sizeof(ifmgd->ht_capa_mask));
2665
2635 if (req->ie && req->ie_len) { 2666 if (req->ie && req->ie_len) {
2636 memcpy(wk->ie, req->ie, req->ie_len); 2667 memcpy(wk->ie, req->ie, req->ie_len);
2637 wk->ie_len = req->ie_len; 2668 wk->ie_len = req->ie_len;