aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorChun-Yeow Yeoh <yeohchunyeow@cozybit.com>2013-10-14 22:08:29 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-10-28 10:05:28 -0400
commitc0f17eb9b2d4d322c099a0700437209149224583 (patch)
treeed32c2de60b9dc2dc50e2125ce49fae54e5507a8 /net/mac80211
parent06be6b149f7e406bcf16098567f5a6c9f042bced (diff)
mac80211: refactor the parsing of chan switch ie
Refactor the channel switch IE parsing to reduce the number of function parameters. Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ibss.c13
-rw-r--r--net/mac80211/ieee80211_i.h17
-rw-r--r--net/mac80211/mlme.c32
-rw-r--r--net/mac80211/spectmgmt.c27
4 files changed, 48 insertions, 41 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 275bbb2c1a5a..a0ae02760139 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -836,13 +836,13 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
836 bool beacon) 836 bool beacon)
837{ 837{
838 struct cfg80211_csa_settings params; 838 struct cfg80211_csa_settings params;
839 struct ieee80211_csa_ie csa_ie;
839 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 840 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
840 struct ieee80211_chanctx_conf *chanctx_conf; 841 struct ieee80211_chanctx_conf *chanctx_conf;
841 struct ieee80211_chanctx *chanctx; 842 struct ieee80211_chanctx *chanctx;
842 enum nl80211_channel_type ch_type; 843 enum nl80211_channel_type ch_type;
843 int err, num_chanctx; 844 int err, num_chanctx;
844 u32 sta_flags; 845 u32 sta_flags;
845 u8 mode;
846 846
847 if (sdata->vif.csa_active) 847 if (sdata->vif.csa_active)
848 return true; 848 return true;
@@ -865,12 +865,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
865 } 865 }
866 866
867 memset(&params, 0, sizeof(params)); 867 memset(&params, 0, sizeof(params));
868 memset(&csa_ie, 0, sizeof(csa_ie));
868 err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, 869 err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
869 ifibss->chandef.chan->band, 870 ifibss->chandef.chan->band,
870 sta_flags, ifibss->bssid, 871 sta_flags, ifibss->bssid, &csa_ie);
871 &params.count, &mode,
872 &params.chandef);
873
874 /* can't switch to destination channel, fail */ 872 /* can't switch to destination channel, fail */
875 if (err < 0) 873 if (err < 0)
876 goto disconnect; 874 goto disconnect;
@@ -879,6 +877,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
879 if (err) 877 if (err)
880 return false; 878 return false;
881 879
880 params.count = csa_ie.count;
881 params.chandef = csa_ie.chandef;
882
882 if (ifibss->chandef.chan->band != params.chandef.chan->band) 883 if (ifibss->chandef.chan->band != params.chandef.chan->band)
883 goto disconnect; 884 goto disconnect;
884 885
@@ -965,7 +966,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
965 "received channel switch announcement to go to channel %d MHz\n", 966 "received channel switch announcement to go to channel %d MHz\n",
966 params.chandef.chan->center_freq); 967 params.chandef.chan->center_freq);
967 968
968 params.block_tx = !!mode; 969 params.block_tx = !!csa_ie.mode;
969 970
970 ieee80211_ibss_csa_beacon(sdata, &params); 971 ieee80211_ibss_csa_beacon(sdata, &params);
971 sdata->csa_radar_required = params.radar_required; 972 sdata->csa_radar_required = params.radar_required;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ff3c310142b5..cbaea32bccf1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1208,6 +1208,14 @@ struct ieee80211_ra_tid {
1208 u16 tid; 1208 u16 tid;
1209}; 1209};
1210 1210
1211/* this struct holds the value parsing from channel switch IE */
1212struct ieee80211_csa_ie {
1213 struct cfg80211_chan_def chandef;
1214 u8 mode;
1215 u8 count;
1216 u8 ttl;
1217};
1218
1211/* Parsed Information Elements */ 1219/* Parsed Information Elements */
1212struct ieee802_11_elems { 1220struct ieee802_11_elems {
1213 const u8 *ie_start; 1221 const u8 *ie_start;
@@ -1505,17 +1513,16 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
1505 * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT, 1513 * %IEEE80211_STA_DISABLE_HT, %IEEE80211_STA_DISABLE_VHT,
1506 * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ, 1514 * %IEEE80211_STA_DISABLE_40MHZ, %IEEE80211_STA_DISABLE_80P80MHZ,
1507 * %IEEE80211_STA_DISABLE_160MHZ. 1515 * %IEEE80211_STA_DISABLE_160MHZ.
1508 * @count: to be filled with the counter until the switch (on success only)
1509 * @bssid: the currently connected bssid (for reporting) 1516 * @bssid: the currently connected bssid (for reporting)
1510 * @mode: to be filled with CSA mode (on success only) 1517 * @csa_ie: parsed 802.11 csa elements on count, mode, chandef and mesh ttl.
1511 * @new_chandef: to be filled with destination chandef (on success only) 1518 All of them will be filled with if success only.
1512 * Return: 0 on success, <0 on error and >0 if there is nothing to parse. 1519 * Return: 0 on success, <0 on error and >0 if there is nothing to parse.
1513 */ 1520 */
1514int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, 1521int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
1515 struct ieee802_11_elems *elems, bool beacon, 1522 struct ieee802_11_elems *elems, bool beacon,
1516 enum ieee80211_band current_band, 1523 enum ieee80211_band current_band,
1517 u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, 1524 u32 sta_flags, u8 *bssid,
1518 struct cfg80211_chan_def *new_chandef); 1525 struct ieee80211_csa_ie *csa_ie);
1519 1526
1520/* Suspend/resume and hw reconfiguration */ 1527/* Suspend/resume and hw reconfiguration */
1521int ieee80211_reconfig(struct ieee80211_local *local); 1528int ieee80211_reconfig(struct ieee80211_local *local);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 5cc1c274dd61..1305ff984d49 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -958,9 +958,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
958 struct cfg80211_bss *cbss = ifmgd->associated; 958 struct cfg80211_bss *cbss = ifmgd->associated;
959 struct ieee80211_chanctx *chanctx; 959 struct ieee80211_chanctx *chanctx;
960 enum ieee80211_band current_band; 960 enum ieee80211_band current_band;
961 u8 count; 961 struct ieee80211_csa_ie csa_ie;
962 u8 mode;
963 struct cfg80211_chan_def new_chandef = {};
964 int res; 962 int res;
965 963
966 sdata_assert_lock(sdata); 964 sdata_assert_lock(sdata);
@@ -976,24 +974,24 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
976 return; 974 return;
977 975
978 current_band = cbss->channel->band; 976 current_band = cbss->channel->band;
977 memset(&csa_ie, 0, sizeof(csa_ie));
979 res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band, 978 res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
980 ifmgd->flags, 979 ifmgd->flags,
981 ifmgd->associated->bssid, &count, 980 ifmgd->associated->bssid, &csa_ie);
982 &mode, &new_chandef);
983 if (res < 0) 981 if (res < 0)
984 ieee80211_queue_work(&local->hw, 982 ieee80211_queue_work(&local->hw,
985 &ifmgd->csa_connection_drop_work); 983 &ifmgd->csa_connection_drop_work);
986 if (res) 984 if (res)
987 return; 985 return;
988 986
989 if (!cfg80211_chandef_usable(local->hw.wiphy, &new_chandef, 987 if (!cfg80211_chandef_usable(local->hw.wiphy, &csa_ie.chandef,
990 IEEE80211_CHAN_DISABLED)) { 988 IEEE80211_CHAN_DISABLED)) {
991 sdata_info(sdata, 989 sdata_info(sdata,
992 "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n", 990 "AP %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), disconnecting\n",
993 ifmgd->associated->bssid, 991 ifmgd->associated->bssid,
994 new_chandef.chan->center_freq, 992 csa_ie.chandef.chan->center_freq,
995 new_chandef.width, new_chandef.center_freq1, 993 csa_ie.chandef.width, csa_ie.chandef.center_freq1,
996 new_chandef.center_freq2); 994 csa_ie.chandef.center_freq2);
997 ieee80211_queue_work(&local->hw, 995 ieee80211_queue_work(&local->hw,
998 &ifmgd->csa_connection_drop_work); 996 &ifmgd->csa_connection_drop_work);
999 return; 997 return;
@@ -1037,9 +1035,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1037 } 1035 }
1038 mutex_unlock(&local->chanctx_mtx); 1036 mutex_unlock(&local->chanctx_mtx);
1039 1037
1040 local->csa_chandef = new_chandef; 1038 local->csa_chandef = csa_ie.chandef;
1041 1039
1042 if (mode) 1040 if (csa_ie.mode)
1043 ieee80211_stop_queues_by_reason(&local->hw, 1041 ieee80211_stop_queues_by_reason(&local->hw,
1044 IEEE80211_MAX_QUEUE_MAP, 1042 IEEE80211_MAX_QUEUE_MAP,
1045 IEEE80211_QUEUE_STOP_REASON_CSA); 1043 IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -1048,9 +1046,9 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1048 /* use driver's channel switch callback */ 1046 /* use driver's channel switch callback */
1049 struct ieee80211_channel_switch ch_switch = { 1047 struct ieee80211_channel_switch ch_switch = {
1050 .timestamp = timestamp, 1048 .timestamp = timestamp,
1051 .block_tx = mode, 1049 .block_tx = csa_ie.mode,
1052 .chandef = new_chandef, 1050 .chandef = csa_ie.chandef,
1053 .count = count, 1051 .count = csa_ie.count,
1054 }; 1052 };
1055 1053
1056 drv_channel_switch(local, &ch_switch); 1054 drv_channel_switch(local, &ch_switch);
@@ -1058,11 +1056,11 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1058 } 1056 }
1059 1057
1060 /* channel switch handled in software */ 1058 /* channel switch handled in software */
1061 if (count <= 1) 1059 if (csa_ie.count <= 1)
1062 ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work); 1060 ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
1063 else 1061 else
1064 mod_timer(&ifmgd->chswitch_timer, 1062 mod_timer(&ifmgd->chswitch_timer,
1065 TU_TO_EXP_TIME(count * cbss->beacon_interval)); 1063 TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
1066} 1064}
1067 1065
1068static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, 1066static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
@@ -3994,7 +3992,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
3994 } 3992 }
3995 3993
3996 /* prepare assoc data */ 3994 /* prepare assoc data */
3997 3995
3998 ifmgd->beacon_crc_valid = false; 3996 ifmgd->beacon_crc_valid = false;
3999 3997
4000 /* 3998 /*
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 921597e279a3..a298e129633b 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -24,8 +24,8 @@
24int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, 24int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
25 struct ieee802_11_elems *elems, bool beacon, 25 struct ieee802_11_elems *elems, bool beacon,
26 enum ieee80211_band current_band, 26 enum ieee80211_band current_band,
27 u32 sta_flags, u8 *bssid, u8 *count, u8 *mode, 27 u32 sta_flags, u8 *bssid,
28 struct cfg80211_chan_def *new_chandef) 28 struct ieee80211_csa_ie *csa_ie)
29{ 29{
30 enum ieee80211_band new_band; 30 enum ieee80211_band new_band;
31 int new_freq; 31 int new_freq;
@@ -62,13 +62,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
62 return -EINVAL; 62 return -EINVAL;
63 } 63 }
64 new_chan_no = elems->ext_chansw_ie->new_ch_num; 64 new_chan_no = elems->ext_chansw_ie->new_ch_num;
65 *count = elems->ext_chansw_ie->count; 65 csa_ie->count = elems->ext_chansw_ie->count;
66 *mode = elems->ext_chansw_ie->mode; 66 csa_ie->mode = elems->ext_chansw_ie->mode;
67 } else if (elems->ch_switch_ie) { 67 } else if (elems->ch_switch_ie) {
68 new_band = current_band; 68 new_band = current_band;
69 new_chan_no = elems->ch_switch_ie->new_ch_num; 69 new_chan_no = elems->ch_switch_ie->new_ch_num;
70 *count = elems->ch_switch_ie->count; 70 csa_ie->count = elems->ch_switch_ie->count;
71 *mode = elems->ch_switch_ie->mode; 71 csa_ie->mode = elems->ch_switch_ie->mode;
72 } else { 72 } else {
73 /* nothing here we understand */ 73 /* nothing here we understand */
74 return 1; 74 return 1;
@@ -103,25 +103,26 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
103 default: 103 default:
104 /* secondary_channel_offset was present but is invalid */ 104 /* secondary_channel_offset was present but is invalid */
105 case IEEE80211_HT_PARAM_CHA_SEC_NONE: 105 case IEEE80211_HT_PARAM_CHA_SEC_NONE:
106 cfg80211_chandef_create(new_chandef, new_chan, 106 cfg80211_chandef_create(&csa_ie->chandef, new_chan,
107 NL80211_CHAN_HT20); 107 NL80211_CHAN_HT20);
108 break; 108 break;
109 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 109 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
110 cfg80211_chandef_create(new_chandef, new_chan, 110 cfg80211_chandef_create(&csa_ie->chandef, new_chan,
111 NL80211_CHAN_HT40PLUS); 111 NL80211_CHAN_HT40PLUS);
112 break; 112 break;
113 case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 113 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
114 cfg80211_chandef_create(new_chandef, new_chan, 114 cfg80211_chandef_create(&csa_ie->chandef, new_chan,
115 NL80211_CHAN_HT40MINUS); 115 NL80211_CHAN_HT40MINUS);
116 break; 116 break;
117 case -1: 117 case -1:
118 cfg80211_chandef_create(new_chandef, new_chan, 118 cfg80211_chandef_create(&csa_ie->chandef, new_chan,
119 NL80211_CHAN_NO_HT); 119 NL80211_CHAN_NO_HT);
120 /* keep width for 5/10 MHz channels */ 120 /* keep width for 5/10 MHz channels */
121 switch (sdata->vif.bss_conf.chandef.width) { 121 switch (sdata->vif.bss_conf.chandef.width) {
122 case NL80211_CHAN_WIDTH_5: 122 case NL80211_CHAN_WIDTH_5:
123 case NL80211_CHAN_WIDTH_10: 123 case NL80211_CHAN_WIDTH_10:
124 new_chandef->width = sdata->vif.bss_conf.chandef.width; 124 csa_ie->chandef.width =
125 sdata->vif.bss_conf.chandef.width;
125 break; 126 break;
126 default: 127 default:
127 break; 128 break;
@@ -171,13 +172,13 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
171 /* if VHT data is there validate & use it */ 172 /* if VHT data is there validate & use it */
172 if (new_vht_chandef.chan) { 173 if (new_vht_chandef.chan) {
173 if (!cfg80211_chandef_compatible(&new_vht_chandef, 174 if (!cfg80211_chandef_compatible(&new_vht_chandef,
174 new_chandef)) { 175 &csa_ie->chandef)) {
175 sdata_info(sdata, 176 sdata_info(sdata,
176 "BSS %pM: CSA has inconsistent channel data, disconnecting\n", 177 "BSS %pM: CSA has inconsistent channel data, disconnecting\n",
177 bssid); 178 bssid);
178 return -EINVAL; 179 return -EINVAL;
179 } 180 }
180 *new_chandef = new_vht_chandef; 181 csa_ie->chandef = new_vht_chandef;
181 } 182 }
182 183
183 return 0; 184 return 0;