diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 155 |
1 files changed, 122 insertions, 33 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d3fe2d23748..fd031e821f4 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -799,6 +799,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
799 | 799 | ||
800 | qparam.uapsd = false; | 800 | qparam.uapsd = false; |
801 | 801 | ||
802 | local->tx_conf[queue] = qparam; | ||
802 | drv_conf_tx(local, queue, &qparam); | 803 | drv_conf_tx(local, queue, &qparam); |
803 | } | 804 | } |
804 | 805 | ||
@@ -1016,9 +1017,10 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1016 | } | 1017 | } |
1017 | 1018 | ||
1018 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1019 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1019 | u8 *dst, | 1020 | u8 *dst, u32 ratemask, |
1020 | const u8 *ssid, size_t ssid_len, | 1021 | const u8 *ssid, size_t ssid_len, |
1021 | const u8 *ie, size_t ie_len) | 1022 | const u8 *ie, size_t ie_len, |
1023 | bool directed) | ||
1022 | { | 1024 | { |
1023 | struct ieee80211_local *local = sdata->local; | 1025 | struct ieee80211_local *local = sdata->local; |
1024 | struct sk_buff *skb; | 1026 | struct sk_buff *skb; |
@@ -1035,18 +1037,26 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1035 | return NULL; | 1037 | return NULL; |
1036 | } | 1038 | } |
1037 | 1039 | ||
1038 | chan = ieee80211_frequency_to_channel( | 1040 | /* |
1039 | local->hw.conf.channel->center_freq); | 1041 | * Do not send DS Channel parameter for directed probe requests |
1042 | * in order to maximize the chance that we get a response. Some | ||
1043 | * badly-behaved APs don't respond when this parameter is included. | ||
1044 | */ | ||
1045 | if (directed) | ||
1046 | chan = 0; | ||
1047 | else | ||
1048 | chan = ieee80211_frequency_to_channel( | ||
1049 | local->hw.conf.channel->center_freq); | ||
1040 | 1050 | ||
1041 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, | 1051 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, |
1042 | local->hw.conf.channel->band, | 1052 | local->hw.conf.channel->band, |
1043 | sdata->rc_rateidx_mask | 1053 | ratemask, chan); |
1044 | [local->hw.conf.channel->band], | ||
1045 | chan); | ||
1046 | 1054 | ||
1047 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1055 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1048 | ssid, ssid_len, | 1056 | ssid, ssid_len, |
1049 | buf, buf_len); | 1057 | buf, buf_len); |
1058 | if (!skb) | ||
1059 | goto out; | ||
1050 | 1060 | ||
1051 | if (dst) { | 1061 | if (dst) { |
1052 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1062 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -1055,6 +1065,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1055 | } | 1065 | } |
1056 | 1066 | ||
1057 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1067 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
1068 | |||
1069 | out: | ||
1058 | kfree(buf); | 1070 | kfree(buf); |
1059 | 1071 | ||
1060 | return skb; | 1072 | return skb; |
@@ -1062,11 +1074,13 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1062 | 1074 | ||
1063 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1075 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1064 | const u8 *ssid, size_t ssid_len, | 1076 | const u8 *ssid, size_t ssid_len, |
1065 | const u8 *ie, size_t ie_len) | 1077 | const u8 *ie, size_t ie_len, |
1078 | u32 ratemask, bool directed) | ||
1066 | { | 1079 | { |
1067 | struct sk_buff *skb; | 1080 | struct sk_buff *skb; |
1068 | 1081 | ||
1069 | skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len); | 1082 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, |
1083 | ie, ie_len, directed); | ||
1070 | if (skb) | 1084 | if (skb) |
1071 | ieee80211_tx_skb(sdata, skb); | 1085 | ieee80211_tx_skb(sdata, skb); |
1072 | } | 1086 | } |
@@ -1123,7 +1137,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1123 | struct ieee80211_hw *hw = &local->hw; | 1137 | struct ieee80211_hw *hw = &local->hw; |
1124 | struct ieee80211_sub_if_data *sdata; | 1138 | struct ieee80211_sub_if_data *sdata; |
1125 | struct sta_info *sta; | 1139 | struct sta_info *sta; |
1126 | int res; | 1140 | int res, i; |
1127 | 1141 | ||
1128 | #ifdef CONFIG_PM | 1142 | #ifdef CONFIG_PM |
1129 | if (local->suspended) | 1143 | if (local->suspended) |
@@ -1146,27 +1160,37 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1146 | } | 1160 | } |
1147 | #endif | 1161 | #endif |
1148 | 1162 | ||
1149 | /* restart hardware */ | 1163 | /* setup fragmentation threshold */ |
1150 | if (local->open_count) { | 1164 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); |
1151 | /* | 1165 | |
1152 | * Upon resume hardware can sometimes be goofy due to | 1166 | /* setup RTS threshold */ |
1153 | * various platform / driver / bus issues, so restarting | 1167 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); |
1154 | * the device may at times not work immediately. Propagate | 1168 | |
1155 | * the error. | 1169 | /* reset coverage class */ |
1156 | */ | 1170 | drv_set_coverage_class(local, hw->wiphy->coverage_class); |
1157 | res = drv_start(local); | ||
1158 | if (res) { | ||
1159 | WARN(local->suspended, "Hardware became unavailable " | ||
1160 | "upon resume. This could be a software issue " | ||
1161 | "prior to suspend or a hardware issue.\n"); | ||
1162 | return res; | ||
1163 | } | ||
1164 | 1171 | ||
1165 | ieee80211_led_radio(local, true); | 1172 | /* everything else happens only if HW was up & running */ |
1166 | ieee80211_mod_tpt_led_trig(local, | 1173 | if (!local->open_count) |
1167 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | 1174 | goto wake_up; |
1175 | |||
1176 | /* | ||
1177 | * Upon resume hardware can sometimes be goofy due to | ||
1178 | * various platform / driver / bus issues, so restarting | ||
1179 | * the device may at times not work immediately. Propagate | ||
1180 | * the error. | ||
1181 | */ | ||
1182 | res = drv_start(local); | ||
1183 | if (res) { | ||
1184 | WARN(local->suspended, "Hardware became unavailable " | ||
1185 | "upon resume. This could be a software issue " | ||
1186 | "prior to suspend or a hardware issue.\n"); | ||
1187 | return res; | ||
1168 | } | 1188 | } |
1169 | 1189 | ||
1190 | ieee80211_led_radio(local, true); | ||
1191 | ieee80211_mod_tpt_led_trig(local, | ||
1192 | IEEE80211_TPT_LEDTRIG_FL_RADIO, 0); | ||
1193 | |||
1170 | /* add interfaces */ | 1194 | /* add interfaces */ |
1171 | list_for_each_entry(sdata, &local->interfaces, list) { | 1195 | list_for_each_entry(sdata, &local->interfaces, list) { |
1172 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1196 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
@@ -1190,11 +1214,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1190 | } | 1214 | } |
1191 | mutex_unlock(&local->sta_mtx); | 1215 | mutex_unlock(&local->sta_mtx); |
1192 | 1216 | ||
1193 | /* setup fragmentation threshold */ | 1217 | /* reconfigure tx conf */ |
1194 | drv_set_frag_threshold(local, hw->wiphy->frag_threshold); | 1218 | for (i = 0; i < hw->queues; i++) |
1195 | 1219 | drv_conf_tx(local, i, &local->tx_conf[i]); | |
1196 | /* setup RTS threshold */ | ||
1197 | drv_set_rts_threshold(local, hw->wiphy->rts_threshold); | ||
1198 | 1220 | ||
1199 | /* reconfigure hardware */ | 1221 | /* reconfigure hardware */ |
1200 | ieee80211_hw_config(local, ~0); | 1222 | ieee80211_hw_config(local, ~0); |
@@ -1321,6 +1343,33 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1321 | return 0; | 1343 | return 0; |
1322 | } | 1344 | } |
1323 | 1345 | ||
1346 | void ieee80211_resume_disconnect(struct ieee80211_vif *vif) | ||
1347 | { | ||
1348 | struct ieee80211_sub_if_data *sdata; | ||
1349 | struct ieee80211_local *local; | ||
1350 | struct ieee80211_key *key; | ||
1351 | |||
1352 | if (WARN_ON(!vif)) | ||
1353 | return; | ||
1354 | |||
1355 | sdata = vif_to_sdata(vif); | ||
1356 | local = sdata->local; | ||
1357 | |||
1358 | if (WARN_ON(!local->resuming)) | ||
1359 | return; | ||
1360 | |||
1361 | if (WARN_ON(vif->type != NL80211_IFTYPE_STATION)) | ||
1362 | return; | ||
1363 | |||
1364 | sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME; | ||
1365 | |||
1366 | mutex_lock(&local->key_mtx); | ||
1367 | list_for_each_entry(key, &sdata->key_list, list) | ||
1368 | key->flags |= KEY_FLAG_TAINTED; | ||
1369 | mutex_unlock(&local->key_mtx); | ||
1370 | } | ||
1371 | EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect); | ||
1372 | |||
1324 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, | 1373 | static int check_mgd_smps(struct ieee80211_if_managed *ifmgd, |
1325 | enum ieee80211_smps_mode *smps_mode) | 1374 | enum ieee80211_smps_mode *smps_mode) |
1326 | { | 1375 | { |
@@ -1437,3 +1486,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) | |||
1437 | 1486 | ||
1438 | return pos; | 1487 | return pos; |
1439 | } | 1488 | } |
1489 | |||
1490 | static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata, | ||
1491 | int rssi_min_thold, | ||
1492 | int rssi_max_thold) | ||
1493 | { | ||
1494 | trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold); | ||
1495 | |||
1496 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) | ||
1497 | return; | ||
1498 | |||
1499 | /* | ||
1500 | * Scale up threshold values before storing it, as the RSSI averaging | ||
1501 | * algorithm uses a scaled up value as well. Change this scaling | ||
1502 | * factor if the RSSI averaging algorithm changes. | ||
1503 | */ | ||
1504 | sdata->u.mgd.rssi_min_thold = rssi_min_thold*16; | ||
1505 | sdata->u.mgd.rssi_max_thold = rssi_max_thold*16; | ||
1506 | } | ||
1507 | |||
1508 | void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, | ||
1509 | int rssi_min_thold, | ||
1510 | int rssi_max_thold) | ||
1511 | { | ||
1512 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1513 | |||
1514 | WARN_ON(rssi_min_thold == rssi_max_thold || | ||
1515 | rssi_min_thold > rssi_max_thold); | ||
1516 | |||
1517 | _ieee80211_enable_rssi_reports(sdata, rssi_min_thold, | ||
1518 | rssi_max_thold); | ||
1519 | } | ||
1520 | EXPORT_SYMBOL(ieee80211_enable_rssi_reports); | ||
1521 | |||
1522 | void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif) | ||
1523 | { | ||
1524 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
1525 | |||
1526 | _ieee80211_enable_rssi_reports(sdata, 0, 0); | ||
1527 | } | ||
1528 | EXPORT_SYMBOL(ieee80211_disable_rssi_reports); | ||