aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-03-26 09:02:26 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-16 09:29:42 -0400
commit37799e52a29af2268d1fbe18908a0d6b9f68af88 (patch)
tree709de66fb30ca2a5d15afa0c8c5daf9e18cfb37b /net/mac80211
parent6553bf04ff6686db658e09626edad003809f6baf (diff)
mac80211: unify CSA action frame/beacon processing
CSA action frame content should be processed as variable IEs rather than fixed to make it extensible. Unify the code and process them just like CSA in beacons to make it easier to extend for HT/VHT. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/mlme.c71
-rw-r--r--net/mac80211/rx.c4
3 files changed, 43 insertions, 36 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 8d5dcbf17bbc..373460f9c069 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1252,10 +1252,6 @@ void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata);
1252int ieee80211_max_network_latency(struct notifier_block *nb, 1252int ieee80211_max_network_latency(struct notifier_block *nb,
1253 unsigned long data, void *dummy); 1253 unsigned long data, void *dummy);
1254int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); 1254int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata);
1255void
1256ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1257 const struct ieee80211_channel_sw_ie *sw_elem,
1258 struct ieee80211_bss *bss, u64 timestamp);
1259void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata); 1255void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
1260void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, 1256void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1261 struct sk_buff *skb); 1257 struct sk_buff *skb);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2a2c45354498..ade3cd6c337d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1020,33 +1020,37 @@ static void ieee80211_chswitch_timer(unsigned long data)
1020 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work); 1020 ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.chswitch_work);
1021} 1021}
1022 1022
1023void 1023static void
1024ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, 1024ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1025 const struct ieee80211_channel_sw_ie *sw_elem, 1025 u64 timestamp, struct ieee802_11_elems *elems)
1026 struct ieee80211_bss *bss, u64 timestamp)
1027{ 1026{
1028 struct cfg80211_bss *cbss =
1029 container_of((void *)bss, struct cfg80211_bss, priv);
1030 struct ieee80211_channel *new_ch;
1031 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1027 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1032 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num, 1028 struct cfg80211_bss *cbss = ifmgd->associated;
1033 cbss->channel->band); 1029 struct ieee80211_bss *bss;
1030 struct ieee80211_channel *new_ch;
1031 int new_freq;
1034 struct ieee80211_chanctx *chanctx; 1032 struct ieee80211_chanctx *chanctx;
1035 1033
1036 ASSERT_MGD_MTX(ifmgd); 1034 ASSERT_MGD_MTX(ifmgd);
1037 1035
1038 if (!ifmgd->associated) 1036 if (!cbss)
1039 return; 1037 return;
1040 1038
1041 if (sdata->local->scanning) 1039 if (sdata->local->scanning)
1042 return; 1040 return;
1043 1041
1044 /* Disregard subsequent beacons if we are already running a timer 1042 /* disregard subsequent announcements if we are already processing */
1045 processing a CSA */
1046
1047 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) 1043 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
1048 return; 1044 return;
1049 1045
1046 if (!elems->ch_switch_ie)
1047 return;
1048
1049 bss = (void *)cbss->priv;
1050
1051 new_freq = ieee80211_channel_to_frequency(
1052 elems->ch_switch_ie->new_ch_num,
1053 cbss->channel->band);
1050 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq); 1054 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
1051 if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) { 1055 if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) {
1052 sdata_info(sdata, 1056 sdata_info(sdata,
@@ -1086,7 +1090,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1086 1090
1087 sdata->local->csa_channel = new_ch; 1091 sdata->local->csa_channel = new_ch;
1088 1092
1089 if (sw_elem->mode) 1093 if (elems->ch_switch_ie->mode)
1090 ieee80211_stop_queues_by_reason(&sdata->local->hw, 1094 ieee80211_stop_queues_by_reason(&sdata->local->hw,
1091 IEEE80211_MAX_QUEUE_MAP, 1095 IEEE80211_MAX_QUEUE_MAP,
1092 IEEE80211_QUEUE_STOP_REASON_CSA); 1096 IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -1095,9 +1099,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1095 /* use driver's channel switch callback */ 1099 /* use driver's channel switch callback */
1096 struct ieee80211_channel_switch ch_switch = { 1100 struct ieee80211_channel_switch ch_switch = {
1097 .timestamp = timestamp, 1101 .timestamp = timestamp,
1098 .block_tx = sw_elem->mode, 1102 .block_tx = elems->ch_switch_ie->mode,
1099 .channel = new_ch, 1103 .channel = new_ch,
1100 .count = sw_elem->count, 1104 .count = elems->ch_switch_ie->count,
1101 }; 1105 };
1102 1106
1103 drv_channel_switch(sdata->local, &ch_switch); 1107 drv_channel_switch(sdata->local, &ch_switch);
@@ -1105,11 +1109,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1105 } 1109 }
1106 1110
1107 /* channel switch handled in software */ 1111 /* channel switch handled in software */
1108 if (sw_elem->count <= 1) 1112 if (elems->ch_switch_ie->count <= 1)
1109 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); 1113 ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
1110 else 1114 else
1111 mod_timer(&ifmgd->chswitch_timer, 1115 mod_timer(&ifmgd->chswitch_timer,
1112 TU_TO_EXP_TIME(sw_elem->count * 1116 TU_TO_EXP_TIME(elems->ch_switch_ie->count *
1113 cbss->beacon_interval)); 1117 cbss->beacon_interval));
1114} 1118}
1115 1119
@@ -2655,7 +2659,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2655 if (bss) 2659 if (bss)
2656 ieee80211_rx_bss_put(local, bss); 2660 ieee80211_rx_bss_put(local, bss);
2657 2661
2658 if (!sdata->u.mgd.associated) 2662 if (!sdata->u.mgd.associated ||
2663 !ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid))
2659 return; 2664 return;
2660 2665
2661 if (need_ps) { 2666 if (need_ps) {
@@ -2664,10 +2669,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
2664 mutex_unlock(&local->iflist_mtx); 2669 mutex_unlock(&local->iflist_mtx);
2665 } 2670 }
2666 2671
2667 if (elems->ch_switch_ie && 2672 ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems);
2668 memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0)
2669 ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie,
2670 bss, rx_status->mactime);
2671} 2673}
2672 2674
2673 2675
@@ -3061,14 +3063,27 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
3061 rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss); 3063 rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
3062 break; 3064 break;
3063 case IEEE80211_STYPE_ACTION: 3065 case IEEE80211_STYPE_ACTION:
3064 switch (mgmt->u.action.category) { 3066 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
3065 case WLAN_CATEGORY_SPECTRUM_MGMT: 3067 struct ieee802_11_elems elems;
3068 int ies_len = skb->len -
3069 offsetof(struct ieee80211_mgmt,
3070 u.action.u.chan_switch.variable);
3071
3072 if (ies_len < 0)
3073 break;
3074
3075 ieee802_11_parse_elems(
3076 mgmt->u.action.u.chan_switch.variable,
3077 ies_len, &elems);
3078
3079 if (elems.parse_error)
3080 break;
3081
3066 ieee80211_sta_process_chanswitch(sdata, 3082 ieee80211_sta_process_chanswitch(sdata,
3067 &mgmt->u.action.u.chan_switch.sw_elem, 3083 rx_status->mactime,
3068 (void *)ifmgd->associated->priv, 3084 &elems);
3069 rx_status->mactime);
3070 break;
3071 } 3085 }
3086 break;
3072 } 3087 }
3073 mutex_unlock(&ifmgd->mtx); 3088 mutex_unlock(&ifmgd->mtx);
3074 3089
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5168f89c754d..e9825f15c14c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2507,10 +2507,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2507 ieee80211_process_measurement_req(sdata, mgmt, len); 2507 ieee80211_process_measurement_req(sdata, mgmt, len);
2508 goto handled; 2508 goto handled;
2509 case WLAN_ACTION_SPCT_CHL_SWITCH: 2509 case WLAN_ACTION_SPCT_CHL_SWITCH:
2510 if (len < (IEEE80211_MIN_ACTION_SIZE +
2511 sizeof(mgmt->u.action.u.chan_switch)))
2512 break;
2513
2514 if (sdata->vif.type != NL80211_IFTYPE_STATION) 2510 if (sdata->vif.type != NL80211_IFTYPE_STATION)
2515 break; 2511 break;
2516 2512