aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-14 10:58:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:16 -0400
commitae5eb02641233a4e9d1b92d22090f1b1afa14466 (patch)
tree117b7cb5efa3ff1cf714218098fc6db3820ed4e0 /net/mac80211/mlme.c
parentbda3933a8aceedd03e0dd410844bd310033ca756 (diff)
mac80211: rewrite HT handling
The HT handling has the following deficiencies, which I've (partially) fixed: * it always uses the AP info even if there is no AP, hence has no chance of working as an AP * it pretends to be HW config, but really is per-BSS * channel sanity checking is left to the drivers * it generally lets the driver control too much HT enabling is still wrong with this patch if you have more than one virtual STA mode interface, but that never happens currently. Once WDS, IBSS or AP/VLAN gets HT capabilities, it will also be wrong, see the comment in ieee80211_enable_ht(). Additionally, this fixes a number of bugs: * mac80211: ieee80211_set_disassoc doesn't notify the driver any more since the refactoring * iwl-agn-rs: always uses the HT capabilities from the wrong stuff mac80211 gives it rather than the actual peer STA * ath9k: a number of bugs resulting from the broken HT API I'm not entirely happy with putting the HT capabilities into struct ieee80211_sta as restricted to our own HT TX capabilities, but I see no cleaner solution for now. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c88
1 files changed, 50 insertions, 38 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9c5f5c37a49e..39bc9c69893b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -700,14 +700,15 @@ static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata,
700 700
701 701
702static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 702static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
703 struct ieee80211_if_sta *ifsta) 703 struct ieee80211_if_sta *ifsta,
704 u32 bss_info_changed)
704{ 705{
705 struct ieee80211_local *local = sdata->local; 706 struct ieee80211_local *local = sdata->local;
706 struct ieee80211_conf *conf = &local_to_hw(local)->conf; 707 struct ieee80211_conf *conf = &local_to_hw(local)->conf;
707 u32 changed = BSS_CHANGED_ASSOC;
708 708
709 struct ieee80211_bss *bss; 709 struct ieee80211_bss *bss;
710 710
711 bss_info_changed |= BSS_CHANGED_ASSOC;
711 ifsta->flags |= IEEE80211_STA_ASSOCIATED; 712 ifsta->flags |= IEEE80211_STA_ASSOCIATED;
712 713
713 if (sdata->vif.type != NL80211_IFTYPE_STATION) 714 if (sdata->vif.type != NL80211_IFTYPE_STATION)
@@ -722,19 +723,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
722 sdata->vif.bss_conf.timestamp = bss->timestamp; 723 sdata->vif.bss_conf.timestamp = bss->timestamp;
723 sdata->vif.bss_conf.dtim_period = bss->dtim_period; 724 sdata->vif.bss_conf.dtim_period = bss->dtim_period;
724 725
725 changed |= ieee80211_handle_bss_capability(sdata, 726 bss_info_changed |= ieee80211_handle_bss_capability(sdata,
726 bss->capability, bss->has_erp_value, bss->erp_value); 727 bss->capability, bss->has_erp_value, bss->erp_value);
727 728
728 ieee80211_rx_bss_put(local, bss); 729 ieee80211_rx_bss_put(local, bss);
729 } 730 }
730 731
731 if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
732 changed |= BSS_CHANGED_HT;
733 sdata->vif.bss_conf.assoc_ht = 1;
734 sdata->vif.bss_conf.ht_cap = &conf->ht_cap;
735 sdata->vif.bss_conf.ht_bss_conf = &conf->ht_bss_conf;
736 }
737
738 ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; 732 ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
739 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); 733 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
740 ieee80211_sta_send_associnfo(sdata, ifsta); 734 ieee80211_sta_send_associnfo(sdata, ifsta);
@@ -748,8 +742,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
748 * when we have associated, we aren't checking whether it actually 742 * when we have associated, we aren't checking whether it actually
749 * changed or not. 743 * changed or not.
750 */ 744 */
751 changed |= BSS_CHANGED_BASIC_RATES; 745 bss_info_changed |= BSS_CHANGED_BASIC_RATES;
752 ieee80211_bss_info_change_notify(sdata, changed); 746 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
753 747
754 netif_tx_start_all_queues(sdata->dev); 748 netif_tx_start_all_queues(sdata->dev);
755 netif_carrier_on(sdata->dev); 749 netif_carrier_on(sdata->dev);
@@ -813,7 +807,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
813{ 807{
814 struct ieee80211_local *local = sdata->local; 808 struct ieee80211_local *local = sdata->local;
815 struct sta_info *sta; 809 struct sta_info *sta;
816 u32 changed = BSS_CHANGED_ASSOC; 810 u32 changed = 0;
817 811
818 rcu_read_lock(); 812 rcu_read_lock();
819 813
@@ -847,15 +841,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
847 ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; 841 ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
848 changed |= ieee80211_reset_erp_info(sdata); 842 changed |= ieee80211_reset_erp_info(sdata);
849 843
850 if (sdata->vif.bss_conf.assoc_ht)
851 changed |= BSS_CHANGED_HT;
852
853 sdata->vif.bss_conf.assoc_ht = 0;
854 sdata->vif.bss_conf.ht_cap = NULL;
855 sdata->vif.bss_conf.ht_bss_conf = NULL;
856
857 ieee80211_led_assoc(local, 0); 844 ieee80211_led_assoc(local, 0);
858 sdata->vif.bss_conf.assoc = 0; 845 changed |= BSS_CHANGED_ASSOC;
846 sdata->vif.bss_conf.assoc = false;
859 847
860 ieee80211_sta_send_apinfo(sdata, ifsta); 848 ieee80211_sta_send_apinfo(sdata, ifsta);
861 849
@@ -867,6 +855,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
867 rcu_read_unlock(); 855 rcu_read_unlock();
868 856
869 sta_info_destroy(sta); 857 sta_info_destroy(sta);
858
859 local->hw.conf.ht.enabled = false;
860 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
861
862 ieee80211_bss_info_change_notify(sdata, changed);
870} 863}
871 864
872static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) 865static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
@@ -1184,8 +1177,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1184 struct ieee802_11_elems elems; 1177 struct ieee802_11_elems elems;
1185 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; 1178 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
1186 u8 *pos; 1179 u8 *pos;
1180 u32 changed = 0;
1187 int i, j; 1181 int i, j;
1188 bool have_higher_than_11mbit = false; 1182 bool have_higher_than_11mbit = false;
1183 u16 ap_ht_cap_flags;
1189 1184
1190 /* AssocResp and ReassocResp have identical structure, so process both 1185 /* AssocResp and ReassocResp have identical structure, so process both
1191 * of them in this function. */ 1186 * of them in this function. */
@@ -1333,15 +1328,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1333 else 1328 else
1334 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; 1329 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
1335 1330
1336 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && 1331 if (elems.ht_cap_elem)
1337 (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { 1332 ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
1338 struct ieee80211_ht_bss_info bss_info;
1339 ieee80211_ht_cap_ie_to_sta_ht_cap(
1340 elems.ht_cap_elem, &sta->sta.ht_cap); 1333 elems.ht_cap_elem, &sta->sta.ht_cap);
1341 ieee80211_ht_info_ie_to_ht_bss_info( 1334
1342 elems.ht_info_elem, &bss_info); 1335 ap_ht_cap_flags = sta->sta.ht_cap.cap;
1343 ieee80211_handle_ht(local, &sta->sta.ht_cap, &bss_info);
1344 }
1345 1336
1346 rate_control_rate_init(sta); 1337 rate_control_rate_init(sta);
1347 1338
@@ -1353,11 +1344,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1353 } else 1344 } else
1354 rcu_read_unlock(); 1345 rcu_read_unlock();
1355 1346
1347 if (elems.ht_info_elem && elems.wmm_param &&
1348 (ifsta->flags & IEEE80211_STA_WMM_ENABLED))
1349 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
1350 ap_ht_cap_flags);
1351
1356 /* set AID and assoc capability, 1352 /* set AID and assoc capability,
1357 * ieee80211_set_associated() will tell the driver */ 1353 * ieee80211_set_associated() will tell the driver */
1358 bss_conf->aid = aid; 1354 bss_conf->aid = aid;
1359 bss_conf->assoc_capability = capab_info; 1355 bss_conf->assoc_capability = capab_info;
1360 ieee80211_set_associated(sdata, ifsta); 1356 ieee80211_set_associated(sdata, ifsta, changed);
1361 1357
1362 ieee80211_associated(sdata, ifsta); 1358 ieee80211_associated(sdata, ifsta);
1363} 1359}
@@ -1657,7 +1653,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1657 size_t baselen; 1653 size_t baselen;
1658 struct ieee802_11_elems elems; 1654 struct ieee802_11_elems elems;
1659 struct ieee80211_local *local = sdata->local; 1655 struct ieee80211_local *local = sdata->local;
1660 struct ieee80211_conf *conf = &local->hw.conf;
1661 u32 changed = 0; 1656 u32 changed = 0;
1662 bool erp_valid; 1657 bool erp_valid;
1663 u8 erp_value = 0; 1658 u8 erp_value = 0;
@@ -1693,14 +1688,31 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1693 le16_to_cpu(mgmt->u.beacon.capab_info), 1688 le16_to_cpu(mgmt->u.beacon.capab_info),
1694 erp_valid, erp_value); 1689 erp_valid, erp_value);
1695 1690
1696 if (elems.ht_cap_elem && elems.ht_info_elem &&
1697 elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
1698 struct ieee80211_ht_bss_info bss_info;
1699 1691
1700 ieee80211_ht_info_ie_to_ht_bss_info( 1692 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
1701 elems.ht_info_elem, &bss_info); 1693 struct sta_info *sta;
1702 changed |= ieee80211_handle_ht(local, &conf->ht_cap, 1694 struct ieee80211_supported_band *sband;
1703 &bss_info); 1695 u16 ap_ht_cap_flags;
1696
1697 rcu_read_lock();
1698
1699 sta = sta_info_get(local, ifsta->bssid);
1700 if (!sta) {
1701 rcu_read_unlock();
1702 return;
1703 }
1704
1705 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
1706
1707 ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
1708 elems.ht_cap_elem, &sta->sta.ht_cap);
1709
1710 ap_ht_cap_flags = sta->sta.ht_cap.cap;
1711
1712 rcu_read_unlock();
1713
1714 changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
1715 ap_ht_cap_flags);
1704 } 1716 }
1705 1717
1706 ieee80211_bss_info_change_notify(sdata, changed); 1718 ieee80211_bss_info_change_notify(sdata, changed);