diff options
41 files changed, 1406 insertions, 390 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1737a3e33685..1adb803a9d86 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2094,7 +2094,7 @@ static void ath9k_wow_add_pattern(struct ath_softc *sc, | |||
2094 | { | 2094 | { |
2095 | struct ath_hw *ah = sc->sc_ah; | 2095 | struct ath_hw *ah = sc->sc_ah; |
2096 | struct ath9k_wow_pattern *wow_pattern = NULL; | 2096 | struct ath9k_wow_pattern *wow_pattern = NULL; |
2097 | struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns; | 2097 | struct cfg80211_pkt_pattern *patterns = wowlan->patterns; |
2098 | int mask_len; | 2098 | int mask_len; |
2099 | s8 i = 0; | 2099 | s8 i = 0; |
2100 | 2100 | ||
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 7eb1f4b458e4..a3c4ca0c94bf 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -1275,6 +1275,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1275 | } | 1275 | } |
1276 | 1276 | ||
1277 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | 1277 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
1278 | struct cfg80211_chan_def *chandef, | ||
1278 | struct ieee80211_sta *sta, void *priv_sta) | 1279 | struct ieee80211_sta *sta, void *priv_sta) |
1279 | { | 1280 | { |
1280 | struct ath_softc *sc = priv; | 1281 | struct ath_softc *sc = priv; |
@@ -1313,6 +1314,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1313 | } | 1314 | } |
1314 | 1315 | ||
1315 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | 1316 | static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, |
1317 | struct cfg80211_chan_def *chandef, | ||
1316 | struct ieee80211_sta *sta, void *priv_sta, | 1318 | struct ieee80211_sta *sta, void *priv_sta, |
1317 | u32 changed) | 1319 | u32 changed) |
1318 | { | 1320 | { |
diff --git a/drivers/net/wireless/iwlegacy/3945-rs.c b/drivers/net/wireless/iwlegacy/3945-rs.c index fe31590a51b2..aea667b430c3 100644 --- a/drivers/net/wireless/iwlegacy/3945-rs.c +++ b/drivers/net/wireless/iwlegacy/3945-rs.c | |||
@@ -887,6 +887,7 @@ il3945_remove_debugfs(void *il, void *il_sta) | |||
887 | */ | 887 | */ |
888 | static void | 888 | static void |
889 | il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, | 889 | il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, |
890 | struct cfg80211_chan_def *chandef, | ||
890 | struct ieee80211_sta *sta, void *il_sta) | 891 | struct ieee80211_sta *sta, void *il_sta) |
891 | { | 892 | { |
892 | } | 893 | } |
diff --git a/drivers/net/wireless/iwlegacy/4965-rs.c b/drivers/net/wireless/iwlegacy/4965-rs.c index ed3c42a63a43..3ccbaf791b48 100644 --- a/drivers/net/wireless/iwlegacy/4965-rs.c +++ b/drivers/net/wireless/iwlegacy/4965-rs.c | |||
@@ -2803,6 +2803,7 @@ il4965_rs_remove_debugfs(void *il, void *il_sta) | |||
2803 | */ | 2803 | */ |
2804 | static void | 2804 | static void |
2805 | il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, | 2805 | il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, |
2806 | struct cfg80211_chan_def *chandef, | ||
2806 | struct ieee80211_sta *sta, void *il_sta) | 2807 | struct ieee80211_sta *sta, void *il_sta) |
2807 | { | 2808 | { |
2808 | } | 2809 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c index 1b693944123b..91eb09b9b56f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/iwlwifi/dvm/rs.c | |||
@@ -3319,7 +3319,8 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) | |||
3319 | * station is added we ignore it. | 3319 | * station is added we ignore it. |
3320 | */ | 3320 | */ |
3321 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, | 3321 | static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband, |
3322 | struct ieee80211_sta *sta, void *priv_sta) | 3322 | struct cfg80211_chan_def *chandef, |
3323 | struct ieee80211_sta *sta, void *priv_sta) | ||
3323 | { | 3324 | { |
3324 | } | 3325 | } |
3325 | static struct rate_control_ops rs_ops = { | 3326 | static struct rate_control_ops rs_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index b328a988c130..376ea2112de2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -3159,8 +3159,9 @@ static void rs_remove_debugfs(void *mvm, void *mvm_sta) | |||
3159 | * station is added we ignore it. | 3159 | * station is added we ignore it. |
3160 | */ | 3160 | */ |
3161 | static void rs_rate_init_stub(void *mvm_r, | 3161 | static void rs_rate_init_stub(void *mvm_r, |
3162 | struct ieee80211_supported_band *sband, | 3162 | struct ieee80211_supported_band *sband, |
3163 | struct ieee80211_sta *sta, void *mvm_sta) | 3163 | struct cfg80211_chan_def *chandef, |
3164 | struct ieee80211_sta *sta, void *mvm_sta) | ||
3164 | { | 3165 | { |
3165 | } | 3166 | } |
3166 | static struct rate_control_ops rs_mvm_ops = { | 3167 | static struct rate_control_ops rs_mvm_ops = { |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index cb34c7895f2a..7b2a6229eedb 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -867,7 +867,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
867 | 867 | ||
868 | if (WARN_ON(skb->len < 10)) { | 868 | if (WARN_ON(skb->len < 10)) { |
869 | /* Should not happen; just a sanity check for addr1 use */ | 869 | /* Should not happen; just a sanity check for addr1 use */ |
870 | dev_kfree_skb(skb); | 870 | ieee80211_free_txskb(hw, skb); |
871 | return; | 871 | return; |
872 | } | 872 | } |
873 | 873 | ||
@@ -884,13 +884,13 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
884 | } | 884 | } |
885 | 885 | ||
886 | if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) { | 886 | if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) { |
887 | dev_kfree_skb(skb); | 887 | ieee80211_free_txskb(hw, skb); |
888 | return; | 888 | return; |
889 | } | 889 | } |
890 | 890 | ||
891 | if (data->idle && !data->tmp_chan) { | 891 | if (data->idle && !data->tmp_chan) { |
892 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); | 892 | wiphy_debug(hw->wiphy, "Trying to TX when idle - reject\n"); |
893 | dev_kfree_skb(skb); | 893 | ieee80211_free_txskb(hw, skb); |
894 | return; | 894 | return; |
895 | } | 895 | } |
896 | 896 | ||
@@ -2309,7 +2309,9 @@ static int __init init_mac80211_hwsim(void) | |||
2309 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; | 2309 | hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE; |
2310 | 2310 | ||
2311 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | | 2311 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | |
2312 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; | 2312 | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | |
2313 | WIPHY_FLAG_AP_UAPSD; | ||
2314 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | ||
2313 | 2315 | ||
2314 | /* ask mac80211 to reserve space for magic */ | 2316 | /* ask mac80211 to reserve space for magic */ |
2315 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 2317 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index cc334d529dbe..8a752637f0ce 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -2309,8 +2309,7 @@ EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); | |||
2309 | 2309 | ||
2310 | #ifdef CONFIG_PM | 2310 | #ifdef CONFIG_PM |
2311 | static bool | 2311 | static bool |
2312 | mwifiex_is_pattern_supported(struct cfg80211_wowlan_trig_pkt_pattern *pat, | 2312 | mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq) |
2313 | s8 *byte_seq) | ||
2314 | { | 2313 | { |
2315 | int j, k, valid_byte_cnt = 0; | 2314 | int j, k, valid_byte_cnt = 0; |
2316 | bool dont_care_byte = false; | 2315 | bool dont_care_byte = false; |
diff --git a/drivers/net/wireless/rtlwifi/rc.c b/drivers/net/wireless/rtlwifi/rc.c index f9f059dadb73..a98acefb8c06 100644 --- a/drivers/net/wireless/rtlwifi/rc.c +++ b/drivers/net/wireless/rtlwifi/rc.c | |||
@@ -218,6 +218,7 @@ static void rtl_tx_status(void *ppriv, | |||
218 | 218 | ||
219 | static void rtl_rate_init(void *ppriv, | 219 | static void rtl_rate_init(void *ppriv, |
220 | struct ieee80211_supported_band *sband, | 220 | struct ieee80211_supported_band *sband, |
221 | struct cfg80211_chan_def *chandef, | ||
221 | struct ieee80211_sta *sta, void *priv_sta) | 222 | struct ieee80211_sta *sta, void *priv_sta) |
222 | { | 223 | { |
223 | } | 224 | } |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index b8db55c868c7..d1b19c38a907 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -1315,7 +1315,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | |||
1315 | 1315 | ||
1316 | #ifdef CONFIG_PM | 1316 | #ifdef CONFIG_PM |
1317 | static int | 1317 | static int |
1318 | wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p) | 1318 | wl1271_validate_wowlan_pattern(struct cfg80211_pkt_pattern *p) |
1319 | { | 1319 | { |
1320 | int num_fields = 0, in_field = 0, fields_size = 0; | 1320 | int num_fields = 0, in_field = 0, fields_size = 0; |
1321 | int i, pattern_len = 0; | 1321 | int i, pattern_len = 0; |
@@ -1458,9 +1458,9 @@ void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | |||
1458 | * Allocates an RX filter returned through f | 1458 | * Allocates an RX filter returned through f |
1459 | * which needs to be freed using rx_filter_free() | 1459 | * which needs to be freed using rx_filter_free() |
1460 | */ | 1460 | */ |
1461 | static int wl1271_convert_wowlan_pattern_to_rx_filter( | 1461 | static int |
1462 | struct cfg80211_wowlan_trig_pkt_pattern *p, | 1462 | wl1271_convert_wowlan_pattern_to_rx_filter(struct cfg80211_pkt_pattern *p, |
1463 | struct wl12xx_rx_filter **f) | 1463 | struct wl12xx_rx_filter **f) |
1464 | { | 1464 | { |
1465 | int i, j, ret = 0; | 1465 | int i, j, ret = 0; |
1466 | struct wl12xx_rx_filter *filter; | 1466 | struct wl12xx_rx_filter *filter; |
@@ -1562,7 +1562,7 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
1562 | 1562 | ||
1563 | /* Translate WoWLAN patterns into filters */ | 1563 | /* Translate WoWLAN patterns into filters */ |
1564 | for (i = 0; i < wow->n_patterns; i++) { | 1564 | for (i = 0; i < wow->n_patterns; i++) { |
1565 | struct cfg80211_wowlan_trig_pkt_pattern *p; | 1565 | struct cfg80211_pkt_pattern *p; |
1566 | struct wl12xx_rx_filter *filter = NULL; | 1566 | struct wl12xx_rx_filter *filter = NULL; |
1567 | 1567 | ||
1568 | p = &wow->patterns[i]; | 1568 | p = &wow->patterns[i]; |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7b0730aeb892..aeaf6dff6e05 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -461,6 +461,33 @@ ieee80211_chandef_rate_flags(struct cfg80211_chan_def *chandef) | |||
461 | } | 461 | } |
462 | 462 | ||
463 | /** | 463 | /** |
464 | * ieee80211_chandef_max_power - maximum transmission power for the chandef | ||
465 | * | ||
466 | * In some regulations, the transmit power may depend on the configured channel | ||
467 | * bandwidth which may be defined as dBm/MHz. This function returns the actual | ||
468 | * max_power for non-standard (20 MHz) channels. | ||
469 | * | ||
470 | * @chandef: channel definition for the channel | ||
471 | * | ||
472 | * Returns: maximum allowed transmission power in dBm for the chandef | ||
473 | */ | ||
474 | static inline int | ||
475 | ieee80211_chandef_max_power(struct cfg80211_chan_def *chandef) | ||
476 | { | ||
477 | switch (chandef->width) { | ||
478 | case NL80211_CHAN_WIDTH_5: | ||
479 | return min(chandef->chan->max_reg_power - 6, | ||
480 | chandef->chan->max_power); | ||
481 | case NL80211_CHAN_WIDTH_10: | ||
482 | return min(chandef->chan->max_reg_power - 3, | ||
483 | chandef->chan->max_power); | ||
484 | default: | ||
485 | break; | ||
486 | } | ||
487 | return chandef->chan->max_power; | ||
488 | } | ||
489 | |||
490 | /** | ||
464 | * enum survey_info_flags - survey information flags | 491 | * enum survey_info_flags - survey information flags |
465 | * | 492 | * |
466 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in | 493 | * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in |
@@ -490,7 +517,7 @@ enum survey_info_flags { | |||
490 | * @channel: the channel this survey record reports, mandatory | 517 | * @channel: the channel this survey record reports, mandatory |
491 | * @filled: bitflag of flags from &enum survey_info_flags | 518 | * @filled: bitflag of flags from &enum survey_info_flags |
492 | * @noise: channel noise in dBm. This and all following fields are | 519 | * @noise: channel noise in dBm. This and all following fields are |
493 | * optional | 520 | * optional |
494 | * @channel_time: amount of time in ms the radio spent on the channel | 521 | * @channel_time: amount of time in ms the radio spent on the channel |
495 | * @channel_time_busy: amount of time the primary channel was sensed busy | 522 | * @channel_time_busy: amount of time the primary channel was sensed busy |
496 | * @channel_time_ext_busy: amount of time the extension channel was sensed busy | 523 | * @channel_time_ext_busy: amount of time the extension channel was sensed busy |
@@ -546,9 +573,9 @@ struct cfg80211_crypto_settings { | |||
546 | /** | 573 | /** |
547 | * struct cfg80211_beacon_data - beacon data | 574 | * struct cfg80211_beacon_data - beacon data |
548 | * @head: head portion of beacon (before TIM IE) | 575 | * @head: head portion of beacon (before TIM IE) |
549 | * or %NULL if not changed | 576 | * or %NULL if not changed |
550 | * @tail: tail portion of beacon (after TIM IE) | 577 | * @tail: tail portion of beacon (after TIM IE) |
551 | * or %NULL if not changed | 578 | * or %NULL if not changed |
552 | * @head_len: length of @head | 579 | * @head_len: length of @head |
553 | * @tail_len: length of @tail | 580 | * @tail_len: length of @tail |
554 | * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL | 581 | * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL |
@@ -764,7 +791,7 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
764 | * @STATION_INFO_PLINK_STATE: @plink_state filled | 791 | * @STATION_INFO_PLINK_STATE: @plink_state filled |
765 | * @STATION_INFO_SIGNAL: @signal filled | 792 | * @STATION_INFO_SIGNAL: @signal filled |
766 | * @STATION_INFO_TX_BITRATE: @txrate fields are filled | 793 | * @STATION_INFO_TX_BITRATE: @txrate fields are filled |
767 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | 794 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) |
768 | * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value | 795 | * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value |
769 | * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value | 796 | * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value |
770 | * @STATION_INFO_TX_RETRIES: @tx_retries filled | 797 | * @STATION_INFO_TX_RETRIES: @tx_retries filled |
@@ -1285,6 +1312,7 @@ struct cfg80211_ssid { | |||
1285 | * @n_ssids: number of SSIDs | 1312 | * @n_ssids: number of SSIDs |
1286 | * @channels: channels to scan on. | 1313 | * @channels: channels to scan on. |
1287 | * @n_channels: total number of channels to scan | 1314 | * @n_channels: total number of channels to scan |
1315 | * @scan_width: channel width for scanning | ||
1288 | * @ie: optional information element(s) to add into Probe Request or %NULL | 1316 | * @ie: optional information element(s) to add into Probe Request or %NULL |
1289 | * @ie_len: length of ie in octets | 1317 | * @ie_len: length of ie in octets |
1290 | * @flags: bit field of flags controlling operation | 1318 | * @flags: bit field of flags controlling operation |
@@ -1300,6 +1328,7 @@ struct cfg80211_scan_request { | |||
1300 | struct cfg80211_ssid *ssids; | 1328 | struct cfg80211_ssid *ssids; |
1301 | int n_ssids; | 1329 | int n_ssids; |
1302 | u32 n_channels; | 1330 | u32 n_channels; |
1331 | enum nl80211_bss_scan_width scan_width; | ||
1303 | const u8 *ie; | 1332 | const u8 *ie; |
1304 | size_t ie_len; | 1333 | size_t ie_len; |
1305 | u32 flags; | 1334 | u32 flags; |
@@ -1333,6 +1362,7 @@ struct cfg80211_match_set { | |||
1333 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) | 1362 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) |
1334 | * @n_ssids: number of SSIDs | 1363 | * @n_ssids: number of SSIDs |
1335 | * @n_channels: total number of channels to scan | 1364 | * @n_channels: total number of channels to scan |
1365 | * @scan_width: channel width for scanning | ||
1336 | * @interval: interval between each scheduled scan cycle | 1366 | * @interval: interval between each scheduled scan cycle |
1337 | * @ie: optional information element(s) to add into Probe Request or %NULL | 1367 | * @ie: optional information element(s) to add into Probe Request or %NULL |
1338 | * @ie_len: length of ie in octets | 1368 | * @ie_len: length of ie in octets |
@@ -1352,6 +1382,7 @@ struct cfg80211_sched_scan_request { | |||
1352 | struct cfg80211_ssid *ssids; | 1382 | struct cfg80211_ssid *ssids; |
1353 | int n_ssids; | 1383 | int n_ssids; |
1354 | u32 n_channels; | 1384 | u32 n_channels; |
1385 | enum nl80211_bss_scan_width scan_width; | ||
1355 | u32 interval; | 1386 | u32 interval; |
1356 | const u8 *ie; | 1387 | const u8 *ie; |
1357 | size_t ie_len; | 1388 | size_t ie_len; |
@@ -1403,6 +1434,7 @@ struct cfg80211_bss_ies { | |||
1403 | * for use in scan results and similar. | 1434 | * for use in scan results and similar. |
1404 | * | 1435 | * |
1405 | * @channel: channel this BSS is on | 1436 | * @channel: channel this BSS is on |
1437 | * @scan_width: width of the control channel | ||
1406 | * @bssid: BSSID of the BSS | 1438 | * @bssid: BSSID of the BSS |
1407 | * @beacon_interval: the beacon interval as from the frame | 1439 | * @beacon_interval: the beacon interval as from the frame |
1408 | * @capability: the capability field in host byte order | 1440 | * @capability: the capability field in host byte order |
@@ -1424,6 +1456,7 @@ struct cfg80211_bss_ies { | |||
1424 | */ | 1456 | */ |
1425 | struct cfg80211_bss { | 1457 | struct cfg80211_bss { |
1426 | struct ieee80211_channel *channel; | 1458 | struct ieee80211_channel *channel; |
1459 | enum nl80211_bss_scan_width scan_width; | ||
1427 | 1460 | ||
1428 | const struct cfg80211_bss_ies __rcu *ies; | 1461 | const struct cfg80211_bss_ies __rcu *ies; |
1429 | const struct cfg80211_bss_ies __rcu *beacon_ies; | 1462 | const struct cfg80211_bss_ies __rcu *beacon_ies; |
@@ -1509,7 +1542,7 @@ enum cfg80211_assoc_req_flags { | |||
1509 | * @prev_bssid: previous BSSID, if not %NULL use reassociate frame | 1542 | * @prev_bssid: previous BSSID, if not %NULL use reassociate frame |
1510 | * @flags: See &enum cfg80211_assoc_req_flags | 1543 | * @flags: See &enum cfg80211_assoc_req_flags |
1511 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1544 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
1512 | * will be used in ht_capa. Un-supported values will be ignored. | 1545 | * will be used in ht_capa. Un-supported values will be ignored. |
1513 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1546 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
1514 | * @vht_capa: VHT capability override | 1547 | * @vht_capa: VHT capability override |
1515 | * @vht_capa_mask: VHT capability mask indicating which fields to use | 1548 | * @vht_capa_mask: VHT capability mask indicating which fields to use |
@@ -1592,6 +1625,9 @@ struct cfg80211_disassoc_request { | |||
1592 | * user space. Otherwise, port is marked authorized by default. | 1625 | * user space. Otherwise, port is marked authorized by default. |
1593 | * @basic_rates: bitmap of basic rates to use when creating the IBSS | 1626 | * @basic_rates: bitmap of basic rates to use when creating the IBSS |
1594 | * @mcast_rate: per-band multicast rate index + 1 (0: disabled) | 1627 | * @mcast_rate: per-band multicast rate index + 1 (0: disabled) |
1628 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | ||
1629 | * will be used in ht_capa. Un-supported values will be ignored. | ||
1630 | * @ht_capa_mask: The bits of ht_capa which are to be used. | ||
1595 | */ | 1631 | */ |
1596 | struct cfg80211_ibss_params { | 1632 | struct cfg80211_ibss_params { |
1597 | u8 *ssid; | 1633 | u8 *ssid; |
@@ -1605,6 +1641,8 @@ struct cfg80211_ibss_params { | |||
1605 | bool privacy; | 1641 | bool privacy; |
1606 | bool control_port; | 1642 | bool control_port; |
1607 | int mcast_rate[IEEE80211_NUM_BANDS]; | 1643 | int mcast_rate[IEEE80211_NUM_BANDS]; |
1644 | struct ieee80211_ht_cap ht_capa; | ||
1645 | struct ieee80211_ht_cap ht_capa_mask; | ||
1608 | }; | 1646 | }; |
1609 | 1647 | ||
1610 | /** | 1648 | /** |
@@ -1630,9 +1668,9 @@ struct cfg80211_ibss_params { | |||
1630 | * @key: WEP key for shared key authentication | 1668 | * @key: WEP key for shared key authentication |
1631 | * @flags: See &enum cfg80211_assoc_req_flags | 1669 | * @flags: See &enum cfg80211_assoc_req_flags |
1632 | * @bg_scan_period: Background scan period in seconds | 1670 | * @bg_scan_period: Background scan period in seconds |
1633 | * or -1 to indicate that default value is to be used. | 1671 | * or -1 to indicate that default value is to be used. |
1634 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask | 1672 | * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask |
1635 | * will be used in ht_capa. Un-supported values will be ignored. | 1673 | * will be used in ht_capa. Un-supported values will be ignored. |
1636 | * @ht_capa_mask: The bits of ht_capa which are to be used. | 1674 | * @ht_capa_mask: The bits of ht_capa which are to be used. |
1637 | * @vht_capa: VHT Capability overrides | 1675 | * @vht_capa: VHT Capability overrides |
1638 | * @vht_capa_mask: The bits of vht_capa which are to be used. | 1676 | * @vht_capa_mask: The bits of vht_capa which are to be used. |
@@ -1698,7 +1736,7 @@ struct cfg80211_pmksa { | |||
1698 | }; | 1736 | }; |
1699 | 1737 | ||
1700 | /** | 1738 | /** |
1701 | * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern | 1739 | * struct cfg80211_pkt_pattern - packet pattern |
1702 | * @mask: bitmask where to match pattern and where to ignore bytes, | 1740 | * @mask: bitmask where to match pattern and where to ignore bytes, |
1703 | * one bit per byte, in same format as nl80211 | 1741 | * one bit per byte, in same format as nl80211 |
1704 | * @pattern: bytes to match where bitmask is 1 | 1742 | * @pattern: bytes to match where bitmask is 1 |
@@ -1708,7 +1746,7 @@ struct cfg80211_pmksa { | |||
1708 | * Internal note: @mask and @pattern are allocated in one chunk of | 1746 | * Internal note: @mask and @pattern are allocated in one chunk of |
1709 | * memory, free @mask only! | 1747 | * memory, free @mask only! |
1710 | */ | 1748 | */ |
1711 | struct cfg80211_wowlan_trig_pkt_pattern { | 1749 | struct cfg80211_pkt_pattern { |
1712 | u8 *mask, *pattern; | 1750 | u8 *mask, *pattern; |
1713 | int pattern_len; | 1751 | int pattern_len; |
1714 | int pkt_offset; | 1752 | int pkt_offset; |
@@ -1770,12 +1808,41 @@ struct cfg80211_wowlan { | |||
1770 | bool any, disconnect, magic_pkt, gtk_rekey_failure, | 1808 | bool any, disconnect, magic_pkt, gtk_rekey_failure, |
1771 | eap_identity_req, four_way_handshake, | 1809 | eap_identity_req, four_way_handshake, |
1772 | rfkill_release; | 1810 | rfkill_release; |
1773 | struct cfg80211_wowlan_trig_pkt_pattern *patterns; | 1811 | struct cfg80211_pkt_pattern *patterns; |
1774 | struct cfg80211_wowlan_tcp *tcp; | 1812 | struct cfg80211_wowlan_tcp *tcp; |
1775 | int n_patterns; | 1813 | int n_patterns; |
1776 | }; | 1814 | }; |
1777 | 1815 | ||
1778 | /** | 1816 | /** |
1817 | * struct cfg80211_coalesce_rules - Coalesce rule parameters | ||
1818 | * | ||
1819 | * This structure defines coalesce rule for the device. | ||
1820 | * @delay: maximum coalescing delay in msecs. | ||
1821 | * @condition: condition for packet coalescence. | ||
1822 | * see &enum nl80211_coalesce_condition. | ||
1823 | * @patterns: array of packet patterns | ||
1824 | * @n_patterns: number of patterns | ||
1825 | */ | ||
1826 | struct cfg80211_coalesce_rules { | ||
1827 | int delay; | ||
1828 | enum nl80211_coalesce_condition condition; | ||
1829 | struct cfg80211_pkt_pattern *patterns; | ||
1830 | int n_patterns; | ||
1831 | }; | ||
1832 | |||
1833 | /** | ||
1834 | * struct cfg80211_coalesce - Packet coalescing settings | ||
1835 | * | ||
1836 | * This structure defines coalescing settings. | ||
1837 | * @rules: array of coalesce rules | ||
1838 | * @n_rules: number of rules | ||
1839 | */ | ||
1840 | struct cfg80211_coalesce { | ||
1841 | struct cfg80211_coalesce_rules *rules; | ||
1842 | int n_rules; | ||
1843 | }; | ||
1844 | |||
1845 | /** | ||
1779 | * struct cfg80211_wowlan_wakeup - wakeup report | 1846 | * struct cfg80211_wowlan_wakeup - wakeup report |
1780 | * @disconnect: woke up by getting disconnected | 1847 | * @disconnect: woke up by getting disconnected |
1781 | * @magic_pkt: woke up by receiving magic packet | 1848 | * @magic_pkt: woke up by receiving magic packet |
@@ -2071,6 +2138,7 @@ struct cfg80211_update_ft_ies_params { | |||
2071 | * driver can take the most appropriate actions. | 2138 | * driver can take the most appropriate actions. |
2072 | * @crit_proto_stop: Indicates critical protocol no longer needs increased link | 2139 | * @crit_proto_stop: Indicates critical protocol no longer needs increased link |
2073 | * reliability. This operation can not fail. | 2140 | * reliability. This operation can not fail. |
2141 | * @set_coalesce: Set coalesce parameters. | ||
2074 | */ | 2142 | */ |
2075 | struct cfg80211_ops { | 2143 | struct cfg80211_ops { |
2076 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); | 2144 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
@@ -2306,6 +2374,8 @@ struct cfg80211_ops { | |||
2306 | u16 duration); | 2374 | u16 duration); |
2307 | void (*crit_proto_stop)(struct wiphy *wiphy, | 2375 | void (*crit_proto_stop)(struct wiphy *wiphy, |
2308 | struct wireless_dev *wdev); | 2376 | struct wireless_dev *wdev); |
2377 | int (*set_coalesce)(struct wiphy *wiphy, | ||
2378 | struct cfg80211_coalesce *coalesce); | ||
2309 | }; | 2379 | }; |
2310 | 2380 | ||
2311 | /* | 2381 | /* |
@@ -2532,6 +2602,25 @@ struct wiphy_wowlan_support { | |||
2532 | }; | 2602 | }; |
2533 | 2603 | ||
2534 | /** | 2604 | /** |
2605 | * struct wiphy_coalesce_support - coalesce support data | ||
2606 | * @n_rules: maximum number of coalesce rules | ||
2607 | * @max_delay: maximum supported coalescing delay in msecs | ||
2608 | * @n_patterns: number of supported patterns in a rule | ||
2609 | * (see nl80211.h for the pattern definition) | ||
2610 | * @pattern_max_len: maximum length of each pattern | ||
2611 | * @pattern_min_len: minimum length of each pattern | ||
2612 | * @max_pkt_offset: maximum Rx packet offset | ||
2613 | */ | ||
2614 | struct wiphy_coalesce_support { | ||
2615 | int n_rules; | ||
2616 | int max_delay; | ||
2617 | int n_patterns; | ||
2618 | int pattern_max_len; | ||
2619 | int pattern_min_len; | ||
2620 | int max_pkt_offset; | ||
2621 | }; | ||
2622 | |||
2623 | /** | ||
2535 | * struct wiphy - wireless hardware description | 2624 | * struct wiphy - wireless hardware description |
2536 | * @reg_notifier: the driver's regulatory notification callback, | 2625 | * @reg_notifier: the driver's regulatory notification callback, |
2537 | * note that if your driver uses wiphy_apply_custom_regulatory() | 2626 | * note that if your driver uses wiphy_apply_custom_regulatory() |
@@ -2641,6 +2730,7 @@ struct wiphy_wowlan_support { | |||
2641 | * 802.11-2012 8.4.2.29 for the defined fields. | 2730 | * 802.11-2012 8.4.2.29 for the defined fields. |
2642 | * @extended_capabilities_mask: mask of the valid values | 2731 | * @extended_capabilities_mask: mask of the valid values |
2643 | * @extended_capabilities_len: length of the extended capabilities | 2732 | * @extended_capabilities_len: length of the extended capabilities |
2733 | * @coalesce: packet coalescing support information | ||
2644 | */ | 2734 | */ |
2645 | struct wiphy { | 2735 | struct wiphy { |
2646 | /* assign these fields before you register the wiphy */ | 2736 | /* assign these fields before you register the wiphy */ |
@@ -2750,6 +2840,8 @@ struct wiphy { | |||
2750 | const struct iw_handler_def *wext; | 2840 | const struct iw_handler_def *wext; |
2751 | #endif | 2841 | #endif |
2752 | 2842 | ||
2843 | const struct wiphy_coalesce_support *coalesce; | ||
2844 | |||
2753 | char priv[0] __aligned(NETDEV_ALIGN); | 2845 | char priv[0] __aligned(NETDEV_ALIGN); |
2754 | }; | 2846 | }; |
2755 | 2847 | ||
@@ -3063,11 +3155,13 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | |||
3063 | /** | 3155 | /** |
3064 | * ieee80211_mandatory_rates - get mandatory rates for a given band | 3156 | * ieee80211_mandatory_rates - get mandatory rates for a given band |
3065 | * @sband: the band to look for rates in | 3157 | * @sband: the band to look for rates in |
3158 | * @scan_width: width of the control channel | ||
3066 | * | 3159 | * |
3067 | * This function returns a bitmap of the mandatory rates for the given | 3160 | * This function returns a bitmap of the mandatory rates for the given |
3068 | * band, bits are set according to the rate position in the bitrates array. | 3161 | * band, bits are set according to the rate position in the bitrates array. |
3069 | */ | 3162 | */ |
3070 | u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband); | 3163 | u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband, |
3164 | enum nl80211_bss_scan_width scan_width); | ||
3071 | 3165 | ||
3072 | /* | 3166 | /* |
3073 | * Radiotap parsing functions -- for controlled injection support | 3167 | * Radiotap parsing functions -- for controlled injection support |
@@ -3379,10 +3473,11 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy); | |||
3379 | void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | 3473 | void cfg80211_sched_scan_stopped(struct wiphy *wiphy); |
3380 | 3474 | ||
3381 | /** | 3475 | /** |
3382 | * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame | 3476 | * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame |
3383 | * | 3477 | * |
3384 | * @wiphy: the wiphy reporting the BSS | 3478 | * @wiphy: the wiphy reporting the BSS |
3385 | * @channel: The channel the frame was received on | 3479 | * @channel: The channel the frame was received on |
3480 | * @scan_width: width of the control channel | ||
3386 | * @mgmt: the management frame (probe response or beacon) | 3481 | * @mgmt: the management frame (probe response or beacon) |
3387 | * @len: length of the management frame | 3482 | * @len: length of the management frame |
3388 | * @signal: the signal strength, type depends on the wiphy's signal_type | 3483 | * @signal: the signal strength, type depends on the wiphy's signal_type |
@@ -3395,16 +3490,29 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | |||
3395 | * Or %NULL on error. | 3490 | * Or %NULL on error. |
3396 | */ | 3491 | */ |
3397 | struct cfg80211_bss * __must_check | 3492 | struct cfg80211_bss * __must_check |
3493 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | ||
3494 | struct ieee80211_channel *channel, | ||
3495 | enum nl80211_bss_scan_width scan_width, | ||
3496 | struct ieee80211_mgmt *mgmt, size_t len, | ||
3497 | s32 signal, gfp_t gfp); | ||
3498 | |||
3499 | static inline struct cfg80211_bss * __must_check | ||
3398 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 3500 | cfg80211_inform_bss_frame(struct wiphy *wiphy, |
3399 | struct ieee80211_channel *channel, | 3501 | struct ieee80211_channel *channel, |
3400 | struct ieee80211_mgmt *mgmt, size_t len, | 3502 | struct ieee80211_mgmt *mgmt, size_t len, |
3401 | s32 signal, gfp_t gfp); | 3503 | s32 signal, gfp_t gfp) |
3504 | { | ||
3505 | return cfg80211_inform_bss_width_frame(wiphy, channel, | ||
3506 | NL80211_BSS_CHAN_WIDTH_20, | ||
3507 | mgmt, len, signal, gfp); | ||
3508 | } | ||
3402 | 3509 | ||
3403 | /** | 3510 | /** |
3404 | * cfg80211_inform_bss - inform cfg80211 of a new BSS | 3511 | * cfg80211_inform_bss - inform cfg80211 of a new BSS |
3405 | * | 3512 | * |
3406 | * @wiphy: the wiphy reporting the BSS | 3513 | * @wiphy: the wiphy reporting the BSS |
3407 | * @channel: The channel the frame was received on | 3514 | * @channel: The channel the frame was received on |
3515 | * @scan_width: width of the control channel | ||
3408 | * @bssid: the BSSID of the BSS | 3516 | * @bssid: the BSSID of the BSS |
3409 | * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) | 3517 | * @tsf: the TSF sent by the peer in the beacon/probe response (or 0) |
3410 | * @capability: the capability field sent by the peer | 3518 | * @capability: the capability field sent by the peer |
@@ -3421,11 +3529,26 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
3421 | * Or %NULL on error. | 3529 | * Or %NULL on error. |
3422 | */ | 3530 | */ |
3423 | struct cfg80211_bss * __must_check | 3531 | struct cfg80211_bss * __must_check |
3532 | cfg80211_inform_bss_width(struct wiphy *wiphy, | ||
3533 | struct ieee80211_channel *channel, | ||
3534 | enum nl80211_bss_scan_width scan_width, | ||
3535 | const u8 *bssid, u64 tsf, u16 capability, | ||
3536 | u16 beacon_interval, const u8 *ie, size_t ielen, | ||
3537 | s32 signal, gfp_t gfp); | ||
3538 | |||
3539 | static inline struct cfg80211_bss * __must_check | ||
3424 | cfg80211_inform_bss(struct wiphy *wiphy, | 3540 | cfg80211_inform_bss(struct wiphy *wiphy, |
3425 | struct ieee80211_channel *channel, | 3541 | struct ieee80211_channel *channel, |
3426 | const u8 *bssid, u64 tsf, u16 capability, | 3542 | const u8 *bssid, u64 tsf, u16 capability, |
3427 | u16 beacon_interval, const u8 *ie, size_t ielen, | 3543 | u16 beacon_interval, const u8 *ie, size_t ielen, |
3428 | s32 signal, gfp_t gfp); | 3544 | s32 signal, gfp_t gfp) |
3545 | { | ||
3546 | return cfg80211_inform_bss_width(wiphy, channel, | ||
3547 | NL80211_BSS_CHAN_WIDTH_20, | ||
3548 | bssid, tsf, capability, | ||
3549 | beacon_interval, ie, ielen, signal, | ||
3550 | gfp); | ||
3551 | } | ||
3429 | 3552 | ||
3430 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | 3553 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, |
3431 | struct ieee80211_channel *channel, | 3554 | struct ieee80211_channel *channel, |
@@ -3471,6 +3594,19 @@ void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); | |||
3471 | */ | 3594 | */ |
3472 | void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); | 3595 | void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); |
3473 | 3596 | ||
3597 | static inline enum nl80211_bss_scan_width | ||
3598 | cfg80211_chandef_to_scan_width(const struct cfg80211_chan_def *chandef) | ||
3599 | { | ||
3600 | switch (chandef->width) { | ||
3601 | case NL80211_CHAN_WIDTH_5: | ||
3602 | return NL80211_BSS_CHAN_WIDTH_5; | ||
3603 | case NL80211_CHAN_WIDTH_10: | ||
3604 | return NL80211_BSS_CHAN_WIDTH_10; | ||
3605 | default: | ||
3606 | return NL80211_BSS_CHAN_WIDTH_20; | ||
3607 | } | ||
3608 | } | ||
3609 | |||
3474 | /** | 3610 | /** |
3475 | * cfg80211_rx_mlme_mgmt - notification of processed MLME management frame | 3611 | * cfg80211_rx_mlme_mgmt - notification of processed MLME management frame |
3476 | * @dev: network device | 3612 | * @dev: network device |
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index c6d07cb074bc..8b5b71433297 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h | |||
@@ -230,6 +230,10 @@ enum ieee80211_radiotap_type { | |||
230 | #define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ | 230 | #define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ |
231 | #define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ | 231 | #define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ |
232 | #define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ | 232 | #define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ |
233 | #define IEEE80211_CHAN_GSM 0x1000 /* GSM (900 MHz) */ | ||
234 | #define IEEE80211_CHAN_STURBO 0x2000 /* Static Turbo */ | ||
235 | #define IEEE80211_CHAN_HALF 0x4000 /* Half channel (10 MHz wide) */ | ||
236 | #define IEEE80211_CHAN_QUARTER 0x8000 /* Quarter channel (5 MHz wide) */ | ||
233 | 237 | ||
234 | /* For IEEE80211_RADIOTAP_FLAGS */ | 238 | /* For IEEE80211_RADIOTAP_FLAGS */ |
235 | #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received | 239 | #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5b7a3dadadde..3124036285eb 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -811,6 +811,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | |||
811 | * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC | 811 | * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC |
812 | * is stored in the @ampdu_delimiter_crc field) | 812 | * is stored in the @ampdu_delimiter_crc field) |
813 | * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 | 813 | * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3 |
814 | * @RX_FLAG_10MHZ: 10 MHz (half channel) was used | ||
815 | * @RX_FLAG_5MHZ: 5 MHz (quarter channel) was used | ||
814 | */ | 816 | */ |
815 | enum mac80211_rx_flags { | 817 | enum mac80211_rx_flags { |
816 | RX_FLAG_MMIC_ERROR = BIT(0), | 818 | RX_FLAG_MMIC_ERROR = BIT(0), |
@@ -839,6 +841,8 @@ enum mac80211_rx_flags { | |||
839 | RX_FLAG_80P80MHZ = BIT(24), | 841 | RX_FLAG_80P80MHZ = BIT(24), |
840 | RX_FLAG_160MHZ = BIT(25), | 842 | RX_FLAG_160MHZ = BIT(25), |
841 | RX_FLAG_STBC_MASK = BIT(26) | BIT(27), | 843 | RX_FLAG_STBC_MASK = BIT(26) | BIT(27), |
844 | RX_FLAG_10MHZ = BIT(28), | ||
845 | RX_FLAG_5MHZ = BIT(29), | ||
842 | }; | 846 | }; |
843 | 847 | ||
844 | #define RX_FLAG_STBC_SHIFT 26 | 848 | #define RX_FLAG_STBC_SHIFT 26 |
@@ -1004,11 +1008,11 @@ enum ieee80211_smps_mode { | |||
1004 | * @radar_enabled: whether radar detection is enabled | 1008 | * @radar_enabled: whether radar detection is enabled |
1005 | * | 1009 | * |
1006 | * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame | 1010 | * @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame |
1007 | * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, | 1011 | * (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11, |
1008 | * but actually means the number of transmissions not the number of retries | 1012 | * but actually means the number of transmissions not the number of retries |
1009 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" | 1013 | * @short_frame_max_tx_count: Maximum number of transmissions for a "short" |
1010 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the | 1014 | * frame, called "dot11ShortRetryLimit" in 802.11, but actually means the |
1011 | * number of transmissions not the number of retries | 1015 | * number of transmissions not the number of retries |
1012 | * | 1016 | * |
1013 | * @smps_mode: spatial multiplexing powersave mode; note that | 1017 | * @smps_mode: spatial multiplexing powersave mode; note that |
1014 | * %IEEE80211_SMPS_STATIC is used when the device is not | 1018 | * %IEEE80211_SMPS_STATIC is used when the device is not |
@@ -1092,7 +1096,7 @@ enum ieee80211_vif_flags { | |||
1092 | * be off when it is %NULL there can still be races and packets could be | 1096 | * be off when it is %NULL there can still be races and packets could be |
1093 | * processed after it switches back to %NULL. | 1097 | * processed after it switches back to %NULL. |
1094 | * @debugfs_dir: debugfs dentry, can be used by drivers to create own per | 1098 | * @debugfs_dir: debugfs dentry, can be used by drivers to create own per |
1095 | * interface debug files. Note that it will be NULL for the virtual | 1099 | * interface debug files. Note that it will be NULL for the virtual |
1096 | * monitor interface (if that is requested.) | 1100 | * monitor interface (if that is requested.) |
1097 | * @drv_priv: data area for driver use, will always be aligned to | 1101 | * @drv_priv: data area for driver use, will always be aligned to |
1098 | * sizeof(void *). | 1102 | * sizeof(void *). |
@@ -1425,10 +1429,10 @@ struct ieee80211_tx_control { | |||
1425 | * the stack. | 1429 | * the stack. |
1426 | * | 1430 | * |
1427 | * @IEEE80211_HW_CONNECTION_MONITOR: | 1431 | * @IEEE80211_HW_CONNECTION_MONITOR: |
1428 | * The hardware performs its own connection monitoring, including | 1432 | * The hardware performs its own connection monitoring, including |
1429 | * periodic keep-alives to the AP and probing the AP on beacon loss. | 1433 | * periodic keep-alives to the AP and probing the AP on beacon loss. |
1430 | * When this flag is set, signaling beacon-loss will cause an immediate | 1434 | * When this flag is set, signaling beacon-loss will cause an immediate |
1431 | * change to disassociated state. | 1435 | * change to disassociated state. |
1432 | * | 1436 | * |
1433 | * @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC: | 1437 | * @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC: |
1434 | * This device needs to get data from beacon before association (i.e. | 1438 | * This device needs to get data from beacon before association (i.e. |
@@ -1526,10 +1530,10 @@ enum ieee80211_hw_flags { | |||
1526 | * @channel_change_time: time (in microseconds) it takes to change channels. | 1530 | * @channel_change_time: time (in microseconds) it takes to change channels. |
1527 | * | 1531 | * |
1528 | * @max_signal: Maximum value for signal (rssi) in RX information, used | 1532 | * @max_signal: Maximum value for signal (rssi) in RX information, used |
1529 | * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB | 1533 | * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB |
1530 | * | 1534 | * |
1531 | * @max_listen_interval: max listen interval in units of beacon interval | 1535 | * @max_listen_interval: max listen interval in units of beacon interval |
1532 | * that HW supports | 1536 | * that HW supports |
1533 | * | 1537 | * |
1534 | * @queues: number of available hardware transmit queues for | 1538 | * @queues: number of available hardware transmit queues for |
1535 | * data packets. WMM/QoS requires at least four, these | 1539 | * data packets. WMM/QoS requires at least four, these |
@@ -2443,7 +2447,7 @@ enum ieee80211_roc_type { | |||
2443 | * The callback can sleep. | 2447 | * The callback can sleep. |
2444 | * | 2448 | * |
2445 | * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware. | 2449 | * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware. |
2446 | * Currently, this is only used for IBSS mode debugging. Is not a | 2450 | * Currently, this is only used for IBSS mode debugging. Is not a |
2447 | * required function. | 2451 | * required function. |
2448 | * The callback can sleep. | 2452 | * The callback can sleep. |
2449 | * | 2453 | * |
@@ -4204,8 +4208,10 @@ struct rate_control_ops { | |||
4204 | 4208 | ||
4205 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); | 4209 | void *(*alloc_sta)(void *priv, struct ieee80211_sta *sta, gfp_t gfp); |
4206 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, | 4210 | void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, |
4211 | struct cfg80211_chan_def *chandef, | ||
4207 | struct ieee80211_sta *sta, void *priv_sta); | 4212 | struct ieee80211_sta *sta, void *priv_sta); |
4208 | void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, | 4213 | void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, |
4214 | struct cfg80211_chan_def *chandef, | ||
4209 | struct ieee80211_sta *sta, void *priv_sta, | 4215 | struct ieee80211_sta *sta, void *priv_sta, |
4210 | u32 changed); | 4216 | u32 changed); |
4211 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, | 4217 | void (*free_sta)(void *priv, struct ieee80211_sta *sta, |
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 861e5eba3953..eb68735b3318 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h | |||
@@ -126,6 +126,31 @@ | |||
126 | */ | 126 | */ |
127 | 127 | ||
128 | /** | 128 | /** |
129 | * DOC: packet coalesce support | ||
130 | * | ||
131 | * In most cases, host that receives IPv4 and IPv6 multicast/broadcast | ||
132 | * packets does not do anything with these packets. Therefore the | ||
133 | * reception of these unwanted packets causes unnecessary processing | ||
134 | * and power consumption. | ||
135 | * | ||
136 | * Packet coalesce feature helps to reduce number of received interrupts | ||
137 | * to host by buffering these packets in firmware/hardware for some | ||
138 | * predefined time. Received interrupt will be generated when one of the | ||
139 | * following events occur. | ||
140 | * a) Expiration of hardware timer whose expiration time is set to maximum | ||
141 | * coalescing delay of matching coalesce rule. | ||
142 | * b) Coalescing buffer in hardware reaches it's limit. | ||
143 | * c) Packet doesn't match any of the configured coalesce rules. | ||
144 | * | ||
145 | * User needs to configure following parameters for creating a coalesce | ||
146 | * rule. | ||
147 | * a) Maximum coalescing delay | ||
148 | * b) List of packet patterns which needs to be matched | ||
149 | * c) Condition for coalescence. pattern 'match' or 'no match' | ||
150 | * Multiple such rules can be created. | ||
151 | */ | ||
152 | |||
153 | /** | ||
129 | * enum nl80211_commands - supported nl80211 commands | 154 | * enum nl80211_commands - supported nl80211 commands |
130 | * | 155 | * |
131 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors | 156 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors |
@@ -648,6 +673,9 @@ | |||
648 | * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can | 673 | * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can |
649 | * return back to normal. | 674 | * return back to normal. |
650 | * | 675 | * |
676 | * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules. | ||
677 | * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. | ||
678 | * | ||
651 | * @NL80211_CMD_MAX: highest used command number | 679 | * @NL80211_CMD_MAX: highest used command number |
652 | * @__NL80211_CMD_AFTER_LAST: internal use | 680 | * @__NL80211_CMD_AFTER_LAST: internal use |
653 | */ | 681 | */ |
@@ -810,6 +838,9 @@ enum nl80211_commands { | |||
810 | NL80211_CMD_CRIT_PROTOCOL_START, | 838 | NL80211_CMD_CRIT_PROTOCOL_START, |
811 | NL80211_CMD_CRIT_PROTOCOL_STOP, | 839 | NL80211_CMD_CRIT_PROTOCOL_STOP, |
812 | 840 | ||
841 | NL80211_CMD_GET_COALESCE, | ||
842 | NL80211_CMD_SET_COALESCE, | ||
843 | |||
813 | /* add new commands above here */ | 844 | /* add new commands above here */ |
814 | 845 | ||
815 | /* used to define NL80211_CMD_MAX below */ | 846 | /* used to define NL80211_CMD_MAX below */ |
@@ -1436,6 +1467,8 @@ enum nl80211_commands { | |||
1436 | * allowed to be used with the first @NL80211_CMD_SET_STATION command to | 1467 | * allowed to be used with the first @NL80211_CMD_SET_STATION command to |
1437 | * update a TDLS peer STA entry. | 1468 | * update a TDLS peer STA entry. |
1438 | * | 1469 | * |
1470 | * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information. | ||
1471 | * | ||
1439 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 1472 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
1440 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1473 | * @__NL80211_ATTR_AFTER_LAST: internal use |
1441 | */ | 1474 | */ |
@@ -1736,6 +1769,8 @@ enum nl80211_attrs { | |||
1736 | 1769 | ||
1737 | NL80211_ATTR_PEER_AID, | 1770 | NL80211_ATTR_PEER_AID, |
1738 | 1771 | ||
1772 | NL80211_ATTR_COALESCE_RULE, | ||
1773 | |||
1739 | /* add attributes here, update the policy in nl80211.c */ | 1774 | /* add attributes here, update the policy in nl80211.c */ |
1740 | 1775 | ||
1741 | __NL80211_ATTR_AFTER_LAST, | 1776 | __NL80211_ATTR_AFTER_LAST, |
@@ -2773,6 +2808,21 @@ enum nl80211_chan_width { | |||
2773 | }; | 2808 | }; |
2774 | 2809 | ||
2775 | /** | 2810 | /** |
2811 | * enum nl80211_bss_scan_width - control channel width for a BSS | ||
2812 | * | ||
2813 | * These values are used with the %NL80211_BSS_CHAN_WIDTH attribute. | ||
2814 | * | ||
2815 | * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible | ||
2816 | * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide | ||
2817 | * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide | ||
2818 | */ | ||
2819 | enum nl80211_bss_scan_width { | ||
2820 | NL80211_BSS_CHAN_WIDTH_20, | ||
2821 | NL80211_BSS_CHAN_WIDTH_10, | ||
2822 | NL80211_BSS_CHAN_WIDTH_5, | ||
2823 | }; | ||
2824 | |||
2825 | /** | ||
2776 | * enum nl80211_bss - netlink attributes for a BSS | 2826 | * enum nl80211_bss - netlink attributes for a BSS |
2777 | * | 2827 | * |
2778 | * @__NL80211_BSS_INVALID: invalid | 2828 | * @__NL80211_BSS_INVALID: invalid |
@@ -2796,6 +2846,8 @@ enum nl80211_chan_width { | |||
2796 | * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information | 2846 | * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information |
2797 | * elements from a Beacon frame (bin); not present if no Beacon frame has | 2847 | * elements from a Beacon frame (bin); not present if no Beacon frame has |
2798 | * yet been received | 2848 | * yet been received |
2849 | * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel | ||
2850 | * (u32, enum nl80211_bss_scan_width) | ||
2799 | * @__NL80211_BSS_AFTER_LAST: internal | 2851 | * @__NL80211_BSS_AFTER_LAST: internal |
2800 | * @NL80211_BSS_MAX: highest BSS attribute | 2852 | * @NL80211_BSS_MAX: highest BSS attribute |
2801 | */ | 2853 | */ |
@@ -2812,6 +2864,7 @@ enum nl80211_bss { | |||
2812 | NL80211_BSS_STATUS, | 2864 | NL80211_BSS_STATUS, |
2813 | NL80211_BSS_SEEN_MS_AGO, | 2865 | NL80211_BSS_SEEN_MS_AGO, |
2814 | NL80211_BSS_BEACON_IES, | 2866 | NL80211_BSS_BEACON_IES, |
2867 | NL80211_BSS_CHAN_WIDTH, | ||
2815 | 2868 | ||
2816 | /* keep last */ | 2869 | /* keep last */ |
2817 | __NL80211_BSS_AFTER_LAST, | 2870 | __NL80211_BSS_AFTER_LAST, |
@@ -3060,11 +3113,11 @@ enum nl80211_tx_power_setting { | |||
3060 | }; | 3113 | }; |
3061 | 3114 | ||
3062 | /** | 3115 | /** |
3063 | * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute | 3116 | * enum nl80211_packet_pattern_attr - packet pattern attribute |
3064 | * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute | 3117 | * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute |
3065 | * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has | 3118 | * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has |
3066 | * a zero bit are ignored | 3119 | * a zero bit are ignored |
3067 | * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have | 3120 | * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have |
3068 | * a bit for each byte in the pattern. The lowest-order bit corresponds | 3121 | * a bit for each byte in the pattern. The lowest-order bit corresponds |
3069 | * to the first byte of the pattern, but the bytes of the pattern are | 3122 | * to the first byte of the pattern, but the bytes of the pattern are |
3070 | * in a little-endian-like format, i.e. the 9th byte of the pattern | 3123 | * in a little-endian-like format, i.e. the 9th byte of the pattern |
@@ -3075,39 +3128,50 @@ enum nl80211_tx_power_setting { | |||
3075 | * Note that the pattern matching is done as though frames were not | 3128 | * Note that the pattern matching is done as though frames were not |
3076 | * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked | 3129 | * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked |
3077 | * first (including SNAP header unpacking) and then matched. | 3130 | * first (including SNAP header unpacking) and then matched. |
3078 | * @NL80211_WOWLAN_PKTPAT_OFFSET: packet offset, pattern is matched after | 3131 | * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after |
3079 | * these fixed number of bytes of received packet | 3132 | * these fixed number of bytes of received packet |
3080 | * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes | 3133 | * @NUM_NL80211_PKTPAT: number of attributes |
3081 | * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number | 3134 | * @MAX_NL80211_PKTPAT: max attribute number |
3082 | */ | 3135 | */ |
3083 | enum nl80211_wowlan_packet_pattern_attr { | 3136 | enum nl80211_packet_pattern_attr { |
3084 | __NL80211_WOWLAN_PKTPAT_INVALID, | 3137 | __NL80211_PKTPAT_INVALID, |
3085 | NL80211_WOWLAN_PKTPAT_MASK, | 3138 | NL80211_PKTPAT_MASK, |
3086 | NL80211_WOWLAN_PKTPAT_PATTERN, | 3139 | NL80211_PKTPAT_PATTERN, |
3087 | NL80211_WOWLAN_PKTPAT_OFFSET, | 3140 | NL80211_PKTPAT_OFFSET, |
3088 | 3141 | ||
3089 | NUM_NL80211_WOWLAN_PKTPAT, | 3142 | NUM_NL80211_PKTPAT, |
3090 | MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, | 3143 | MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1, |
3091 | }; | 3144 | }; |
3092 | 3145 | ||
3093 | /** | 3146 | /** |
3094 | * struct nl80211_wowlan_pattern_support - pattern support information | 3147 | * struct nl80211_pattern_support - packet pattern support information |
3095 | * @max_patterns: maximum number of patterns supported | 3148 | * @max_patterns: maximum number of patterns supported |
3096 | * @min_pattern_len: minimum length of each pattern | 3149 | * @min_pattern_len: minimum length of each pattern |
3097 | * @max_pattern_len: maximum length of each pattern | 3150 | * @max_pattern_len: maximum length of each pattern |
3098 | * @max_pkt_offset: maximum Rx packet offset | 3151 | * @max_pkt_offset: maximum Rx packet offset |
3099 | * | 3152 | * |
3100 | * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when | 3153 | * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when |
3101 | * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the | 3154 | * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in |
3102 | * capability information given by the kernel to userspace. | 3155 | * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of |
3156 | * %NL80211_ATTR_COALESCE_RULE in the capability information given | ||
3157 | * by the kernel to userspace. | ||
3103 | */ | 3158 | */ |
3104 | struct nl80211_wowlan_pattern_support { | 3159 | struct nl80211_pattern_support { |
3105 | __u32 max_patterns; | 3160 | __u32 max_patterns; |
3106 | __u32 min_pattern_len; | 3161 | __u32 min_pattern_len; |
3107 | __u32 max_pattern_len; | 3162 | __u32 max_pattern_len; |
3108 | __u32 max_pkt_offset; | 3163 | __u32 max_pkt_offset; |
3109 | } __attribute__((packed)); | 3164 | } __attribute__((packed)); |
3110 | 3165 | ||
3166 | /* only for backward compatibility */ | ||
3167 | #define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID | ||
3168 | #define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK | ||
3169 | #define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN | ||
3170 | #define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET | ||
3171 | #define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT | ||
3172 | #define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT | ||
3173 | #define nl80211_wowlan_pattern_support nl80211_pattern_support | ||
3174 | |||
3111 | /** | 3175 | /** |
3112 | * enum nl80211_wowlan_triggers - WoWLAN trigger definitions | 3176 | * enum nl80211_wowlan_triggers - WoWLAN trigger definitions |
3113 | * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes | 3177 | * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes |
@@ -3127,7 +3191,7 @@ struct nl80211_wowlan_pattern_support { | |||
3127 | * pattern matching is done after the packet is converted to the MSDU. | 3191 | * pattern matching is done after the packet is converted to the MSDU. |
3128 | * | 3192 | * |
3129 | * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute | 3193 | * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute |
3130 | * carrying a &struct nl80211_wowlan_pattern_support. | 3194 | * carrying a &struct nl80211_pattern_support. |
3131 | * | 3195 | * |
3132 | * When reporting wakeup. it is a u32 attribute containing the 0-based | 3196 | * When reporting wakeup. it is a u32 attribute containing the 0-based |
3133 | * index of the pattern that caused the wakeup, in the patterns passed | 3197 | * index of the pattern that caused the wakeup, in the patterns passed |
@@ -3284,7 +3348,7 @@ struct nl80211_wowlan_tcp_data_token_feature { | |||
3284 | * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a | 3348 | * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a |
3285 | * u32 attribute holding the maximum length | 3349 | * u32 attribute holding the maximum length |
3286 | * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for | 3350 | * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for |
3287 | * feature advertising. The mask works like @NL80211_WOWLAN_PKTPAT_MASK | 3351 | * feature advertising. The mask works like @NL80211_PKTPAT_MASK |
3288 | * but on the TCP payload only. | 3352 | * but on the TCP payload only. |
3289 | * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes | 3353 | * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes |
3290 | * @MAX_NL80211_WOWLAN_TCP: highest attribute number | 3354 | * @MAX_NL80211_WOWLAN_TCP: highest attribute number |
@@ -3309,6 +3373,55 @@ enum nl80211_wowlan_tcp_attrs { | |||
3309 | }; | 3373 | }; |
3310 | 3374 | ||
3311 | /** | 3375 | /** |
3376 | * struct nl80211_coalesce_rule_support - coalesce rule support information | ||
3377 | * @max_rules: maximum number of rules supported | ||
3378 | * @pat: packet pattern support information | ||
3379 | * @max_delay: maximum supported coalescing delay in msecs | ||
3380 | * | ||
3381 | * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the | ||
3382 | * capability information given by the kernel to userspace. | ||
3383 | */ | ||
3384 | struct nl80211_coalesce_rule_support { | ||
3385 | __u32 max_rules; | ||
3386 | struct nl80211_pattern_support pat; | ||
3387 | __u32 max_delay; | ||
3388 | } __attribute__((packed)); | ||
3389 | |||
3390 | /** | ||
3391 | * enum nl80211_attr_coalesce_rule - coalesce rule attribute | ||
3392 | * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute | ||
3393 | * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing | ||
3394 | * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence, | ||
3395 | * see &enum nl80211_coalesce_condition. | ||
3396 | * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched | ||
3397 | * after these fixed number of bytes of received packet | ||
3398 | * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes | ||
3399 | * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number | ||
3400 | */ | ||
3401 | enum nl80211_attr_coalesce_rule { | ||
3402 | __NL80211_COALESCE_RULE_INVALID, | ||
3403 | NL80211_ATTR_COALESCE_RULE_DELAY, | ||
3404 | NL80211_ATTR_COALESCE_RULE_CONDITION, | ||
3405 | NL80211_ATTR_COALESCE_RULE_PKT_PATTERN, | ||
3406 | |||
3407 | /* keep last */ | ||
3408 | NUM_NL80211_ATTR_COALESCE_RULE, | ||
3409 | NL80211_ATTR_COALESCE_RULE_MAX = NUM_NL80211_ATTR_COALESCE_RULE - 1 | ||
3410 | }; | ||
3411 | |||
3412 | /** | ||
3413 | * enum nl80211_coalesce_condition - coalesce rule conditions | ||
3414 | * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns | ||
3415 | * in a rule are matched. | ||
3416 | * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns | ||
3417 | * in a rule are not matched. | ||
3418 | */ | ||
3419 | enum nl80211_coalesce_condition { | ||
3420 | NL80211_COALESCE_CONDITION_MATCH, | ||
3421 | NL80211_COALESCE_CONDITION_NO_MATCH | ||
3422 | }; | ||
3423 | |||
3424 | /** | ||
3312 | * enum nl80211_iface_limit_attrs - limit attributes | 3425 | * enum nl80211_iface_limit_attrs - limit attributes |
3313 | * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) | 3426 | * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) |
3314 | * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that | 3427 | * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 43dd7525bfcb..973594b229f4 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -395,9 +395,13 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
395 | rinfo->nss = ieee80211_rate_get_vht_nss(rate); | 395 | rinfo->nss = ieee80211_rate_get_vht_nss(rate); |
396 | } else { | 396 | } else { |
397 | struct ieee80211_supported_band *sband; | 397 | struct ieee80211_supported_band *sband; |
398 | int shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
399 | u16 brate; | ||
400 | |||
398 | sband = sta->local->hw.wiphy->bands[ | 401 | sband = sta->local->hw.wiphy->bands[ |
399 | ieee80211_get_sdata_band(sta->sdata)]; | 402 | ieee80211_get_sdata_band(sta->sdata)]; |
400 | rinfo->legacy = sband->bitrates[rate->idx].bitrate; | 403 | brate = sband->bitrates[rate->idx].bitrate; |
404 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | ||
401 | } | 405 | } |
402 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 406 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) |
403 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 407 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
@@ -422,11 +426,13 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
422 | rinfo->mcs = sta->last_rx_rate_idx; | 426 | rinfo->mcs = sta->last_rx_rate_idx; |
423 | } else { | 427 | } else { |
424 | struct ieee80211_supported_band *sband; | 428 | struct ieee80211_supported_band *sband; |
429 | int shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
430 | u16 brate; | ||
425 | 431 | ||
426 | sband = sta->local->hw.wiphy->bands[ | 432 | sband = sta->local->hw.wiphy->bands[ |
427 | ieee80211_get_sdata_band(sta->sdata)]; | 433 | ieee80211_get_sdata_band(sta->sdata)]; |
428 | rinfo->legacy = | 434 | brate = sband->bitrates[sta->last_rx_rate_idx].bitrate; |
429 | sband->bitrates[sta->last_rx_rate_idx].bitrate; | 435 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); |
430 | } | 436 | } |
431 | 437 | ||
432 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | 438 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) |
@@ -1192,8 +1198,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1192 | struct station_parameters *params) | 1198 | struct station_parameters *params) |
1193 | { | 1199 | { |
1194 | int ret = 0; | 1200 | int ret = 0; |
1195 | u32 rates; | ||
1196 | int i, j; | ||
1197 | struct ieee80211_supported_band *sband; | 1201 | struct ieee80211_supported_band *sband; |
1198 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1202 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1199 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 1203 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
@@ -1286,16 +1290,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1286 | sta->listen_interval = params->listen_interval; | 1290 | sta->listen_interval = params->listen_interval; |
1287 | 1291 | ||
1288 | if (params->supported_rates) { | 1292 | if (params->supported_rates) { |
1289 | rates = 0; | 1293 | ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef, |
1290 | 1294 | sband, params->supported_rates, | |
1291 | for (i = 0; i < params->supported_rates_len; i++) { | 1295 | params->supported_rates_len, |
1292 | int rate = (params->supported_rates[i] & 0x7f) * 5; | 1296 | &sta->sta.supp_rates[band]); |
1293 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1294 | if (sband->bitrates[j].bitrate == rate) | ||
1295 | rates |= BIT(j); | ||
1296 | } | ||
1297 | } | ||
1298 | sta->sta.supp_rates[band] = rates; | ||
1299 | } | 1297 | } |
1300 | 1298 | ||
1301 | if (params->ht_capa) | 1299 | if (params->ht_capa) |
@@ -1958,18 +1956,11 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1958 | } | 1956 | } |
1959 | 1957 | ||
1960 | if (params->basic_rates) { | 1958 | if (params->basic_rates) { |
1961 | int i, j; | 1959 | ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef, |
1962 | u32 rates = 0; | 1960 | wiphy->bands[band], |
1963 | struct ieee80211_supported_band *sband = wiphy->bands[band]; | 1961 | params->basic_rates, |
1964 | 1962 | params->basic_rates_len, | |
1965 | for (i = 0; i < params->basic_rates_len; i++) { | 1963 | &sdata->vif.bss_conf.basic_rates); |
1966 | int rate = (params->basic_rates[i] & 0x7f) * 5; | ||
1967 | for (j = 0; j < sband->n_bitrates; j++) { | ||
1968 | if (sband->bitrates[j].bitrate == rate) | ||
1969 | rates |= BIT(j); | ||
1970 | } | ||
1971 | } | ||
1972 | sdata->vif.bss_conf.basic_rates = rates; | ||
1973 | changed |= BSS_CHANGED_BASIC_RATES; | 1964 | changed |= BSS_CHANGED_BASIC_RATES; |
1974 | } | 1965 | } |
1975 | 1966 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index f83534f6a2ee..529bf58bc145 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -19,13 +19,14 @@ | |||
19 | #include "ieee80211_i.h" | 19 | #include "ieee80211_i.h" |
20 | #include "rate.h" | 20 | #include "rate.h" |
21 | 21 | ||
22 | static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, | 22 | static void __check_htcap_disable(struct ieee80211_ht_cap *ht_capa, |
23 | struct ieee80211_ht_cap *ht_capa_mask, | ||
23 | struct ieee80211_sta_ht_cap *ht_cap, | 24 | struct ieee80211_sta_ht_cap *ht_cap, |
24 | u16 flag) | 25 | u16 flag) |
25 | { | 26 | { |
26 | __le16 le_flag = cpu_to_le16(flag); | 27 | __le16 le_flag = cpu_to_le16(flag); |
27 | if (sdata->u.mgd.ht_capa_mask.cap_info & le_flag) { | 28 | if (ht_capa_mask->cap_info & le_flag) { |
28 | if (!(sdata->u.mgd.ht_capa.cap_info & le_flag)) | 29 | if (!(ht_capa->cap_info & le_flag)) |
29 | ht_cap->cap &= ~flag; | 30 | ht_cap->cap &= ~flag; |
30 | } | 31 | } |
31 | } | 32 | } |
@@ -33,13 +34,30 @@ static void __check_htcap_disable(struct ieee80211_sub_if_data *sdata, | |||
33 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | 34 | void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, |
34 | struct ieee80211_sta_ht_cap *ht_cap) | 35 | struct ieee80211_sta_ht_cap *ht_cap) |
35 | { | 36 | { |
36 | u8 *scaps = (u8 *)(&sdata->u.mgd.ht_capa.mcs.rx_mask); | 37 | struct ieee80211_ht_cap *ht_capa, *ht_capa_mask; |
37 | u8 *smask = (u8 *)(&sdata->u.mgd.ht_capa_mask.mcs.rx_mask); | 38 | u8 *scaps, *smask; |
38 | int i; | 39 | int i; |
39 | 40 | ||
40 | if (!ht_cap->ht_supported) | 41 | if (!ht_cap->ht_supported) |
41 | return; | 42 | return; |
42 | 43 | ||
44 | switch (sdata->vif.type) { | ||
45 | case NL80211_IFTYPE_STATION: | ||
46 | ht_capa = &sdata->u.mgd.ht_capa; | ||
47 | ht_capa_mask = &sdata->u.mgd.ht_capa_mask; | ||
48 | break; | ||
49 | case NL80211_IFTYPE_ADHOC: | ||
50 | ht_capa = &sdata->u.ibss.ht_capa; | ||
51 | ht_capa_mask = &sdata->u.ibss.ht_capa_mask; | ||
52 | break; | ||
53 | default: | ||
54 | WARN_ON_ONCE(1); | ||
55 | return; | ||
56 | } | ||
57 | |||
58 | scaps = (u8 *)(&ht_capa->mcs.rx_mask); | ||
59 | smask = (u8 *)(&ht_capa_mask->mcs.rx_mask); | ||
60 | |||
43 | /* NOTE: If you add more over-rides here, update register_hw | 61 | /* NOTE: If you add more over-rides here, update register_hw |
44 | * ht_capa_mod_msk logic in main.c as well. | 62 | * ht_capa_mod_msk logic in main.c as well. |
45 | * And, if this method can ever change ht_cap.ht_supported, fix | 63 | * And, if this method can ever change ht_cap.ht_supported, fix |
@@ -55,28 +73,32 @@ void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata, | |||
55 | } | 73 | } |
56 | 74 | ||
57 | /* Force removal of HT-40 capabilities? */ | 75 | /* Force removal of HT-40 capabilities? */ |
58 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SUP_WIDTH_20_40); | 76 | __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap, |
59 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_40); | 77 | IEEE80211_HT_CAP_SUP_WIDTH_20_40); |
78 | __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap, | ||
79 | IEEE80211_HT_CAP_SGI_40); | ||
60 | 80 | ||
61 | /* Allow user to disable SGI-20 (SGI-40 is handled above) */ | 81 | /* Allow user to disable SGI-20 (SGI-40 is handled above) */ |
62 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_SGI_20); | 82 | __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap, |
83 | IEEE80211_HT_CAP_SGI_20); | ||
63 | 84 | ||
64 | /* Allow user to disable the max-AMSDU bit. */ | 85 | /* Allow user to disable the max-AMSDU bit. */ |
65 | __check_htcap_disable(sdata, ht_cap, IEEE80211_HT_CAP_MAX_AMSDU); | 86 | __check_htcap_disable(ht_capa, ht_capa_mask, ht_cap, |
87 | IEEE80211_HT_CAP_MAX_AMSDU); | ||
66 | 88 | ||
67 | /* Allow user to decrease AMPDU factor */ | 89 | /* Allow user to decrease AMPDU factor */ |
68 | if (sdata->u.mgd.ht_capa_mask.ampdu_params_info & | 90 | if (ht_capa_mask->ampdu_params_info & |
69 | IEEE80211_HT_AMPDU_PARM_FACTOR) { | 91 | IEEE80211_HT_AMPDU_PARM_FACTOR) { |
70 | u8 n = sdata->u.mgd.ht_capa.ampdu_params_info | 92 | u8 n = ht_capa->ampdu_params_info & |
71 | & IEEE80211_HT_AMPDU_PARM_FACTOR; | 93 | IEEE80211_HT_AMPDU_PARM_FACTOR; |
72 | if (n < ht_cap->ampdu_factor) | 94 | if (n < ht_cap->ampdu_factor) |
73 | ht_cap->ampdu_factor = n; | 95 | ht_cap->ampdu_factor = n; |
74 | } | 96 | } |
75 | 97 | ||
76 | /* Allow the user to increase AMPDU density. */ | 98 | /* Allow the user to increase AMPDU density. */ |
77 | if (sdata->u.mgd.ht_capa_mask.ampdu_params_info & | 99 | if (ht_capa_mask->ampdu_params_info & |
78 | IEEE80211_HT_AMPDU_PARM_DENSITY) { | 100 | IEEE80211_HT_AMPDU_PARM_DENSITY) { |
79 | u8 n = (sdata->u.mgd.ht_capa.ampdu_params_info & | 101 | u8 n = (ht_capa->ampdu_params_info & |
80 | IEEE80211_HT_AMPDU_PARM_DENSITY) | 102 | IEEE80211_HT_AMPDU_PARM_DENSITY) |
81 | >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; | 103 | >> IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT; |
82 | if (n > ht_cap->ampdu_density) | 104 | if (n > ht_cap->ampdu_density) |
@@ -112,7 +134,8 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
112 | * we advertised a restricted capability set to. Override | 134 | * we advertised a restricted capability set to. Override |
113 | * our own capabilities and then use those below. | 135 | * our own capabilities and then use those below. |
114 | */ | 136 | */ |
115 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 137 | if ((sdata->vif.type == NL80211_IFTYPE_STATION || |
138 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | ||
116 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | 139 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) |
117 | ieee80211_apply_htcap_overrides(sdata, &own_cap); | 140 | ieee80211_apply_htcap_overrides(sdata, &own_cap); |
118 | 141 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ea7b9c2c7e66..5e6836c3aa4c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -43,16 +43,18 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
43 | { | 43 | { |
44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
45 | struct ieee80211_local *local = sdata->local; | 45 | struct ieee80211_local *local = sdata->local; |
46 | int rates, i; | 46 | int rates_n = 0, i, ri; |
47 | struct ieee80211_mgmt *mgmt; | 47 | struct ieee80211_mgmt *mgmt; |
48 | u8 *pos; | 48 | u8 *pos; |
49 | struct ieee80211_supported_band *sband; | 49 | struct ieee80211_supported_band *sband; |
50 | struct cfg80211_bss *bss; | 50 | struct cfg80211_bss *bss; |
51 | u32 bss_change; | 51 | u32 bss_change, rate_flags, rates = 0, rates_added = 0; |
52 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | ||
53 | struct cfg80211_chan_def chandef; | 52 | struct cfg80211_chan_def chandef; |
53 | enum nl80211_bss_scan_width scan_width; | ||
54 | bool have_higher_than_11mbit = false; | ||
54 | struct beacon_data *presp; | 55 | struct beacon_data *presp; |
55 | int frame_len; | 56 | int frame_len; |
57 | int shift; | ||
56 | 58 | ||
57 | sdata_assert_lock(sdata); | 59 | sdata_assert_lock(sdata); |
58 | 60 | ||
@@ -83,6 +85,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
83 | 85 | ||
84 | chandef = ifibss->chandef; | 86 | chandef = ifibss->chandef; |
85 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | 87 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { |
88 | if (chandef.width == NL80211_CHAN_WIDTH_5 || | ||
89 | chandef.width == NL80211_CHAN_WIDTH_10 || | ||
90 | chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | ||
91 | chandef.width == NL80211_CHAN_WIDTH_20) { | ||
92 | sdata_info(sdata, | ||
93 | "Failed to join IBSS, beacons forbidden\n"); | ||
94 | return; | ||
95 | } | ||
86 | chandef.width = NL80211_CHAN_WIDTH_20; | 96 | chandef.width = NL80211_CHAN_WIDTH_20; |
87 | chandef.center_freq1 = chan->center_freq; | 97 | chandef.center_freq1 = chan->center_freq; |
88 | } | 98 | } |
@@ -99,6 +109,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
99 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 109 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
100 | 110 | ||
101 | sband = local->hw.wiphy->bands[chan->band]; | 111 | sband = local->hw.wiphy->bands[chan->band]; |
112 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
102 | 113 | ||
103 | /* Build IBSS probe response */ | 114 | /* Build IBSS probe response */ |
104 | frame_len = sizeof(struct ieee80211_hdr_3addr) + | 115 | frame_len = sizeof(struct ieee80211_hdr_3addr) + |
@@ -134,15 +145,33 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
134 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); | 145 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
135 | pos += ifibss->ssid_len; | 146 | pos += ifibss->ssid_len; |
136 | 147 | ||
137 | rates = min_t(int, 8, sband->n_bitrates); | 148 | rate_flags = ieee80211_chandef_rate_flags(&chandef); |
149 | for (i = 0; i < sband->n_bitrates; i++) { | ||
150 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
151 | continue; | ||
152 | if (sband->bitrates[i].bitrate > 110) | ||
153 | have_higher_than_11mbit = true; | ||
154 | |||
155 | rates |= BIT(i); | ||
156 | rates_n++; | ||
157 | } | ||
158 | |||
138 | *pos++ = WLAN_EID_SUPP_RATES; | 159 | *pos++ = WLAN_EID_SUPP_RATES; |
139 | *pos++ = rates; | 160 | *pos++ = min_t(int, 8, rates_n); |
140 | for (i = 0; i < rates; i++) { | 161 | for (ri = 0; ri < sband->n_bitrates; ri++) { |
141 | int rate = sband->bitrates[i].bitrate; | 162 | int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate, |
163 | 5 * (1 << shift)); | ||
142 | u8 basic = 0; | 164 | u8 basic = 0; |
143 | if (basic_rates & BIT(i)) | 165 | if (!(rates & BIT(ri))) |
166 | continue; | ||
167 | |||
168 | if (basic_rates & BIT(ri)) | ||
144 | basic = 0x80; | 169 | basic = 0x80; |
145 | *pos++ = basic | (u8) (rate / 5); | 170 | *pos++ = basic | (u8) rate; |
171 | if (++rates_added == 8) { | ||
172 | ri++; /* continue at next rate for EXT_SUPP_RATES */ | ||
173 | break; | ||
174 | } | ||
146 | } | 175 | } |
147 | 176 | ||
148 | if (sband->band == IEEE80211_BAND_2GHZ) { | 177 | if (sband->band == IEEE80211_BAND_2GHZ) { |
@@ -157,15 +186,20 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
157 | *pos++ = 0; | 186 | *pos++ = 0; |
158 | *pos++ = 0; | 187 | *pos++ = 0; |
159 | 188 | ||
160 | if (sband->n_bitrates > 8) { | 189 | /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */ |
190 | if (rates_n > 8) { | ||
161 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 191 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
162 | *pos++ = sband->n_bitrates - 8; | 192 | *pos++ = rates_n - 8; |
163 | for (i = 8; i < sband->n_bitrates; i++) { | 193 | for (; ri < sband->n_bitrates; ri++) { |
164 | int rate = sband->bitrates[i].bitrate; | 194 | int rate = DIV_ROUND_UP(sband->bitrates[ri].bitrate, |
195 | 5 * (1 << shift)); | ||
165 | u8 basic = 0; | 196 | u8 basic = 0; |
166 | if (basic_rates & BIT(i)) | 197 | if (!(rates & BIT(ri))) |
198 | continue; | ||
199 | |||
200 | if (basic_rates & BIT(ri)) | ||
167 | basic = 0x80; | 201 | basic = 0x80; |
168 | *pos++ = basic | (u8) (rate / 5); | 202 | *pos++ = basic | (u8) rate; |
169 | } | 203 | } |
170 | } | 204 | } |
171 | 205 | ||
@@ -179,8 +213,12 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
179 | chandef.width != NL80211_CHAN_WIDTH_5 && | 213 | chandef.width != NL80211_CHAN_WIDTH_5 && |
180 | chandef.width != NL80211_CHAN_WIDTH_10 && | 214 | chandef.width != NL80211_CHAN_WIDTH_10 && |
181 | sband->ht_cap.ht_supported) { | 215 | sband->ht_cap.ht_supported) { |
182 | pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap, | 216 | struct ieee80211_sta_ht_cap ht_cap; |
183 | sband->ht_cap.cap); | 217 | |
218 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
219 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
220 | |||
221 | pos = ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); | ||
184 | /* | 222 | /* |
185 | * Note: According to 802.11n-2009 9.13.3.1, HT Protection | 223 | * Note: According to 802.11n-2009 9.13.3.1, HT Protection |
186 | * field and RIFS Mode are reserved in IBSS mode, therefore | 224 | * field and RIFS Mode are reserved in IBSS mode, therefore |
@@ -236,18 +274,26 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
236 | sdata->vif.bss_conf.use_short_slot = chan->band == IEEE80211_BAND_5GHZ; | 274 | sdata->vif.bss_conf.use_short_slot = chan->band == IEEE80211_BAND_5GHZ; |
237 | bss_change |= BSS_CHANGED_ERP_SLOT; | 275 | bss_change |= BSS_CHANGED_ERP_SLOT; |
238 | 276 | ||
277 | /* cf. IEEE 802.11 9.2.12 */ | ||
278 | if (chan->band == IEEE80211_BAND_2GHZ && have_higher_than_11mbit) | ||
279 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
280 | else | ||
281 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
282 | |||
239 | sdata->vif.bss_conf.ibss_joined = true; | 283 | sdata->vif.bss_conf.ibss_joined = true; |
240 | sdata->vif.bss_conf.ibss_creator = creator; | 284 | sdata->vif.bss_conf.ibss_creator = creator; |
241 | ieee80211_bss_info_change_notify(sdata, bss_change); | 285 | ieee80211_bss_info_change_notify(sdata, bss_change); |
242 | 286 | ||
243 | ieee80211_sta_def_wmm_params(sdata, sband->n_bitrates, supp_rates); | 287 | ieee80211_set_wmm_default(sdata, true); |
244 | 288 | ||
245 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; | 289 | ifibss->state = IEEE80211_IBSS_MLME_JOINED; |
246 | mod_timer(&ifibss->timer, | 290 | mod_timer(&ifibss->timer, |
247 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 291 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
248 | 292 | ||
249 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, | 293 | scan_width = cfg80211_chandef_to_scan_width(&chandef); |
250 | mgmt, presp->head_len, 0, GFP_KERNEL); | 294 | bss = cfg80211_inform_bss_width_frame(local->hw.wiphy, chan, |
295 | scan_width, mgmt, | ||
296 | presp->head_len, 0, GFP_KERNEL); | ||
251 | cfg80211_put_bss(local->hw.wiphy, bss); | 297 | cfg80211_put_bss(local->hw.wiphy, bss); |
252 | netif_carrier_on(sdata->dev); | 298 | netif_carrier_on(sdata->dev); |
253 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 299 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); |
@@ -264,6 +310,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
264 | u16 beacon_int = cbss->beacon_interval; | 310 | u16 beacon_int = cbss->beacon_interval; |
265 | const struct cfg80211_bss_ies *ies; | 311 | const struct cfg80211_bss_ies *ies; |
266 | u64 tsf; | 312 | u64 tsf; |
313 | u32 rate_flags; | ||
314 | int shift; | ||
267 | 315 | ||
268 | sdata_assert_lock(sdata); | 316 | sdata_assert_lock(sdata); |
269 | 317 | ||
@@ -271,15 +319,24 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
271 | beacon_int = 10; | 319 | beacon_int = 10; |
272 | 320 | ||
273 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; | 321 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; |
322 | rate_flags = ieee80211_chandef_rate_flags(&sdata->u.ibss.chandef); | ||
323 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
274 | 324 | ||
275 | basic_rates = 0; | 325 | basic_rates = 0; |
276 | 326 | ||
277 | for (i = 0; i < bss->supp_rates_len; i++) { | 327 | for (i = 0; i < bss->supp_rates_len; i++) { |
278 | int rate = (bss->supp_rates[i] & 0x7f) * 5; | 328 | int rate = bss->supp_rates[i] & 0x7f; |
279 | bool is_basic = !!(bss->supp_rates[i] & 0x80); | 329 | bool is_basic = !!(bss->supp_rates[i] & 0x80); |
280 | 330 | ||
281 | for (j = 0; j < sband->n_bitrates; j++) { | 331 | for (j = 0; j < sband->n_bitrates; j++) { |
282 | if (sband->bitrates[j].bitrate == rate) { | 332 | int brate; |
333 | if ((rate_flags & sband->bitrates[j].flags) | ||
334 | != rate_flags) | ||
335 | continue; | ||
336 | |||
337 | brate = DIV_ROUND_UP(sband->bitrates[j].bitrate, | ||
338 | 5 * (1 << shift)); | ||
339 | if (brate == rate) { | ||
283 | if (is_basic) | 340 | if (is_basic) |
284 | basic_rates |= BIT(j); | 341 | basic_rates |= BIT(j); |
285 | break; | 342 | break; |
@@ -335,6 +392,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, | |||
335 | struct sta_info *sta; | 392 | struct sta_info *sta; |
336 | struct ieee80211_chanctx_conf *chanctx_conf; | 393 | struct ieee80211_chanctx_conf *chanctx_conf; |
337 | struct ieee80211_supported_band *sband; | 394 | struct ieee80211_supported_band *sband; |
395 | enum nl80211_bss_scan_width scan_width; | ||
338 | int band; | 396 | int band; |
339 | 397 | ||
340 | /* | 398 | /* |
@@ -363,6 +421,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, | |||
363 | if (WARN_ON_ONCE(!chanctx_conf)) | 421 | if (WARN_ON_ONCE(!chanctx_conf)) |
364 | return NULL; | 422 | return NULL; |
365 | band = chanctx_conf->def.chan->band; | 423 | band = chanctx_conf->def.chan->band; |
424 | scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def); | ||
366 | rcu_read_unlock(); | 425 | rcu_read_unlock(); |
367 | 426 | ||
368 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); | 427 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); |
@@ -376,7 +435,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, const u8 *bssid, | |||
376 | /* make sure mandatory rates are always added */ | 435 | /* make sure mandatory rates are always added */ |
377 | sband = local->hw.wiphy->bands[band]; | 436 | sband = local->hw.wiphy->bands[band]; |
378 | sta->sta.supp_rates[band] = supp_rates | | 437 | sta->sta.supp_rates[band] = supp_rates | |
379 | ieee80211_mandatory_rates(sband); | 438 | ieee80211_mandatory_rates(sband, scan_width); |
380 | 439 | ||
381 | return ieee80211_ibss_finish_sta(sta); | 440 | return ieee80211_ibss_finish_sta(sta); |
382 | } | 441 | } |
@@ -440,6 +499,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
440 | u64 beacon_timestamp, rx_timestamp; | 499 | u64 beacon_timestamp, rx_timestamp; |
441 | u32 supp_rates = 0; | 500 | u32 supp_rates = 0; |
442 | enum ieee80211_band band = rx_status->band; | 501 | enum ieee80211_band band = rx_status->band; |
502 | enum nl80211_bss_scan_width scan_width; | ||
443 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 503 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
444 | bool rates_updated = false; | 504 | bool rates_updated = false; |
445 | 505 | ||
@@ -461,16 +521,22 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
461 | sta = sta_info_get(sdata, mgmt->sa); | 521 | sta = sta_info_get(sdata, mgmt->sa); |
462 | 522 | ||
463 | if (elems->supp_rates) { | 523 | if (elems->supp_rates) { |
464 | supp_rates = ieee80211_sta_get_rates(local, elems, | 524 | supp_rates = ieee80211_sta_get_rates(sdata, elems, |
465 | band, NULL); | 525 | band, NULL); |
466 | if (sta) { | 526 | if (sta) { |
467 | u32 prev_rates; | 527 | u32 prev_rates; |
468 | 528 | ||
469 | prev_rates = sta->sta.supp_rates[band]; | 529 | prev_rates = sta->sta.supp_rates[band]; |
470 | /* make sure mandatory rates are always added */ | 530 | /* make sure mandatory rates are always added */ |
471 | sta->sta.supp_rates[band] = supp_rates | | 531 | scan_width = NL80211_BSS_CHAN_WIDTH_20; |
472 | ieee80211_mandatory_rates(sband); | 532 | if (rx_status->flag & RX_FLAG_5MHZ) |
533 | scan_width = NL80211_BSS_CHAN_WIDTH_5; | ||
534 | if (rx_status->flag & RX_FLAG_10MHZ) | ||
535 | scan_width = NL80211_BSS_CHAN_WIDTH_10; | ||
473 | 536 | ||
537 | sta->sta.supp_rates[band] = supp_rates | | ||
538 | ieee80211_mandatory_rates(sband, | ||
539 | scan_width); | ||
474 | if (sta->sta.supp_rates[band] != prev_rates) { | 540 | if (sta->sta.supp_rates[band] != prev_rates) { |
475 | ibss_dbg(sdata, | 541 | ibss_dbg(sdata, |
476 | "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n", | 542 | "updated supp_rates set for %pM based on beacon/probe_resp (0x%x -> 0x%x)\n", |
@@ -585,7 +651,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
585 | "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", | 651 | "beacon TSF higher than local TSF - IBSS merge with BSSID %pM\n", |
586 | mgmt->bssid); | 652 | mgmt->bssid); |
587 | ieee80211_sta_join_ibss(sdata, bss); | 653 | ieee80211_sta_join_ibss(sdata, bss); |
588 | supp_rates = ieee80211_sta_get_rates(local, elems, band, NULL); | 654 | supp_rates = ieee80211_sta_get_rates(sdata, elems, band, NULL); |
589 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, | 655 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, |
590 | supp_rates); | 656 | supp_rates); |
591 | rcu_read_unlock(); | 657 | rcu_read_unlock(); |
@@ -604,6 +670,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
604 | struct sta_info *sta; | 670 | struct sta_info *sta; |
605 | struct ieee80211_chanctx_conf *chanctx_conf; | 671 | struct ieee80211_chanctx_conf *chanctx_conf; |
606 | struct ieee80211_supported_band *sband; | 672 | struct ieee80211_supported_band *sband; |
673 | enum nl80211_bss_scan_width scan_width; | ||
607 | int band; | 674 | int band; |
608 | 675 | ||
609 | /* | 676 | /* |
@@ -629,6 +696,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
629 | return; | 696 | return; |
630 | } | 697 | } |
631 | band = chanctx_conf->def.chan->band; | 698 | band = chanctx_conf->def.chan->band; |
699 | scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def); | ||
632 | rcu_read_unlock(); | 700 | rcu_read_unlock(); |
633 | 701 | ||
634 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 702 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
@@ -640,7 +708,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
640 | /* make sure mandatory rates are always added */ | 708 | /* make sure mandatory rates are always added */ |
641 | sband = local->hw.wiphy->bands[band]; | 709 | sband = local->hw.wiphy->bands[band]; |
642 | sta->sta.supp_rates[band] = supp_rates | | 710 | sta->sta.supp_rates[band] = supp_rates | |
643 | ieee80211_mandatory_rates(sband); | 711 | ieee80211_mandatory_rates(sband, scan_width); |
644 | 712 | ||
645 | spin_lock(&ifibss->incomplete_lock); | 713 | spin_lock(&ifibss->incomplete_lock); |
646 | list_add(&sta->list, &ifibss->incomplete_stations); | 714 | list_add(&sta->list, &ifibss->incomplete_stations); |
@@ -679,6 +747,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | |||
679 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | 747 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) |
680 | { | 748 | { |
681 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 749 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
750 | enum nl80211_bss_scan_width scan_width; | ||
682 | 751 | ||
683 | sdata_assert_lock(sdata); | 752 | sdata_assert_lock(sdata); |
684 | 753 | ||
@@ -700,8 +769,9 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
700 | sdata_info(sdata, | 769 | sdata_info(sdata, |
701 | "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); | 770 | "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); |
702 | 771 | ||
772 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); | ||
703 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, | 773 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, |
704 | NULL); | 774 | NULL, scan_width); |
705 | } | 775 | } |
706 | 776 | ||
707 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | 777 | static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) |
@@ -751,6 +821,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
751 | struct cfg80211_bss *cbss; | 821 | struct cfg80211_bss *cbss; |
752 | struct ieee80211_channel *chan = NULL; | 822 | struct ieee80211_channel *chan = NULL; |
753 | const u8 *bssid = NULL; | 823 | const u8 *bssid = NULL; |
824 | enum nl80211_bss_scan_width scan_width; | ||
754 | int active_ibss; | 825 | int active_ibss; |
755 | u16 capability; | 826 | u16 capability; |
756 | 827 | ||
@@ -799,8 +870,10 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
799 | IEEE80211_SCAN_INTERVAL)) { | 870 | IEEE80211_SCAN_INTERVAL)) { |
800 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); | 871 | sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); |
801 | 872 | ||
873 | scan_width = cfg80211_chandef_to_scan_width(&ifibss->chandef); | ||
802 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, | 874 | ieee80211_request_ibss_scan(sdata, ifibss->ssid, |
803 | ifibss->ssid_len, chan); | 875 | ifibss->ssid_len, chan, |
876 | scan_width); | ||
804 | } else { | 877 | } else { |
805 | int interval = IEEE80211_SCAN_INTERVAL; | 878 | int interval = IEEE80211_SCAN_INTERVAL; |
806 | 879 | ||
@@ -1020,6 +1093,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1020 | struct cfg80211_ibss_params *params) | 1093 | struct cfg80211_ibss_params *params) |
1021 | { | 1094 | { |
1022 | u32 changed = 0; | 1095 | u32 changed = 0; |
1096 | u32 rate_flags; | ||
1097 | struct ieee80211_supported_band *sband; | ||
1098 | int i; | ||
1023 | 1099 | ||
1024 | if (params->bssid) { | 1100 | if (params->bssid) { |
1025 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); | 1101 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); |
@@ -1030,6 +1106,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1030 | sdata->u.ibss.privacy = params->privacy; | 1106 | sdata->u.ibss.privacy = params->privacy; |
1031 | sdata->u.ibss.control_port = params->control_port; | 1107 | sdata->u.ibss.control_port = params->control_port; |
1032 | sdata->u.ibss.basic_rates = params->basic_rates; | 1108 | sdata->u.ibss.basic_rates = params->basic_rates; |
1109 | |||
1110 | /* fix basic_rates if channel does not support these rates */ | ||
1111 | rate_flags = ieee80211_chandef_rate_flags(¶ms->chandef); | ||
1112 | sband = sdata->local->hw.wiphy->bands[params->chandef.chan->band]; | ||
1113 | for (i = 0; i < sband->n_bitrates; i++) { | ||
1114 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
1115 | sdata->u.ibss.basic_rates &= ~BIT(i); | ||
1116 | } | ||
1033 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, | 1117 | memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate, |
1034 | sizeof(params->mcast_rate)); | 1118 | sizeof(params->mcast_rate)); |
1035 | 1119 | ||
@@ -1051,6 +1135,11 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1051 | memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); | 1135 | memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); |
1052 | sdata->u.ibss.ssid_len = params->ssid_len; | 1136 | sdata->u.ibss.ssid_len = params->ssid_len; |
1053 | 1137 | ||
1138 | memcpy(&sdata->u.ibss.ht_capa, ¶ms->ht_capa, | ||
1139 | sizeof(sdata->u.ibss.ht_capa)); | ||
1140 | memcpy(&sdata->u.ibss.ht_capa_mask, ¶ms->ht_capa_mask, | ||
1141 | sizeof(sdata->u.ibss.ht_capa_mask)); | ||
1142 | |||
1054 | /* | 1143 | /* |
1055 | * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is | 1144 | * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is |
1056 | * reserved, but an HT STA shall protect HT transmissions as though | 1145 | * reserved, but an HT STA shall protect HT transmissions as though |
@@ -1131,6 +1220,11 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
1131 | presp = rcu_dereference_protected(ifibss->presp, | 1220 | presp = rcu_dereference_protected(ifibss->presp, |
1132 | lockdep_is_held(&sdata->wdev.mtx)); | 1221 | lockdep_is_held(&sdata->wdev.mtx)); |
1133 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); | 1222 | RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); |
1223 | |||
1224 | /* on the next join, re-program HT parameters */ | ||
1225 | memset(&ifibss->ht_capa, 0, sizeof(ifibss->ht_capa)); | ||
1226 | memset(&ifibss->ht_capa_mask, 0, sizeof(ifibss->ht_capa_mask)); | ||
1227 | |||
1134 | sdata->vif.bss_conf.ibss_joined = false; | 1228 | sdata->vif.bss_conf.ibss_joined = false; |
1135 | sdata->vif.bss_conf.ibss_creator = false; | 1229 | sdata->vif.bss_conf.ibss_creator = false; |
1136 | sdata->vif.bss_conf.enable_beacon = false; | 1230 | sdata->vif.bss_conf.enable_beacon = false; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8412a303993a..3d32df1fbc6d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -509,6 +509,9 @@ struct ieee80211_if_ibss { | |||
509 | /* probe response/beacon for IBSS */ | 509 | /* probe response/beacon for IBSS */ |
510 | struct beacon_data __rcu *presp; | 510 | struct beacon_data __rcu *presp; |
511 | 511 | ||
512 | struct ieee80211_ht_cap ht_capa; /* configured ht-cap over-rides */ | ||
513 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | ||
514 | |||
512 | spinlock_t incomplete_lock; | 515 | spinlock_t incomplete_lock; |
513 | struct list_head incomplete_stations; | 516 | struct list_head incomplete_stations; |
514 | 517 | ||
@@ -809,6 +812,34 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) | |||
809 | return band; | 812 | return band; |
810 | } | 813 | } |
811 | 814 | ||
815 | static inline int | ||
816 | ieee80211_chandef_get_shift(struct cfg80211_chan_def *chandef) | ||
817 | { | ||
818 | switch (chandef->width) { | ||
819 | case NL80211_CHAN_WIDTH_5: | ||
820 | return 2; | ||
821 | case NL80211_CHAN_WIDTH_10: | ||
822 | return 1; | ||
823 | default: | ||
824 | return 0; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | static inline int | ||
829 | ieee80211_vif_get_shift(struct ieee80211_vif *vif) | ||
830 | { | ||
831 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
832 | int shift = 0; | ||
833 | |||
834 | rcu_read_lock(); | ||
835 | chanctx_conf = rcu_dereference(vif->chanctx_conf); | ||
836 | if (chanctx_conf) | ||
837 | shift = ieee80211_chandef_get_shift(&chanctx_conf->def); | ||
838 | rcu_read_unlock(); | ||
839 | |||
840 | return shift; | ||
841 | } | ||
842 | |||
812 | enum sdata_queue_type { | 843 | enum sdata_queue_type { |
813 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | 844 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, |
814 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | 845 | IEEE80211_SDATA_QUEUE_AGG_START = 1, |
@@ -1026,7 +1057,7 @@ struct ieee80211_local { | |||
1026 | struct cfg80211_ssid scan_ssid; | 1057 | struct cfg80211_ssid scan_ssid; |
1027 | struct cfg80211_scan_request *int_scan_req; | 1058 | struct cfg80211_scan_request *int_scan_req; |
1028 | struct cfg80211_scan_request *scan_req, *hw_scan_req; | 1059 | struct cfg80211_scan_request *scan_req, *hw_scan_req; |
1029 | struct ieee80211_channel *scan_channel; | 1060 | struct cfg80211_chan_def scan_chandef; |
1030 | enum ieee80211_band hw_scan_band; | 1061 | enum ieee80211_band hw_scan_band; |
1031 | int scan_channel_idx; | 1062 | int scan_channel_idx; |
1032 | int scan_ies_len; | 1063 | int scan_ies_len; |
@@ -1306,7 +1337,8 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1306 | void ieee80211_scan_work(struct work_struct *work); | 1337 | void ieee80211_scan_work(struct work_struct *work); |
1307 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | 1338 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
1308 | const u8 *ssid, u8 ssid_len, | 1339 | const u8 *ssid, u8 ssid_len, |
1309 | struct ieee80211_channel *chan); | 1340 | struct ieee80211_channel *chan, |
1341 | enum nl80211_bss_scan_width scan_width); | ||
1310 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 1342 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
1311 | struct cfg80211_scan_request *req); | 1343 | struct cfg80211_scan_request *req); |
1312 | void ieee80211_scan_cancel(struct ieee80211_local *local); | 1344 | void ieee80211_scan_cancel(struct ieee80211_local *local); |
@@ -1465,7 +1497,8 @@ extern void *mac80211_wiphy_privid; /* for wiphy privid */ | |||
1465 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 1497 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
1466 | enum nl80211_iftype type); | 1498 | enum nl80211_iftype type); |
1467 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 1499 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
1468 | int rate, int erp, int short_preamble); | 1500 | int rate, int erp, int short_preamble, |
1501 | int shift); | ||
1469 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, | 1502 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
1470 | struct ieee80211_hdr *hdr, const u8 *tsc, | 1503 | struct ieee80211_hdr *hdr, const u8 *tsc, |
1471 | gfp_t gfp); | 1504 | gfp_t gfp); |
@@ -1569,7 +1602,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1569 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1602 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1570 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1603 | size_t buffer_len, const u8 *ie, size_t ie_len, |
1571 | enum ieee80211_band band, u32 rate_mask, | 1604 | enum ieee80211_band band, u32 rate_mask, |
1572 | u8 channel); | 1605 | struct cfg80211_chan_def *chandef); |
1573 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1606 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1574 | u8 *dst, u32 ratemask, | 1607 | u8 *dst, u32 ratemask, |
1575 | struct ieee80211_channel *chan, | 1608 | struct ieee80211_channel *chan, |
@@ -1582,10 +1615,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1582 | u32 ratemask, bool directed, u32 tx_flags, | 1615 | u32 ratemask, bool directed, u32 tx_flags, |
1583 | struct ieee80211_channel *channel, bool scan); | 1616 | struct ieee80211_channel *channel, bool scan); |
1584 | 1617 | ||
1585 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1618 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
1586 | const size_t supp_rates_len, | ||
1587 | const u8 *supp_rates); | ||
1588 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | ||
1589 | struct ieee802_11_elems *elems, | 1619 | struct ieee802_11_elems *elems, |
1590 | enum ieee80211_band band, u32 *basic_rates); | 1620 | enum ieee80211_band band, u32 *basic_rates); |
1591 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | 1621 | int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, |
@@ -1602,6 +1632,9 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1602 | u16 prot_mode); | 1632 | u16 prot_mode); |
1603 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1633 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1604 | u32 cap); | 1634 | u32 cap); |
1635 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, | ||
1636 | const struct ieee80211_supported_band *sband, | ||
1637 | const u8 *srates, int srates_len, u32 *rates); | ||
1605 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1638 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1606 | struct sk_buff *skb, bool need_basic, | 1639 | struct sk_buff *skb, bool need_basic, |
1607 | enum ieee80211_band band); | 1640 | enum ieee80211_band band); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index cc117591f678..4c41c11958c8 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -54,7 +54,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
54 | return false; | 54 | return false; |
55 | } | 55 | } |
56 | 56 | ||
57 | power = chanctx_conf->def.chan->max_power; | 57 | power = ieee80211_chandef_max_power(&chanctx_conf->def); |
58 | rcu_read_unlock(); | 58 | rcu_read_unlock(); |
59 | 59 | ||
60 | if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) | 60 | if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 091088ac7890..25eb35b01938 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -102,17 +102,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
102 | 102 | ||
103 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | 103 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
104 | 104 | ||
105 | if (local->scan_channel) { | 105 | if (local->scan_chandef.chan) { |
106 | chandef.chan = local->scan_channel; | 106 | chandef = local->scan_chandef; |
107 | /* If scanning on oper channel, use whatever channel-type | ||
108 | * is currently in use. | ||
109 | */ | ||
110 | if (chandef.chan == local->_oper_chandef.chan) { | ||
111 | chandef = local->_oper_chandef; | ||
112 | } else { | ||
113 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
114 | chandef.center_freq1 = chandef.chan->center_freq; | ||
115 | } | ||
116 | } else if (local->tmp_channel) { | 107 | } else if (local->tmp_channel) { |
117 | chandef.chan = local->tmp_channel; | 108 | chandef.chan = local->tmp_channel; |
118 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | 109 | chandef.width = NL80211_CHAN_WIDTH_20_NOHT; |
@@ -151,7 +142,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
151 | changed |= IEEE80211_CONF_CHANGE_SMPS; | 142 | changed |= IEEE80211_CONF_CHANGE_SMPS; |
152 | } | 143 | } |
153 | 144 | ||
154 | power = chandef.chan->max_power; | 145 | power = ieee80211_chandef_max_power(&chandef); |
155 | 146 | ||
156 | rcu_read_lock(); | 147 | rcu_read_lock(); |
157 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 148 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 447f41bbe744..885a5f6e2c21 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -62,7 +62,6 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
62 | struct ieee802_11_elems *ie) | 62 | struct ieee802_11_elems *ie) |
63 | { | 63 | { |
64 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 64 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
65 | struct ieee80211_local *local = sdata->local; | ||
66 | u32 basic_rates = 0; | 65 | u32 basic_rates = 0; |
67 | struct cfg80211_chan_def sta_chan_def; | 66 | struct cfg80211_chan_def sta_chan_def; |
68 | 67 | ||
@@ -85,7 +84,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
85 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 84 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
86 | return false; | 85 | return false; |
87 | 86 | ||
88 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), | 87 | ieee80211_sta_get_rates(sdata, ie, ieee80211_get_sdata_band(sdata), |
89 | &basic_rates); | 88 | &basic_rates); |
90 | 89 | ||
91 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 90 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
@@ -274,7 +273,9 @@ int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, | |||
274 | neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS); | 273 | neighbors = min_t(int, neighbors, IEEE80211_MAX_MESH_PEERINGS); |
275 | *pos++ = neighbors << 1; | 274 | *pos++ = neighbors << 1; |
276 | /* Mesh capability */ | 275 | /* Mesh capability */ |
277 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; | 276 | *pos = 0x00; |
277 | *pos |= ifmsh->mshcfg.dot11MeshForwarding ? | ||
278 | IEEE80211_MESHCONF_CAPAB_FORWARDING : 0x00; | ||
278 | *pos |= ifmsh->accepting_plinks ? | 279 | *pos |= ifmsh->accepting_plinks ? |
279 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 280 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
280 | /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ | 281 | /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 02c05fa15c20..6b65d5055f5b 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -379,7 +379,7 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
379 | u32 rates, basic_rates = 0, changed = 0; | 379 | u32 rates, basic_rates = 0, changed = 0; |
380 | 380 | ||
381 | sband = local->hw.wiphy->bands[band]; | 381 | sband = local->hw.wiphy->bands[band]; |
382 | rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates); | 382 | rates = ieee80211_sta_get_rates(sdata, elems, band, &basic_rates); |
383 | 383 | ||
384 | spin_lock_bh(&sta->lock); | 384 | spin_lock_bh(&sta->lock); |
385 | sta->last_rx = jiffies; | 385 | sta->last_rx = jiffies; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ae31968d42d3..211246b46819 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -478,27 +478,6 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, | |||
478 | 478 | ||
479 | /* frame sending functions */ | 479 | /* frame sending functions */ |
480 | 480 | ||
481 | static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | ||
482 | struct ieee80211_supported_band *sband, | ||
483 | u32 *rates) | ||
484 | { | ||
485 | int i, j, count; | ||
486 | *rates = 0; | ||
487 | count = 0; | ||
488 | for (i = 0; i < supp_rates_len; i++) { | ||
489 | int rate = (supp_rates[i] & 0x7F) * 5; | ||
490 | |||
491 | for (j = 0; j < sband->n_bitrates; j++) | ||
492 | if (sband->bitrates[j].bitrate == rate) { | ||
493 | *rates |= BIT(j); | ||
494 | count++; | ||
495 | break; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | return count; | ||
500 | } | ||
501 | |||
502 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | 481 | static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, |
503 | struct sk_buff *skb, u8 ap_ht_param, | 482 | struct sk_buff *skb, u8 ap_ht_param, |
504 | struct ieee80211_supported_band *sband, | 483 | struct ieee80211_supported_band *sband, |
@@ -617,12 +596,12 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
617 | struct ieee80211_mgmt *mgmt; | 596 | struct ieee80211_mgmt *mgmt; |
618 | u8 *pos, qos_info; | 597 | u8 *pos, qos_info; |
619 | size_t offset = 0, noffset; | 598 | size_t offset = 0, noffset; |
620 | int i, count, rates_len, supp_rates_len; | 599 | int i, count, rates_len, supp_rates_len, shift; |
621 | u16 capab; | 600 | u16 capab; |
622 | struct ieee80211_supported_band *sband; | 601 | struct ieee80211_supported_band *sband; |
623 | struct ieee80211_chanctx_conf *chanctx_conf; | 602 | struct ieee80211_chanctx_conf *chanctx_conf; |
624 | struct ieee80211_channel *chan; | 603 | struct ieee80211_channel *chan; |
625 | u32 rates = 0; | 604 | u32 rate_flags, rates = 0; |
626 | 605 | ||
627 | sdata_assert_lock(sdata); | 606 | sdata_assert_lock(sdata); |
628 | 607 | ||
@@ -633,8 +612,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
633 | return; | 612 | return; |
634 | } | 613 | } |
635 | chan = chanctx_conf->def.chan; | 614 | chan = chanctx_conf->def.chan; |
615 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
636 | rcu_read_unlock(); | 616 | rcu_read_unlock(); |
637 | sband = local->hw.wiphy->bands[chan->band]; | 617 | sband = local->hw.wiphy->bands[chan->band]; |
618 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
638 | 619 | ||
639 | if (assoc_data->supp_rates_len) { | 620 | if (assoc_data->supp_rates_len) { |
640 | /* | 621 | /* |
@@ -643,17 +624,24 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
643 | * in the association request (e.g. D-Link DAP 1353 in | 624 | * in the association request (e.g. D-Link DAP 1353 in |
644 | * b-only mode)... | 625 | * b-only mode)... |
645 | */ | 626 | */ |
646 | rates_len = ieee80211_compatible_rates(assoc_data->supp_rates, | 627 | rates_len = ieee80211_parse_bitrates(&chanctx_conf->def, sband, |
647 | assoc_data->supp_rates_len, | 628 | assoc_data->supp_rates, |
648 | sband, &rates); | 629 | assoc_data->supp_rates_len, |
630 | &rates); | ||
649 | } else { | 631 | } else { |
650 | /* | 632 | /* |
651 | * In case AP not provide any supported rates information | 633 | * In case AP not provide any supported rates information |
652 | * before association, we send information element(s) with | 634 | * before association, we send information element(s) with |
653 | * all rates that we support. | 635 | * all rates that we support. |
654 | */ | 636 | */ |
655 | rates = ~0; | 637 | rates_len = 0; |
656 | rates_len = sband->n_bitrates; | 638 | for (i = 0; i < sband->n_bitrates; i++) { |
639 | if ((rate_flags & sband->bitrates[i].flags) | ||
640 | != rate_flags) | ||
641 | continue; | ||
642 | rates |= BIT(i); | ||
643 | rates_len++; | ||
644 | } | ||
657 | } | 645 | } |
658 | 646 | ||
659 | skb = alloc_skb(local->hw.extra_tx_headroom + | 647 | skb = alloc_skb(local->hw.extra_tx_headroom + |
@@ -730,8 +718,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
730 | count = 0; | 718 | count = 0; |
731 | for (i = 0; i < sband->n_bitrates; i++) { | 719 | for (i = 0; i < sband->n_bitrates; i++) { |
732 | if (BIT(i) & rates) { | 720 | if (BIT(i) & rates) { |
733 | int rate = sband->bitrates[i].bitrate; | 721 | int rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
734 | *pos++ = (u8) (rate / 5); | 722 | 5 * (1 << shift)); |
723 | *pos++ = (u8) rate; | ||
735 | if (++count == 8) | 724 | if (++count == 8) |
736 | break; | 725 | break; |
737 | } | 726 | } |
@@ -744,8 +733,10 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
744 | 733 | ||
745 | for (i++; i < sband->n_bitrates; i++) { | 734 | for (i++; i < sband->n_bitrates; i++) { |
746 | if (BIT(i) & rates) { | 735 | if (BIT(i) & rates) { |
747 | int rate = sband->bitrates[i].bitrate; | 736 | int rate; |
748 | *pos++ = (u8) (rate / 5); | 737 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
738 | 5 * (1 << shift)); | ||
739 | *pos++ = (u8) rate; | ||
749 | } | 740 | } |
750 | } | 741 | } |
751 | } | 742 | } |
@@ -756,7 +747,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
756 | *pos++ = WLAN_EID_PWR_CAPABILITY; | 747 | *pos++ = WLAN_EID_PWR_CAPABILITY; |
757 | *pos++ = 2; | 748 | *pos++ = 2; |
758 | *pos++ = 0; /* min tx power */ | 749 | *pos++ = 0; /* min tx power */ |
759 | *pos++ = chan->max_power; /* max tx power */ | 750 | /* max tx power */ |
751 | *pos++ = ieee80211_chandef_max_power(&chanctx_conf->def); | ||
760 | 752 | ||
761 | /* 2. supported channels */ | 753 | /* 2. supported channels */ |
762 | /* TODO: get this in reg domain format */ | 754 | /* TODO: get this in reg domain format */ |
@@ -2432,15 +2424,16 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
2432 | u8 *supp_rates, unsigned int supp_rates_len, | 2424 | u8 *supp_rates, unsigned int supp_rates_len, |
2433 | u32 *rates, u32 *basic_rates, | 2425 | u32 *rates, u32 *basic_rates, |
2434 | bool *have_higher_than_11mbit, | 2426 | bool *have_higher_than_11mbit, |
2435 | int *min_rate, int *min_rate_index) | 2427 | int *min_rate, int *min_rate_index, |
2428 | int shift, u32 rate_flags) | ||
2436 | { | 2429 | { |
2437 | int i, j; | 2430 | int i, j; |
2438 | 2431 | ||
2439 | for (i = 0; i < supp_rates_len; i++) { | 2432 | for (i = 0; i < supp_rates_len; i++) { |
2440 | int rate = (supp_rates[i] & 0x7f) * 5; | 2433 | int rate = supp_rates[i] & 0x7f; |
2441 | bool is_basic = !!(supp_rates[i] & 0x80); | 2434 | bool is_basic = !!(supp_rates[i] & 0x80); |
2442 | 2435 | ||
2443 | if (rate > 110) | 2436 | if ((rate * 5 * (1 << shift)) > 110) |
2444 | *have_higher_than_11mbit = true; | 2437 | *have_higher_than_11mbit = true; |
2445 | 2438 | ||
2446 | /* | 2439 | /* |
@@ -2456,12 +2449,20 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, | |||
2456 | continue; | 2449 | continue; |
2457 | 2450 | ||
2458 | for (j = 0; j < sband->n_bitrates; j++) { | 2451 | for (j = 0; j < sband->n_bitrates; j++) { |
2459 | if (sband->bitrates[j].bitrate == rate) { | 2452 | struct ieee80211_rate *br; |
2453 | int brate; | ||
2454 | |||
2455 | br = &sband->bitrates[j]; | ||
2456 | if ((rate_flags & br->flags) != rate_flags) | ||
2457 | continue; | ||
2458 | |||
2459 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); | ||
2460 | if (brate == rate) { | ||
2460 | *rates |= BIT(j); | 2461 | *rates |= BIT(j); |
2461 | if (is_basic) | 2462 | if (is_basic) |
2462 | *basic_rates |= BIT(j); | 2463 | *basic_rates |= BIT(j); |
2463 | if (rate < *min_rate) { | 2464 | if ((rate * 5) < *min_rate) { |
2464 | *min_rate = rate; | 2465 | *min_rate = rate * 5; |
2465 | *min_rate_index = j; | 2466 | *min_rate_index = j; |
2466 | } | 2467 | } |
2467 | break; | 2468 | break; |
@@ -3884,27 +3885,40 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3884 | if (!new_sta) | 3885 | if (!new_sta) |
3885 | return -ENOMEM; | 3886 | return -ENOMEM; |
3886 | } | 3887 | } |
3887 | |||
3888 | if (new_sta) { | 3888 | if (new_sta) { |
3889 | u32 rates = 0, basic_rates = 0; | 3889 | u32 rates = 0, basic_rates = 0; |
3890 | bool have_higher_than_11mbit; | 3890 | bool have_higher_than_11mbit; |
3891 | int min_rate = INT_MAX, min_rate_index = -1; | 3891 | int min_rate = INT_MAX, min_rate_index = -1; |
3892 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3892 | struct ieee80211_supported_band *sband; | 3893 | struct ieee80211_supported_band *sband; |
3893 | const struct cfg80211_bss_ies *ies; | 3894 | const struct cfg80211_bss_ies *ies; |
3895 | int shift; | ||
3896 | u32 rate_flags; | ||
3894 | 3897 | ||
3895 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3898 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3896 | 3899 | ||
3897 | err = ieee80211_prep_channel(sdata, cbss); | 3900 | err = ieee80211_prep_channel(sdata, cbss); |
3898 | if (err) { | 3901 | if (err) { |
3899 | sta_info_free(local, new_sta); | 3902 | sta_info_free(local, new_sta); |
3900 | return err; | 3903 | return -EINVAL; |
3901 | } | 3904 | } |
3905 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
3906 | |||
3907 | rcu_read_lock(); | ||
3908 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3909 | if (WARN_ON(!chanctx_conf)) { | ||
3910 | rcu_read_unlock(); | ||
3911 | return -EINVAL; | ||
3912 | } | ||
3913 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
3914 | rcu_read_unlock(); | ||
3902 | 3915 | ||
3903 | ieee80211_get_rates(sband, bss->supp_rates, | 3916 | ieee80211_get_rates(sband, bss->supp_rates, |
3904 | bss->supp_rates_len, | 3917 | bss->supp_rates_len, |
3905 | &rates, &basic_rates, | 3918 | &rates, &basic_rates, |
3906 | &have_higher_than_11mbit, | 3919 | &have_higher_than_11mbit, |
3907 | &min_rate, &min_rate_index); | 3920 | &min_rate, &min_rate_index, |
3921 | shift, rate_flags); | ||
3908 | 3922 | ||
3909 | /* | 3923 | /* |
3910 | * This used to be a workaround for basic rates missing | 3924 | * This used to be a workaround for basic rates missing |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 30d58d2d13e2..ba63ac851c2b 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -232,37 +232,28 @@ static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, | |||
232 | /* could not find a basic rate; use original selection */ | 232 | /* could not find a basic rate; use original selection */ |
233 | } | 233 | } |
234 | 234 | ||
235 | static inline s8 | 235 | static void __rate_control_send_low(struct ieee80211_hw *hw, |
236 | rate_lowest_non_cck_index(struct ieee80211_supported_band *sband, | 236 | struct ieee80211_supported_band *sband, |
237 | struct ieee80211_sta *sta) | 237 | struct ieee80211_sta *sta, |
238 | struct ieee80211_tx_info *info) | ||
238 | { | 239 | { |
239 | int i; | 240 | int i; |
241 | u32 rate_flags = | ||
242 | ieee80211_chandef_rate_flags(&hw->conf.chandef); | ||
240 | 243 | ||
244 | if ((sband->band == IEEE80211_BAND_2GHZ) && | ||
245 | (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) | ||
246 | rate_flags |= IEEE80211_RATE_ERP_G; | ||
247 | |||
248 | info->control.rates[0].idx = 0; | ||
241 | for (i = 0; i < sband->n_bitrates; i++) { | 249 | for (i = 0; i < sband->n_bitrates; i++) { |
242 | struct ieee80211_rate *srate = &sband->bitrates[i]; | 250 | if (!rate_supported(sta, sband->band, i)) |
243 | if ((srate->bitrate == 10) || (srate->bitrate == 20) || | ||
244 | (srate->bitrate == 55) || (srate->bitrate == 110)) | ||
245 | continue; | 251 | continue; |
246 | 252 | ||
247 | if (rate_supported(sta, sband->band, i)) | 253 | info->control.rates[0].idx = i; |
248 | return i; | 254 | break; |
249 | } | 255 | } |
250 | 256 | WARN_ON_ONCE(i == sband->n_bitrates); | |
251 | /* No matching rate found */ | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static void __rate_control_send_low(struct ieee80211_hw *hw, | ||
256 | struct ieee80211_supported_band *sband, | ||
257 | struct ieee80211_sta *sta, | ||
258 | struct ieee80211_tx_info *info) | ||
259 | { | ||
260 | if ((sband->band != IEEE80211_BAND_2GHZ) || | ||
261 | !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)) | ||
262 | info->control.rates[0].idx = rate_lowest_index(sband, sta); | ||
263 | else | ||
264 | info->control.rates[0].idx = | ||
265 | rate_lowest_non_cck_index(sband, sta); | ||
266 | 257 | ||
267 | info->control.rates[0].count = | 258 | info->control.rates[0].count = |
268 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? | 259 | (info->flags & IEEE80211_TX_CTL_NO_ACK) ? |
@@ -585,6 +576,7 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
585 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; | 576 | u8 mcs_mask[IEEE80211_HT_MCS_MASK_LEN]; |
586 | bool has_mcs_mask; | 577 | bool has_mcs_mask; |
587 | u32 mask; | 578 | u32 mask; |
579 | u32 rate_flags; | ||
588 | int i; | 580 | int i; |
589 | 581 | ||
590 | /* | 582 | /* |
@@ -594,6 +586,12 @@ static void rate_control_apply_mask(struct ieee80211_sub_if_data *sdata, | |||
594 | */ | 586 | */ |
595 | mask = sdata->rc_rateidx_mask[info->band]; | 587 | mask = sdata->rc_rateidx_mask[info->band]; |
596 | has_mcs_mask = sdata->rc_has_mcs_mask[info->band]; | 588 | has_mcs_mask = sdata->rc_has_mcs_mask[info->band]; |
589 | rate_flags = | ||
590 | ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
591 | for (i = 0; i < sband->n_bitrates; i++) | ||
592 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
593 | mask &= ~BIT(i); | ||
594 | |||
597 | if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask) | 595 | if (mask == (1 << sband->n_bitrates) - 1 && !has_mcs_mask) |
598 | return; | 596 | return; |
599 | 597 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index d35a5dd3fb13..5dedc56c94db 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -66,11 +66,12 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; | 68 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; |
69 | rcu_read_unlock(); | ||
70 | 69 | ||
71 | ieee80211_sta_set_rx_nss(sta); | 70 | ieee80211_sta_set_rx_nss(sta); |
72 | 71 | ||
73 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 72 | ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista, |
73 | priv_sta); | ||
74 | rcu_read_unlock(); | ||
74 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); | 75 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); |
75 | } | 76 | } |
76 | 77 | ||
@@ -81,10 +82,21 @@ static inline void rate_control_rate_update(struct ieee80211_local *local, | |||
81 | struct rate_control_ref *ref = local->rate_ctrl; | 82 | struct rate_control_ref *ref = local->rate_ctrl; |
82 | struct ieee80211_sta *ista = &sta->sta; | 83 | struct ieee80211_sta *ista = &sta->sta; |
83 | void *priv_sta = sta->rate_ctrl_priv; | 84 | void *priv_sta = sta->rate_ctrl_priv; |
85 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
86 | |||
87 | if (ref && ref->ops->rate_update) { | ||
88 | rcu_read_lock(); | ||
84 | 89 | ||
85 | if (ref && ref->ops->rate_update) | 90 | chanctx_conf = rcu_dereference(sta->sdata->vif.chanctx_conf); |
86 | ref->ops->rate_update(ref->priv, sband, ista, | 91 | if (WARN_ON(!chanctx_conf)) { |
87 | priv_sta, changed); | 92 | rcu_read_unlock(); |
93 | return; | ||
94 | } | ||
95 | |||
96 | ref->ops->rate_update(ref->priv, sband, &chanctx_conf->def, | ||
97 | ista, priv_sta, changed); | ||
98 | rcu_read_unlock(); | ||
99 | } | ||
88 | drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); | 100 | drv_sta_rc_update(local, sta->sdata, &sta->sta, changed); |
89 | } | 101 | } |
90 | 102 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index e6512e2ffd20..8b5f7ef7c0c9 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -383,14 +383,18 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, | |||
383 | static void | 383 | static void |
384 | calc_rate_durations(enum ieee80211_band band, | 384 | calc_rate_durations(enum ieee80211_band band, |
385 | struct minstrel_rate *d, | 385 | struct minstrel_rate *d, |
386 | struct ieee80211_rate *rate) | 386 | struct ieee80211_rate *rate, |
387 | struct cfg80211_chan_def *chandef) | ||
387 | { | 388 | { |
388 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); | 389 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); |
390 | int shift = ieee80211_chandef_get_shift(chandef); | ||
389 | 391 | ||
390 | d->perfect_tx_time = ieee80211_frame_duration(band, 1200, | 392 | d->perfect_tx_time = ieee80211_frame_duration(band, 1200, |
391 | rate->bitrate, erp, 1); | 393 | DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1, |
394 | shift); | ||
392 | d->ack_time = ieee80211_frame_duration(band, 10, | 395 | d->ack_time = ieee80211_frame_duration(band, 10, |
393 | rate->bitrate, erp, 1); | 396 | DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1, |
397 | shift); | ||
394 | } | 398 | } |
395 | 399 | ||
396 | static void | 400 | static void |
@@ -418,21 +422,25 @@ init_sample_table(struct minstrel_sta_info *mi) | |||
418 | 422 | ||
419 | static void | 423 | static void |
420 | minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | 424 | minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, |
421 | struct ieee80211_sta *sta, void *priv_sta) | 425 | struct cfg80211_chan_def *chandef, |
426 | struct ieee80211_sta *sta, void *priv_sta) | ||
422 | { | 427 | { |
423 | struct minstrel_sta_info *mi = priv_sta; | 428 | struct minstrel_sta_info *mi = priv_sta; |
424 | struct minstrel_priv *mp = priv; | 429 | struct minstrel_priv *mp = priv; |
425 | struct ieee80211_rate *ctl_rate; | 430 | struct ieee80211_rate *ctl_rate; |
426 | unsigned int i, n = 0; | 431 | unsigned int i, n = 0; |
427 | unsigned int t_slot = 9; /* FIXME: get real slot time */ | 432 | unsigned int t_slot = 9; /* FIXME: get real slot time */ |
433 | u32 rate_flags; | ||
428 | 434 | ||
429 | mi->sta = sta; | 435 | mi->sta = sta; |
430 | mi->lowest_rix = rate_lowest_index(sband, sta); | 436 | mi->lowest_rix = rate_lowest_index(sband, sta); |
431 | ctl_rate = &sband->bitrates[mi->lowest_rix]; | 437 | ctl_rate = &sband->bitrates[mi->lowest_rix]; |
432 | mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10, | 438 | mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10, |
433 | ctl_rate->bitrate, | 439 | ctl_rate->bitrate, |
434 | !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1); | 440 | !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1, |
441 | ieee80211_chandef_get_shift(chandef)); | ||
435 | 442 | ||
443 | rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); | ||
436 | memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate)); | 444 | memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate)); |
437 | mi->max_prob_rate = 0; | 445 | mi->max_prob_rate = 0; |
438 | 446 | ||
@@ -441,15 +449,22 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
441 | unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; | 449 | unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; |
442 | unsigned int tx_time_single; | 450 | unsigned int tx_time_single; |
443 | unsigned int cw = mp->cw_min; | 451 | unsigned int cw = mp->cw_min; |
452 | int shift; | ||
444 | 453 | ||
445 | if (!rate_supported(sta, sband->band, i)) | 454 | if (!rate_supported(sta, sband->band, i)) |
446 | continue; | 455 | continue; |
456 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
457 | continue; | ||
458 | |||
447 | n++; | 459 | n++; |
448 | memset(mr, 0, sizeof(*mr)); | 460 | memset(mr, 0, sizeof(*mr)); |
449 | 461 | ||
450 | mr->rix = i; | 462 | mr->rix = i; |
451 | mr->bitrate = sband->bitrates[i].bitrate / 5; | 463 | shift = ieee80211_chandef_get_shift(chandef); |
452 | calc_rate_durations(sband->band, mr, &sband->bitrates[i]); | 464 | mr->bitrate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
465 | (1 << shift) * 5); | ||
466 | calc_rate_durations(sband->band, mr, &sband->bitrates[i], | ||
467 | chandef); | ||
453 | 468 | ||
454 | /* calculate maximum number of retransmissions before | 469 | /* calculate maximum number of retransmissions before |
455 | * fallback (based on maximum segment size) */ | 470 | * fallback (based on maximum segment size) */ |
@@ -547,6 +562,7 @@ minstrel_init_cck_rates(struct minstrel_priv *mp) | |||
547 | { | 562 | { |
548 | static const int bitrates[4] = { 10, 20, 55, 110 }; | 563 | static const int bitrates[4] = { 10, 20, 55, 110 }; |
549 | struct ieee80211_supported_band *sband; | 564 | struct ieee80211_supported_band *sband; |
565 | u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); | ||
550 | int i, j; | 566 | int i, j; |
551 | 567 | ||
552 | sband = mp->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; | 568 | sband = mp->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; |
@@ -559,6 +575,9 @@ minstrel_init_cck_rates(struct minstrel_priv *mp) | |||
559 | if (rate->flags & IEEE80211_RATE_ERP_G) | 575 | if (rate->flags & IEEE80211_RATE_ERP_G) |
560 | continue; | 576 | continue; |
561 | 577 | ||
578 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
579 | continue; | ||
580 | |||
562 | for (j = 0; j < ARRAY_SIZE(bitrates); j++) { | 581 | for (j = 0; j < ARRAY_SIZE(bitrates); j++) { |
563 | if (rate->bitrate != bitrates[j]) | 582 | if (rate->bitrate != bitrates[j]) |
564 | continue; | 583 | continue; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index f5aed963b22e..61569425b723 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -844,6 +844,7 @@ minstrel_ht_update_cck(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
844 | 844 | ||
845 | static void | 845 | static void |
846 | minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | 846 | minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, |
847 | struct cfg80211_chan_def *chandef, | ||
847 | struct ieee80211_sta *sta, void *priv_sta) | 848 | struct ieee80211_sta *sta, void *priv_sta) |
848 | { | 849 | { |
849 | struct minstrel_priv *mp = priv; | 850 | struct minstrel_priv *mp = priv; |
@@ -869,8 +870,9 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, | |||
869 | mi->sta = sta; | 870 | mi->sta = sta; |
870 | mi->stats_update = jiffies; | 871 | mi->stats_update = jiffies; |
871 | 872 | ||
872 | ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1); | 873 | ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0); |
873 | mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1) + ack_dur; | 874 | mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0); |
875 | mi->overhead += ack_dur; | ||
874 | mi->overhead_rtscts = mi->overhead + 2 * ack_dur; | 876 | mi->overhead_rtscts = mi->overhead + 2 * ack_dur; |
875 | 877 | ||
876 | mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); | 878 | mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); |
@@ -939,22 +941,25 @@ use_legacy: | |||
939 | memset(&msp->legacy, 0, sizeof(msp->legacy)); | 941 | memset(&msp->legacy, 0, sizeof(msp->legacy)); |
940 | msp->legacy.r = msp->ratelist; | 942 | msp->legacy.r = msp->ratelist; |
941 | msp->legacy.sample_table = msp->sample_table; | 943 | msp->legacy.sample_table = msp->sample_table; |
942 | return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy); | 944 | return mac80211_minstrel.rate_init(priv, sband, chandef, sta, |
945 | &msp->legacy); | ||
943 | } | 946 | } |
944 | 947 | ||
945 | static void | 948 | static void |
946 | minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, | 949 | minstrel_ht_rate_init(void *priv, struct ieee80211_supported_band *sband, |
950 | struct cfg80211_chan_def *chandef, | ||
947 | struct ieee80211_sta *sta, void *priv_sta) | 951 | struct ieee80211_sta *sta, void *priv_sta) |
948 | { | 952 | { |
949 | minstrel_ht_update_caps(priv, sband, sta, priv_sta); | 953 | minstrel_ht_update_caps(priv, sband, chandef, sta, priv_sta); |
950 | } | 954 | } |
951 | 955 | ||
952 | static void | 956 | static void |
953 | minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, | 957 | minstrel_ht_rate_update(void *priv, struct ieee80211_supported_band *sband, |
958 | struct cfg80211_chan_def *chandef, | ||
954 | struct ieee80211_sta *sta, void *priv_sta, | 959 | struct ieee80211_sta *sta, void *priv_sta, |
955 | u32 changed) | 960 | u32 changed) |
956 | { | 961 | { |
957 | minstrel_ht_update_caps(priv, sband, sta, priv_sta); | 962 | minstrel_ht_update_caps(priv, sband, chandef, sta, priv_sta); |
958 | } | 963 | } |
959 | 964 | ||
960 | static void * | 965 | static void * |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 502d3ecc4a79..958fad07b54c 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -293,6 +293,7 @@ rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | |||
293 | 293 | ||
294 | static void | 294 | static void |
295 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | 295 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, |
296 | struct cfg80211_chan_def *chandef, | ||
296 | struct ieee80211_sta *sta, void *priv_sta) | 297 | struct ieee80211_sta *sta, void *priv_sta) |
297 | { | 298 | { |
298 | struct rc_pid_sta_info *spinfo = priv_sta; | 299 | struct rc_pid_sta_info *spinfo = priv_sta; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 2c5a79bd3777..6b85f95b9ba1 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -87,11 +87,13 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
87 | int len; | 87 | int len; |
88 | 88 | ||
89 | /* always present fields */ | 89 | /* always present fields */ |
90 | len = sizeof(struct ieee80211_radiotap_header) + 9; | 90 | len = sizeof(struct ieee80211_radiotap_header) + 8; |
91 | 91 | ||
92 | /* allocate extra bitmap */ | 92 | /* allocate extra bitmaps */ |
93 | if (status->vendor_radiotap_len) | 93 | if (status->vendor_radiotap_len) |
94 | len += 4; | 94 | len += 4; |
95 | if (status->chains) | ||
96 | len += 4 * hweight8(status->chains); | ||
95 | 97 | ||
96 | if (ieee80211_have_rx_timestamp(status)) { | 98 | if (ieee80211_have_rx_timestamp(status)) { |
97 | len = ALIGN(len, 8); | 99 | len = ALIGN(len, 8); |
@@ -100,6 +102,10 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
100 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 102 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
101 | len += 1; | 103 | len += 1; |
102 | 104 | ||
105 | /* antenna field, if we don't have per-chain info */ | ||
106 | if (!status->chains) | ||
107 | len += 1; | ||
108 | |||
103 | /* padding for RX_FLAGS if necessary */ | 109 | /* padding for RX_FLAGS if necessary */ |
104 | len = ALIGN(len, 2); | 110 | len = ALIGN(len, 2); |
105 | 111 | ||
@@ -116,6 +122,11 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
116 | len += 12; | 122 | len += 12; |
117 | } | 123 | } |
118 | 124 | ||
125 | if (status->chains) { | ||
126 | /* antenna and antenna signal fields */ | ||
127 | len += 2 * hweight8(status->chains); | ||
128 | } | ||
129 | |||
119 | if (status->vendor_radiotap_len) { | 130 | if (status->vendor_radiotap_len) { |
120 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) | 131 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) |
121 | status->vendor_radiotap_align = 1; | 132 | status->vendor_radiotap_align = 1; |
@@ -145,8 +156,12 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
145 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 156 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
146 | struct ieee80211_radiotap_header *rthdr; | 157 | struct ieee80211_radiotap_header *rthdr; |
147 | unsigned char *pos; | 158 | unsigned char *pos; |
159 | __le32 *it_present; | ||
160 | u32 it_present_val; | ||
148 | u16 rx_flags = 0; | 161 | u16 rx_flags = 0; |
149 | int mpdulen; | 162 | u16 channel_flags = 0; |
163 | int mpdulen, chain; | ||
164 | unsigned long chains = status->chains; | ||
150 | 165 | ||
151 | mpdulen = skb->len; | 166 | mpdulen = skb->len; |
152 | if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))) | 167 | if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))) |
@@ -154,25 +169,39 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
154 | 169 | ||
155 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); | 170 | rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); |
156 | memset(rthdr, 0, rtap_len); | 171 | memset(rthdr, 0, rtap_len); |
172 | it_present = &rthdr->it_present; | ||
157 | 173 | ||
158 | /* radiotap header, set always present flags */ | 174 | /* radiotap header, set always present flags */ |
159 | rthdr->it_present = | ||
160 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | ||
161 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
162 | (1 << IEEE80211_RADIOTAP_ANTENNA) | | ||
163 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | ||
164 | rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); | 175 | rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); |
176 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | | ||
177 | BIT(IEEE80211_RADIOTAP_CHANNEL) | | ||
178 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); | ||
165 | 179 | ||
166 | pos = (unsigned char *)(rthdr + 1); | 180 | if (!status->chains) |
181 | it_present_val |= BIT(IEEE80211_RADIOTAP_ANTENNA); | ||
182 | |||
183 | for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { | ||
184 | it_present_val |= | ||
185 | BIT(IEEE80211_RADIOTAP_EXT) | | ||
186 | BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE); | ||
187 | put_unaligned_le32(it_present_val, it_present); | ||
188 | it_present++; | ||
189 | it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) | | ||
190 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | ||
191 | } | ||
167 | 192 | ||
168 | if (status->vendor_radiotap_len) { | 193 | if (status->vendor_radiotap_len) { |
169 | rthdr->it_present |= | 194 | it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | |
170 | cpu_to_le32(BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE)) | | 195 | BIT(IEEE80211_RADIOTAP_EXT); |
171 | cpu_to_le32(BIT(IEEE80211_RADIOTAP_EXT)); | 196 | put_unaligned_le32(it_present_val, it_present); |
172 | put_unaligned_le32(status->vendor_radiotap_bitmap, pos); | 197 | it_present++; |
173 | pos += 4; | 198 | it_present_val = status->vendor_radiotap_bitmap; |
174 | } | 199 | } |
175 | 200 | ||
201 | put_unaligned_le32(it_present_val, it_present); | ||
202 | |||
203 | pos = (void *)(it_present + 1); | ||
204 | |||
176 | /* the order of the following fields is important */ | 205 | /* the order of the following fields is important */ |
177 | 206 | ||
178 | /* IEEE80211_RADIOTAP_TSFT */ | 207 | /* IEEE80211_RADIOTAP_TSFT */ |
@@ -207,28 +236,35 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
207 | */ | 236 | */ |
208 | *pos = 0; | 237 | *pos = 0; |
209 | } else { | 238 | } else { |
239 | int shift = 0; | ||
210 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | 240 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); |
211 | *pos = rate->bitrate / 5; | 241 | if (status->flag & RX_FLAG_10MHZ) |
242 | shift = 1; | ||
243 | else if (status->flag & RX_FLAG_5MHZ) | ||
244 | shift = 2; | ||
245 | *pos = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift)); | ||
212 | } | 246 | } |
213 | pos++; | 247 | pos++; |
214 | 248 | ||
215 | /* IEEE80211_RADIOTAP_CHANNEL */ | 249 | /* IEEE80211_RADIOTAP_CHANNEL */ |
216 | put_unaligned_le16(status->freq, pos); | 250 | put_unaligned_le16(status->freq, pos); |
217 | pos += 2; | 251 | pos += 2; |
252 | if (status->flag & RX_FLAG_10MHZ) | ||
253 | channel_flags |= IEEE80211_CHAN_HALF; | ||
254 | else if (status->flag & RX_FLAG_5MHZ) | ||
255 | channel_flags |= IEEE80211_CHAN_QUARTER; | ||
256 | |||
218 | if (status->band == IEEE80211_BAND_5GHZ) | 257 | if (status->band == IEEE80211_BAND_5GHZ) |
219 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, | 258 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ; |
220 | pos); | ||
221 | else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) | 259 | else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) |
222 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | 260 | channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; |
223 | pos); | ||
224 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 261 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
225 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, | 262 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; |
226 | pos); | ||
227 | else if (rate) | 263 | else if (rate) |
228 | put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ, | 264 | channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; |
229 | pos); | ||
230 | else | 265 | else |
231 | put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos); | 266 | channel_flags |= IEEE80211_CHAN_2GHZ; |
267 | put_unaligned_le16(channel_flags, pos); | ||
232 | pos += 2; | 268 | pos += 2; |
233 | 269 | ||
234 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ | 270 | /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ |
@@ -242,9 +278,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
242 | 278 | ||
243 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ | 279 | /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ |
244 | 280 | ||
245 | /* IEEE80211_RADIOTAP_ANTENNA */ | 281 | if (!status->chains) { |
246 | *pos = status->antenna; | 282 | /* IEEE80211_RADIOTAP_ANTENNA */ |
247 | pos++; | 283 | *pos = status->antenna; |
284 | pos++; | ||
285 | } | ||
248 | 286 | ||
249 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ | 287 | /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ |
250 | 288 | ||
@@ -341,6 +379,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
341 | pos += 2; | 379 | pos += 2; |
342 | } | 380 | } |
343 | 381 | ||
382 | for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { | ||
383 | *pos++ = status->chain_signal[chain]; | ||
384 | *pos++ = chain; | ||
385 | } | ||
386 | |||
344 | if (status->vendor_radiotap_len) { | 387 | if (status->vendor_radiotap_len) { |
345 | /* ensure 2 byte alignment for the vendor field as required */ | 388 | /* ensure 2 byte alignment for the vendor field as required */ |
346 | if ((pos - (u8 *)rthdr) & 1) | 389 | if ((pos - (u8 *)rthdr) & 1) |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 1b122a79b0d8..08afe74b98f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -66,6 +66,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
66 | struct cfg80211_bss *cbss; | 66 | struct cfg80211_bss *cbss; |
67 | struct ieee80211_bss *bss; | 67 | struct ieee80211_bss *bss; |
68 | int clen, srlen; | 68 | int clen, srlen; |
69 | enum nl80211_bss_scan_width scan_width; | ||
69 | s32 signal = 0; | 70 | s32 signal = 0; |
70 | 71 | ||
71 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 72 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
@@ -73,8 +74,15 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
73 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 74 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
74 | signal = (rx_status->signal * 100) / local->hw.max_signal; | 75 | signal = (rx_status->signal * 100) / local->hw.max_signal; |
75 | 76 | ||
76 | cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, | 77 | scan_width = NL80211_BSS_CHAN_WIDTH_20; |
77 | mgmt, len, signal, GFP_ATOMIC); | 78 | if (rx_status->flag & RX_FLAG_5MHZ) |
79 | scan_width = NL80211_BSS_CHAN_WIDTH_5; | ||
80 | if (rx_status->flag & RX_FLAG_10MHZ) | ||
81 | scan_width = NL80211_BSS_CHAN_WIDTH_10; | ||
82 | |||
83 | cbss = cfg80211_inform_bss_width_frame(local->hw.wiphy, channel, | ||
84 | scan_width, mgmt, len, signal, | ||
85 | GFP_ATOMIC); | ||
78 | if (!cbss) | 86 | if (!cbss) |
79 | return NULL; | 87 | return NULL; |
80 | 88 | ||
@@ -204,10 +212,29 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
204 | ieee80211_rx_bss_put(local, bss); | 212 | ieee80211_rx_bss_put(local, bss); |
205 | } | 213 | } |
206 | 214 | ||
215 | static void | ||
216 | ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef, | ||
217 | enum nl80211_bss_scan_width scan_width) | ||
218 | { | ||
219 | memset(chandef, 0, sizeof(*chandef)); | ||
220 | switch (scan_width) { | ||
221 | case NL80211_BSS_CHAN_WIDTH_5: | ||
222 | chandef->width = NL80211_CHAN_WIDTH_5; | ||
223 | break; | ||
224 | case NL80211_BSS_CHAN_WIDTH_10: | ||
225 | chandef->width = NL80211_CHAN_WIDTH_10; | ||
226 | break; | ||
227 | default: | ||
228 | chandef->width = NL80211_CHAN_WIDTH_20_NOHT; | ||
229 | break; | ||
230 | } | ||
231 | } | ||
232 | |||
207 | /* return false if no more work */ | 233 | /* return false if no more work */ |
208 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | 234 | static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) |
209 | { | 235 | { |
210 | struct cfg80211_scan_request *req = local->scan_req; | 236 | struct cfg80211_scan_request *req = local->scan_req; |
237 | struct cfg80211_chan_def chandef; | ||
211 | enum ieee80211_band band; | 238 | enum ieee80211_band band; |
212 | int i, ielen, n_chans; | 239 | int i, ielen, n_chans; |
213 | 240 | ||
@@ -229,11 +256,12 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
229 | } while (!n_chans); | 256 | } while (!n_chans); |
230 | 257 | ||
231 | local->hw_scan_req->n_channels = n_chans; | 258 | local->hw_scan_req->n_channels = n_chans; |
259 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | ||
232 | 260 | ||
233 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, | 261 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, |
234 | local->hw_scan_ies_bufsize, | 262 | local->hw_scan_ies_bufsize, |
235 | req->ie, req->ie_len, band, | 263 | req->ie, req->ie_len, band, |
236 | req->rates[band], 0); | 264 | req->rates[band], &chandef); |
237 | local->hw_scan_req->ie_len = ielen; | 265 | local->hw_scan_req->ie_len = ielen; |
238 | local->hw_scan_req->no_cck = req->no_cck; | 266 | local->hw_scan_req->no_cck = req->no_cck; |
239 | 267 | ||
@@ -280,7 +308,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
280 | rcu_assign_pointer(local->scan_sdata, NULL); | 308 | rcu_assign_pointer(local->scan_sdata, NULL); |
281 | 309 | ||
282 | local->scanning = 0; | 310 | local->scanning = 0; |
283 | local->scan_channel = NULL; | 311 | local->scan_chandef.chan = NULL; |
284 | 312 | ||
285 | /* Set power back to normal operating levels. */ | 313 | /* Set power back to normal operating levels. */ |
286 | ieee80211_hw_config(local, 0); | 314 | ieee80211_hw_config(local, 0); |
@@ -615,11 +643,34 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | |||
615 | { | 643 | { |
616 | int skip; | 644 | int skip; |
617 | struct ieee80211_channel *chan; | 645 | struct ieee80211_channel *chan; |
646 | enum nl80211_bss_scan_width oper_scan_width; | ||
618 | 647 | ||
619 | skip = 0; | 648 | skip = 0; |
620 | chan = local->scan_req->channels[local->scan_channel_idx]; | 649 | chan = local->scan_req->channels[local->scan_channel_idx]; |
621 | 650 | ||
622 | local->scan_channel = chan; | 651 | local->scan_chandef.chan = chan; |
652 | local->scan_chandef.center_freq1 = chan->center_freq; | ||
653 | local->scan_chandef.center_freq2 = 0; | ||
654 | switch (local->scan_req->scan_width) { | ||
655 | case NL80211_BSS_CHAN_WIDTH_5: | ||
656 | local->scan_chandef.width = NL80211_CHAN_WIDTH_5; | ||
657 | break; | ||
658 | case NL80211_BSS_CHAN_WIDTH_10: | ||
659 | local->scan_chandef.width = NL80211_CHAN_WIDTH_10; | ||
660 | break; | ||
661 | case NL80211_BSS_CHAN_WIDTH_20: | ||
662 | /* If scanning on oper channel, use whatever channel-type | ||
663 | * is currently in use. | ||
664 | */ | ||
665 | oper_scan_width = cfg80211_chandef_to_scan_width( | ||
666 | &local->_oper_chandef); | ||
667 | if (chan == local->_oper_chandef.chan && | ||
668 | oper_scan_width == local->scan_req->scan_width) | ||
669 | local->scan_chandef = local->_oper_chandef; | ||
670 | else | ||
671 | local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT; | ||
672 | break; | ||
673 | } | ||
623 | 674 | ||
624 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) | 675 | if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL)) |
625 | skip = 1; | 676 | skip = 1; |
@@ -659,7 +710,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, | |||
659 | unsigned long *next_delay) | 710 | unsigned long *next_delay) |
660 | { | 711 | { |
661 | /* switch back to the operating channel */ | 712 | /* switch back to the operating channel */ |
662 | local->scan_channel = NULL; | 713 | local->scan_chandef.chan = NULL; |
663 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 714 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
664 | 715 | ||
665 | /* disable PS */ | 716 | /* disable PS */ |
@@ -801,7 +852,8 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |||
801 | 852 | ||
802 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | 853 | int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, |
803 | const u8 *ssid, u8 ssid_len, | 854 | const u8 *ssid, u8 ssid_len, |
804 | struct ieee80211_channel *chan) | 855 | struct ieee80211_channel *chan, |
856 | enum nl80211_bss_scan_width scan_width) | ||
805 | { | 857 | { |
806 | struct ieee80211_local *local = sdata->local; | 858 | struct ieee80211_local *local = sdata->local; |
807 | int ret = -EBUSY; | 859 | int ret = -EBUSY; |
@@ -851,6 +903,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, | |||
851 | 903 | ||
852 | local->int_scan_req->ssids = &local->scan_ssid; | 904 | local->int_scan_req->ssids = &local->scan_ssid; |
853 | local->int_scan_req->n_ssids = 1; | 905 | local->int_scan_req->n_ssids = 1; |
906 | local->int_scan_req->scan_width = scan_width; | ||
854 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); | 907 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); |
855 | local->int_scan_req->ssids[0].ssid_len = ssid_len; | 908 | local->int_scan_req->ssids[0].ssid_len = ssid_len; |
856 | 909 | ||
@@ -912,6 +965,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
912 | { | 965 | { |
913 | struct ieee80211_local *local = sdata->local; | 966 | struct ieee80211_local *local = sdata->local; |
914 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; | 967 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; |
968 | struct cfg80211_chan_def chandef; | ||
915 | int ret, i, iebufsz; | 969 | int ret, i, iebufsz; |
916 | 970 | ||
917 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + | 971 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + |
@@ -939,10 +993,12 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
939 | goto out_free; | 993 | goto out_free; |
940 | } | 994 | } |
941 | 995 | ||
996 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | ||
997 | |||
942 | sched_scan_ies.len[i] = | 998 | sched_scan_ies.len[i] = |
943 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], | 999 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], |
944 | iebufsz, req->ie, req->ie_len, | 1000 | iebufsz, req->ie, req->ie_len, |
945 | i, (u32) -1, 0); | 1001 | i, (u32) -1, &chandef); |
946 | } | 1002 | } |
947 | 1003 | ||
948 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1004 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 43439203f4e4..6ad4c14385ef 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -252,9 +252,10 @@ static int ieee80211_tx_radiotap_len(struct ieee80211_tx_info *info) | |||
252 | return len; | 252 | return len; |
253 | } | 253 | } |
254 | 254 | ||
255 | static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | 255 | static void |
256 | *sband, struct sk_buff *skb, | 256 | ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band *sband, |
257 | int retry_count, int rtap_len) | 257 | struct sk_buff *skb, int retry_count, |
258 | int rtap_len, int shift) | ||
258 | { | 259 | { |
259 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 260 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
260 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 261 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -280,8 +281,11 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band | |||
280 | /* IEEE80211_RADIOTAP_RATE */ | 281 | /* IEEE80211_RADIOTAP_RATE */ |
281 | if (info->status.rates[0].idx >= 0 && | 282 | if (info->status.rates[0].idx >= 0 && |
282 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { | 283 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) { |
284 | u16 rate; | ||
285 | |||
283 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | 286 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); |
284 | *pos = sband->bitrates[info->status.rates[0].idx].bitrate / 5; | 287 | rate = sband->bitrates[info->status.rates[0].idx].bitrate; |
288 | *pos = DIV_ROUND_UP(rate, 5 * (1 << shift)); | ||
285 | /* padding for tx flags */ | 289 | /* padding for tx flags */ |
286 | pos += 2; | 290 | pos += 2; |
287 | } | 291 | } |
@@ -424,6 +428,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
424 | bool acked; | 428 | bool acked; |
425 | struct ieee80211_bar *bar; | 429 | struct ieee80211_bar *bar; |
426 | int rtap_len; | 430 | int rtap_len; |
431 | int shift = 0; | ||
427 | 432 | ||
428 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 433 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
429 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 434 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
@@ -458,6 +463,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
458 | if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) | 463 | if (!ether_addr_equal(hdr->addr2, sta->sdata->vif.addr)) |
459 | continue; | 464 | continue; |
460 | 465 | ||
466 | shift = ieee80211_vif_get_shift(&sta->sdata->vif); | ||
467 | |||
461 | if (info->flags & IEEE80211_TX_STATUS_EOSP) | 468 | if (info->flags & IEEE80211_TX_STATUS_EOSP) |
462 | clear_sta_flag(sta, WLAN_STA_SP); | 469 | clear_sta_flag(sta, WLAN_STA_SP); |
463 | 470 | ||
@@ -624,7 +631,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
624 | dev_kfree_skb(skb); | 631 | dev_kfree_skb(skb); |
625 | return; | 632 | return; |
626 | } | 633 | } |
627 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len); | 634 | ieee80211_add_tx_radiotap_header(sband, skb, retry_count, rtap_len, |
635 | shift); | ||
628 | 636 | ||
629 | /* XXX: is this sufficient for BPF? */ | 637 | /* XXX: is this sufficient for BPF? */ |
630 | skb_set_mac_header(skb, 0); | 638 | skb_set_mac_header(skb, 0); |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4105d0ca963e..be4d3caf4879 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -40,12 +40,22 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
40 | struct sk_buff *skb, int group_addr, | 40 | struct sk_buff *skb, int group_addr, |
41 | int next_frag_len) | 41 | int next_frag_len) |
42 | { | 42 | { |
43 | int rate, mrate, erp, dur, i; | 43 | int rate, mrate, erp, dur, i, shift = 0; |
44 | struct ieee80211_rate *txrate; | 44 | struct ieee80211_rate *txrate; |
45 | struct ieee80211_local *local = tx->local; | 45 | struct ieee80211_local *local = tx->local; |
46 | struct ieee80211_supported_band *sband; | 46 | struct ieee80211_supported_band *sband; |
47 | struct ieee80211_hdr *hdr; | 47 | struct ieee80211_hdr *hdr; |
48 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 48 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
49 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
50 | u32 rate_flags = 0; | ||
51 | |||
52 | rcu_read_lock(); | ||
53 | chanctx_conf = rcu_dereference(tx->sdata->vif.chanctx_conf); | ||
54 | if (chanctx_conf) { | ||
55 | shift = ieee80211_chandef_get_shift(&chanctx_conf->def); | ||
56 | rate_flags = ieee80211_chandef_rate_flags(&chanctx_conf->def); | ||
57 | } | ||
58 | rcu_read_unlock(); | ||
49 | 59 | ||
50 | /* assume HW handles this */ | 60 | /* assume HW handles this */ |
51 | if (tx->rate.flags & IEEE80211_TX_RC_MCS) | 61 | if (tx->rate.flags & IEEE80211_TX_RC_MCS) |
@@ -122,8 +132,11 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
122 | if (r->bitrate > txrate->bitrate) | 132 | if (r->bitrate > txrate->bitrate) |
123 | break; | 133 | break; |
124 | 134 | ||
135 | if ((rate_flags & r->flags) != rate_flags) | ||
136 | continue; | ||
137 | |||
125 | if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) | 138 | if (tx->sdata->vif.bss_conf.basic_rates & BIT(i)) |
126 | rate = r->bitrate; | 139 | rate = DIV_ROUND_UP(r->bitrate, 1 << shift); |
127 | 140 | ||
128 | switch (sband->band) { | 141 | switch (sband->band) { |
129 | case IEEE80211_BAND_2GHZ: { | 142 | case IEEE80211_BAND_2GHZ: { |
@@ -150,7 +163,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
150 | if (rate == -1) { | 163 | if (rate == -1) { |
151 | /* No matching basic rate found; use highest suitable mandatory | 164 | /* No matching basic rate found; use highest suitable mandatory |
152 | * PHY rate */ | 165 | * PHY rate */ |
153 | rate = mrate; | 166 | rate = DIV_ROUND_UP(mrate, 1 << shift); |
154 | } | 167 | } |
155 | 168 | ||
156 | /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ | 169 | /* Don't calculate ACKs for QoS Frames with NoAck Policy set */ |
@@ -162,7 +175,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
162 | * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up | 175 | * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up |
163 | * to closest integer */ | 176 | * to closest integer */ |
164 | dur = ieee80211_frame_duration(sband->band, 10, rate, erp, | 177 | dur = ieee80211_frame_duration(sband->band, 10, rate, erp, |
165 | tx->sdata->vif.bss_conf.use_short_preamble); | 178 | tx->sdata->vif.bss_conf.use_short_preamble, |
179 | shift); | ||
166 | 180 | ||
167 | if (next_frag_len) { | 181 | if (next_frag_len) { |
168 | /* Frame is fragmented: duration increases with time needed to | 182 | /* Frame is fragmented: duration increases with time needed to |
@@ -171,7 +185,8 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
171 | /* next fragment */ | 185 | /* next fragment */ |
172 | dur += ieee80211_frame_duration(sband->band, next_frag_len, | 186 | dur += ieee80211_frame_duration(sband->band, next_frag_len, |
173 | txrate->bitrate, erp, | 187 | txrate->bitrate, erp, |
174 | tx->sdata->vif.bss_conf.use_short_preamble); | 188 | tx->sdata->vif.bss_conf.use_short_preamble, |
189 | shift); | ||
175 | } | 190 | } |
176 | 191 | ||
177 | return cpu_to_le16(dur); | 192 | return cpu_to_le16(dur); |
@@ -1257,6 +1272,10 @@ static bool __ieee80211_tx(struct ieee80211_local *local, | |||
1257 | 1272 | ||
1258 | switch (sdata->vif.type) { | 1273 | switch (sdata->vif.type) { |
1259 | case NL80211_IFTYPE_MONITOR: | 1274 | case NL80211_IFTYPE_MONITOR: |
1275 | if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) { | ||
1276 | vif = &sdata->vif; | ||
1277 | break; | ||
1278 | } | ||
1260 | sdata = rcu_dereference(local->monitor_sdata); | 1279 | sdata = rcu_dereference(local->monitor_sdata); |
1261 | if (sdata) { | 1280 | if (sdata) { |
1262 | vif = &sdata->vif; | 1281 | vif = &sdata->vif; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 22654452a561..d23c5a705a68 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -107,7 +107,8 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) | |||
107 | } | 107 | } |
108 | 108 | ||
109 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 109 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
110 | int rate, int erp, int short_preamble) | 110 | int rate, int erp, int short_preamble, |
111 | int shift) | ||
111 | { | 112 | { |
112 | int dur; | 113 | int dur; |
113 | 114 | ||
@@ -118,6 +119,9 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | |||
118 | * | 119 | * |
119 | * rate is in 100 kbps, so divident is multiplied by 10 in the | 120 | * rate is in 100 kbps, so divident is multiplied by 10 in the |
120 | * DIV_ROUND_UP() operations. | 121 | * DIV_ROUND_UP() operations. |
122 | * | ||
123 | * shift may be 2 for 5 MHz channels or 1 for 10 MHz channels, and | ||
124 | * is assumed to be 0 otherwise. | ||
121 | */ | 125 | */ |
122 | 126 | ||
123 | if (band == IEEE80211_BAND_5GHZ || erp) { | 127 | if (band == IEEE80211_BAND_5GHZ || erp) { |
@@ -130,13 +134,23 @@ int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | |||
130 | * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext | 134 | * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext |
131 | * | 135 | * |
132 | * T_SYM = 4 usec | 136 | * T_SYM = 4 usec |
133 | * 802.11a - 17.5.2: aSIFSTime = 16 usec | 137 | * 802.11a - 18.5.2: aSIFSTime = 16 usec |
134 | * 802.11g - 19.8.4: aSIFSTime = 10 usec + | 138 | * 802.11g - 19.8.4: aSIFSTime = 10 usec + |
135 | * signal ext = 6 usec | 139 | * signal ext = 6 usec |
136 | */ | 140 | */ |
137 | dur = 16; /* SIFS + signal ext */ | 141 | dur = 16; /* SIFS + signal ext */ |
138 | dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */ | 142 | dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */ |
139 | dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */ | 143 | dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */ |
144 | |||
145 | /* IEEE 802.11-2012 18.3.2.4: all values above are: | ||
146 | * * times 4 for 5 MHz | ||
147 | * * times 2 for 10 MHz | ||
148 | */ | ||
149 | dur *= 1 << shift; | ||
150 | |||
151 | /* rates should already consider the channel bandwidth, | ||
152 | * don't apply divisor again. | ||
153 | */ | ||
140 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, | 154 | dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10, |
141 | 4 * rate); /* T_SYM x N_SYM */ | 155 | 4 * rate); /* T_SYM x N_SYM */ |
142 | } else { | 156 | } else { |
@@ -168,7 +182,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
168 | { | 182 | { |
169 | struct ieee80211_sub_if_data *sdata; | 183 | struct ieee80211_sub_if_data *sdata; |
170 | u16 dur; | 184 | u16 dur; |
171 | int erp; | 185 | int erp, shift = 0; |
172 | bool short_preamble = false; | 186 | bool short_preamble = false; |
173 | 187 | ||
174 | erp = 0; | 188 | erp = 0; |
@@ -177,10 +191,11 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
177 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 191 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
178 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 192 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
179 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 193 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
194 | shift = ieee80211_vif_get_shift(vif); | ||
180 | } | 195 | } |
181 | 196 | ||
182 | dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp, | 197 | dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp, |
183 | short_preamble); | 198 | short_preamble, shift); |
184 | 199 | ||
185 | return cpu_to_le16(dur); | 200 | return cpu_to_le16(dur); |
186 | } | 201 | } |
@@ -194,7 +209,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
194 | struct ieee80211_rate *rate; | 209 | struct ieee80211_rate *rate; |
195 | struct ieee80211_sub_if_data *sdata; | 210 | struct ieee80211_sub_if_data *sdata; |
196 | bool short_preamble; | 211 | bool short_preamble; |
197 | int erp; | 212 | int erp, shift = 0, bitrate; |
198 | u16 dur; | 213 | u16 dur; |
199 | struct ieee80211_supported_band *sband; | 214 | struct ieee80211_supported_band *sband; |
200 | 215 | ||
@@ -210,17 +225,20 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
210 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 225 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
211 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 226 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
212 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 227 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
228 | shift = ieee80211_vif_get_shift(vif); | ||
213 | } | 229 | } |
214 | 230 | ||
231 | bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift); | ||
232 | |||
215 | /* CTS duration */ | 233 | /* CTS duration */ |
216 | dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 234 | dur = ieee80211_frame_duration(sband->band, 10, bitrate, |
217 | erp, short_preamble); | 235 | erp, short_preamble, shift); |
218 | /* Data frame duration */ | 236 | /* Data frame duration */ |
219 | dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, | 237 | dur += ieee80211_frame_duration(sband->band, frame_len, bitrate, |
220 | erp, short_preamble); | 238 | erp, short_preamble, shift); |
221 | /* ACK duration */ | 239 | /* ACK duration */ |
222 | dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 240 | dur += ieee80211_frame_duration(sband->band, 10, bitrate, |
223 | erp, short_preamble); | 241 | erp, short_preamble, shift); |
224 | 242 | ||
225 | return cpu_to_le16(dur); | 243 | return cpu_to_le16(dur); |
226 | } | 244 | } |
@@ -235,7 +253,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
235 | struct ieee80211_rate *rate; | 253 | struct ieee80211_rate *rate; |
236 | struct ieee80211_sub_if_data *sdata; | 254 | struct ieee80211_sub_if_data *sdata; |
237 | bool short_preamble; | 255 | bool short_preamble; |
238 | int erp; | 256 | int erp, shift = 0, bitrate; |
239 | u16 dur; | 257 | u16 dur; |
240 | struct ieee80211_supported_band *sband; | 258 | struct ieee80211_supported_band *sband; |
241 | 259 | ||
@@ -250,15 +268,18 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
250 | short_preamble = sdata->vif.bss_conf.use_short_preamble; | 268 | short_preamble = sdata->vif.bss_conf.use_short_preamble; |
251 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 269 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) |
252 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 270 | erp = rate->flags & IEEE80211_RATE_ERP_G; |
271 | shift = ieee80211_vif_get_shift(vif); | ||
253 | } | 272 | } |
254 | 273 | ||
274 | bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift); | ||
275 | |||
255 | /* Data frame duration */ | 276 | /* Data frame duration */ |
256 | dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, | 277 | dur = ieee80211_frame_duration(sband->band, frame_len, bitrate, |
257 | erp, short_preamble); | 278 | erp, short_preamble, shift); |
258 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { | 279 | if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { |
259 | /* ACK duration */ | 280 | /* ACK duration */ |
260 | dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, | 281 | dur += ieee80211_frame_duration(sband->band, 10, bitrate, |
261 | erp, short_preamble); | 282 | erp, short_preamble, shift); |
262 | } | 283 | } |
263 | 284 | ||
264 | return cpu_to_le16(dur); | 285 | return cpu_to_le16(dur); |
@@ -1052,32 +1073,6 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
1052 | } | 1073 | } |
1053 | } | 1074 | } |
1054 | 1075 | ||
1055 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | ||
1056 | const size_t supp_rates_len, | ||
1057 | const u8 *supp_rates) | ||
1058 | { | ||
1059 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
1060 | int i, have_higher_than_11mbit = 0; | ||
1061 | |||
1062 | /* cf. IEEE 802.11 9.2.12 */ | ||
1063 | for (i = 0; i < supp_rates_len; i++) | ||
1064 | if ((supp_rates[i] & 0x7f) * 5 > 110) | ||
1065 | have_higher_than_11mbit = 1; | ||
1066 | |||
1067 | rcu_read_lock(); | ||
1068 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
1069 | |||
1070 | if (chanctx_conf && | ||
1071 | chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ && | ||
1072 | have_higher_than_11mbit) | ||
1073 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
1074 | else | ||
1075 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
1076 | rcu_read_unlock(); | ||
1077 | |||
1078 | ieee80211_set_wmm_default(sdata, true); | ||
1079 | } | ||
1080 | |||
1081 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | 1076 | void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, |
1082 | u16 transaction, u16 auth_alg, u16 status, | 1077 | u16 transaction, u16 auth_alg, u16 status, |
1083 | const u8 *extra, size_t extra_len, const u8 *da, | 1078 | const u8 *extra, size_t extra_len, const u8 *da, |
@@ -1162,7 +1157,7 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1162 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1157 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1163 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1158 | size_t buffer_len, const u8 *ie, size_t ie_len, |
1164 | enum ieee80211_band band, u32 rate_mask, | 1159 | enum ieee80211_band band, u32 rate_mask, |
1165 | u8 channel) | 1160 | struct cfg80211_chan_def *chandef) |
1166 | { | 1161 | { |
1167 | struct ieee80211_supported_band *sband; | 1162 | struct ieee80211_supported_band *sband; |
1168 | u8 *pos = buffer, *end = buffer + buffer_len; | 1163 | u8 *pos = buffer, *end = buffer + buffer_len; |
@@ -1171,16 +1166,26 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1171 | u8 rates[32]; | 1166 | u8 rates[32]; |
1172 | int num_rates; | 1167 | int num_rates; |
1173 | int ext_rates_len; | 1168 | int ext_rates_len; |
1169 | int shift; | ||
1170 | u32 rate_flags; | ||
1174 | 1171 | ||
1175 | sband = local->hw.wiphy->bands[band]; | 1172 | sband = local->hw.wiphy->bands[band]; |
1176 | if (WARN_ON_ONCE(!sband)) | 1173 | if (WARN_ON_ONCE(!sband)) |
1177 | return 0; | 1174 | return 0; |
1178 | 1175 | ||
1176 | rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
1177 | shift = ieee80211_chandef_get_shift(chandef); | ||
1178 | |||
1179 | num_rates = 0; | 1179 | num_rates = 0; |
1180 | for (i = 0; i < sband->n_bitrates; i++) { | 1180 | for (i = 0; i < sband->n_bitrates; i++) { |
1181 | if ((BIT(i) & rate_mask) == 0) | 1181 | if ((BIT(i) & rate_mask) == 0) |
1182 | continue; /* skip rate */ | 1182 | continue; /* skip rate */ |
1183 | rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5); | 1183 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
1184 | continue; | ||
1185 | |||
1186 | rates[num_rates++] = | ||
1187 | (u8) DIV_ROUND_UP(sband->bitrates[i].bitrate, | ||
1188 | (1 << shift) * 5); | ||
1184 | } | 1189 | } |
1185 | 1190 | ||
1186 | supp_rates_len = min_t(int, num_rates, 8); | 1191 | supp_rates_len = min_t(int, num_rates, 8); |
@@ -1220,12 +1225,13 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1220 | pos += ext_rates_len; | 1225 | pos += ext_rates_len; |
1221 | } | 1226 | } |
1222 | 1227 | ||
1223 | if (channel && sband->band == IEEE80211_BAND_2GHZ) { | 1228 | if (chandef->chan && sband->band == IEEE80211_BAND_2GHZ) { |
1224 | if (end - pos < 3) | 1229 | if (end - pos < 3) |
1225 | goto out_err; | 1230 | goto out_err; |
1226 | *pos++ = WLAN_EID_DS_PARAMS; | 1231 | *pos++ = WLAN_EID_DS_PARAMS; |
1227 | *pos++ = 1; | 1232 | *pos++ = 1; |
1228 | *pos++ = channel; | 1233 | *pos++ = ieee80211_frequency_to_channel( |
1234 | chandef->chan->center_freq); | ||
1229 | } | 1235 | } |
1230 | 1236 | ||
1231 | /* insert custom IEs that go before HT */ | 1237 | /* insert custom IEs that go before HT */ |
@@ -1290,9 +1296,9 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1290 | bool directed) | 1296 | bool directed) |
1291 | { | 1297 | { |
1292 | struct ieee80211_local *local = sdata->local; | 1298 | struct ieee80211_local *local = sdata->local; |
1299 | struct cfg80211_chan_def chandef; | ||
1293 | struct sk_buff *skb; | 1300 | struct sk_buff *skb; |
1294 | struct ieee80211_mgmt *mgmt; | 1301 | struct ieee80211_mgmt *mgmt; |
1295 | u8 chan_no; | ||
1296 | int ies_len; | 1302 | int ies_len; |
1297 | 1303 | ||
1298 | /* | 1304 | /* |
@@ -1300,10 +1306,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1300 | * in order to maximize the chance that we get a response. Some | 1306 | * in order to maximize the chance that we get a response. Some |
1301 | * badly-behaved APs don't respond when this parameter is included. | 1307 | * badly-behaved APs don't respond when this parameter is included. |
1302 | */ | 1308 | */ |
1309 | chandef.width = sdata->vif.bss_conf.chandef.width; | ||
1303 | if (directed) | 1310 | if (directed) |
1304 | chan_no = 0; | 1311 | chandef.chan = NULL; |
1305 | else | 1312 | else |
1306 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); | 1313 | chandef.chan = chan; |
1307 | 1314 | ||
1308 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1315 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1309 | ssid, ssid_len, 100 + ie_len); | 1316 | ssid, ssid_len, 100 + ie_len); |
@@ -1313,7 +1320,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1313 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | 1320 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), |
1314 | skb_tailroom(skb), | 1321 | skb_tailroom(skb), |
1315 | ie, ie_len, chan->band, | 1322 | ie, ie_len, chan->band, |
1316 | ratemask, chan_no); | 1323 | ratemask, &chandef); |
1317 | skb_put(skb, ies_len); | 1324 | skb_put(skb, ies_len); |
1318 | 1325 | ||
1319 | if (dst) { | 1326 | if (dst) { |
@@ -1347,16 +1354,19 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
1347 | } | 1354 | } |
1348 | } | 1355 | } |
1349 | 1356 | ||
1350 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1357 | u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, |
1351 | struct ieee802_11_elems *elems, | 1358 | struct ieee802_11_elems *elems, |
1352 | enum ieee80211_band band, u32 *basic_rates) | 1359 | enum ieee80211_band band, u32 *basic_rates) |
1353 | { | 1360 | { |
1354 | struct ieee80211_supported_band *sband; | 1361 | struct ieee80211_supported_band *sband; |
1355 | struct ieee80211_rate *bitrates; | 1362 | struct ieee80211_rate *bitrates; |
1356 | size_t num_rates; | 1363 | size_t num_rates; |
1357 | u32 supp_rates; | 1364 | u32 supp_rates, rate_flags; |
1358 | int i, j; | 1365 | int i, j, shift; |
1359 | sband = local->hw.wiphy->bands[band]; | 1366 | sband = sdata->local->hw.wiphy->bands[band]; |
1367 | |||
1368 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
1369 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
1360 | 1370 | ||
1361 | if (WARN_ON(!sband)) | 1371 | if (WARN_ON(!sband)) |
1362 | return 1; | 1372 | return 1; |
@@ -1381,7 +1391,15 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
1381 | continue; | 1391 | continue; |
1382 | 1392 | ||
1383 | for (j = 0; j < num_rates; j++) { | 1393 | for (j = 0; j < num_rates; j++) { |
1384 | if (bitrates[j].bitrate == own_rate) { | 1394 | int brate; |
1395 | if ((rate_flags & sband->bitrates[j].flags) | ||
1396 | != rate_flags) | ||
1397 | continue; | ||
1398 | |||
1399 | brate = DIV_ROUND_UP(sband->bitrates[j].bitrate, | ||
1400 | 1 << shift); | ||
1401 | |||
1402 | if (brate == own_rate) { | ||
1385 | supp_rates |= BIT(j); | 1403 | supp_rates |= BIT(j); |
1386 | if (basic_rates && is_basic) | 1404 | if (basic_rates && is_basic) |
1387 | *basic_rates |= BIT(j); | 1405 | *basic_rates |= BIT(j); |
@@ -2004,18 +2022,56 @@ void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | |||
2004 | cfg80211_chandef_create(chandef, control_chan, channel_type); | 2022 | cfg80211_chandef_create(chandef, control_chan, channel_type); |
2005 | } | 2023 | } |
2006 | 2024 | ||
2025 | int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef, | ||
2026 | const struct ieee80211_supported_band *sband, | ||
2027 | const u8 *srates, int srates_len, u32 *rates) | ||
2028 | { | ||
2029 | u32 rate_flags = ieee80211_chandef_rate_flags(chandef); | ||
2030 | int shift = ieee80211_chandef_get_shift(chandef); | ||
2031 | struct ieee80211_rate *br; | ||
2032 | int brate, rate, i, j, count = 0; | ||
2033 | |||
2034 | *rates = 0; | ||
2035 | |||
2036 | for (i = 0; i < srates_len; i++) { | ||
2037 | rate = srates[i] & 0x7f; | ||
2038 | |||
2039 | for (j = 0; j < sband->n_bitrates; j++) { | ||
2040 | br = &sband->bitrates[j]; | ||
2041 | if ((rate_flags & br->flags) != rate_flags) | ||
2042 | continue; | ||
2043 | |||
2044 | brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5); | ||
2045 | if (brate == rate) { | ||
2046 | *rates |= BIT(j); | ||
2047 | count++; | ||
2048 | break; | ||
2049 | } | ||
2050 | } | ||
2051 | } | ||
2052 | return count; | ||
2053 | } | ||
2054 | |||
2007 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 2055 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
2008 | struct sk_buff *skb, bool need_basic, | 2056 | struct sk_buff *skb, bool need_basic, |
2009 | enum ieee80211_band band) | 2057 | enum ieee80211_band band) |
2010 | { | 2058 | { |
2011 | struct ieee80211_local *local = sdata->local; | 2059 | struct ieee80211_local *local = sdata->local; |
2012 | struct ieee80211_supported_band *sband; | 2060 | struct ieee80211_supported_band *sband; |
2013 | int rate; | 2061 | int rate, shift; |
2014 | u8 i, rates, *pos; | 2062 | u8 i, rates, *pos; |
2015 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2063 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
2064 | u32 rate_flags; | ||
2016 | 2065 | ||
2066 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
2067 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
2017 | sband = local->hw.wiphy->bands[band]; | 2068 | sband = local->hw.wiphy->bands[band]; |
2018 | rates = sband->n_bitrates; | 2069 | rates = 0; |
2070 | for (i = 0; i < sband->n_bitrates; i++) { | ||
2071 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
2072 | continue; | ||
2073 | rates++; | ||
2074 | } | ||
2019 | if (rates > 8) | 2075 | if (rates > 8) |
2020 | rates = 8; | 2076 | rates = 8; |
2021 | 2077 | ||
@@ -2027,10 +2083,15 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
2027 | *pos++ = rates; | 2083 | *pos++ = rates; |
2028 | for (i = 0; i < rates; i++) { | 2084 | for (i = 0; i < rates; i++) { |
2029 | u8 basic = 0; | 2085 | u8 basic = 0; |
2086 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
2087 | continue; | ||
2088 | |||
2030 | if (need_basic && basic_rates & BIT(i)) | 2089 | if (need_basic && basic_rates & BIT(i)) |
2031 | basic = 0x80; | 2090 | basic = 0x80; |
2032 | rate = sband->bitrates[i].bitrate; | 2091 | rate = sband->bitrates[i].bitrate; |
2033 | *pos++ = basic | (u8) (rate / 5); | 2092 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
2093 | 5 * (1 << shift)); | ||
2094 | *pos++ = basic | (u8) rate; | ||
2034 | } | 2095 | } |
2035 | 2096 | ||
2036 | return 0; | 2097 | return 0; |
@@ -2042,12 +2103,22 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
2042 | { | 2103 | { |
2043 | struct ieee80211_local *local = sdata->local; | 2104 | struct ieee80211_local *local = sdata->local; |
2044 | struct ieee80211_supported_band *sband; | 2105 | struct ieee80211_supported_band *sband; |
2045 | int rate; | 2106 | int rate, skip, shift; |
2046 | u8 i, exrates, *pos; | 2107 | u8 i, exrates, *pos; |
2047 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 2108 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
2109 | u32 rate_flags; | ||
2110 | |||
2111 | rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef); | ||
2112 | shift = ieee80211_vif_get_shift(&sdata->vif); | ||
2048 | 2113 | ||
2049 | sband = local->hw.wiphy->bands[band]; | 2114 | sband = local->hw.wiphy->bands[band]; |
2050 | exrates = sband->n_bitrates; | 2115 | exrates = 0; |
2116 | for (i = 0; i < sband->n_bitrates; i++) { | ||
2117 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) | ||
2118 | continue; | ||
2119 | exrates++; | ||
2120 | } | ||
2121 | |||
2051 | if (exrates > 8) | 2122 | if (exrates > 8) |
2052 | exrates -= 8; | 2123 | exrates -= 8; |
2053 | else | 2124 | else |
@@ -2060,12 +2131,19 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
2060 | pos = skb_put(skb, exrates + 2); | 2131 | pos = skb_put(skb, exrates + 2); |
2061 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 2132 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
2062 | *pos++ = exrates; | 2133 | *pos++ = exrates; |
2134 | skip = 0; | ||
2063 | for (i = 8; i < sband->n_bitrates; i++) { | 2135 | for (i = 8; i < sband->n_bitrates; i++) { |
2064 | u8 basic = 0; | 2136 | u8 basic = 0; |
2137 | if ((rate_flags & sband->bitrates[i].flags) | ||
2138 | != rate_flags) | ||
2139 | continue; | ||
2140 | if (skip++ < 8) | ||
2141 | continue; | ||
2065 | if (need_basic && basic_rates & BIT(i)) | 2142 | if (need_basic && basic_rates & BIT(i)) |
2066 | basic = 0x80; | 2143 | basic = 0x80; |
2067 | rate = sband->bitrates[i].bitrate; | 2144 | rate = DIV_ROUND_UP(sband->bitrates[i].bitrate, |
2068 | *pos++ = basic | (u8) (rate / 5); | 2145 | 5 * (1 << shift)); |
2146 | *pos++ = basic | (u8) rate; | ||
2069 | } | 2147 | } |
2070 | } | 2148 | } |
2071 | return 0; | 2149 | return 0; |
@@ -2149,9 +2227,17 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2149 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2227 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
2150 | } else { | 2228 | } else { |
2151 | struct ieee80211_supported_band *sband; | 2229 | struct ieee80211_supported_band *sband; |
2230 | int shift = 0; | ||
2231 | int bitrate; | ||
2232 | |||
2233 | if (status->flag & RX_FLAG_10MHZ) | ||
2234 | shift = 1; | ||
2235 | if (status->flag & RX_FLAG_5MHZ) | ||
2236 | shift = 2; | ||
2152 | 2237 | ||
2153 | sband = local->hw.wiphy->bands[status->band]; | 2238 | sband = local->hw.wiphy->bands[status->band]; |
2154 | ri.legacy = sband->bitrates[status->rate_idx].bitrate; | 2239 | bitrate = sband->bitrates[status->rate_idx].bitrate; |
2240 | ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift)); | ||
2155 | } | 2241 | } |
2156 | 2242 | ||
2157 | rate = cfg80211_calculate_bitrate(&ri); | 2243 | rate = cfg80211_calculate_bitrate(&ri); |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 4f9f216665e9..389a3f2ee464 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -462,6 +462,14 @@ int wiphy_register(struct wiphy *wiphy) | |||
462 | return -EINVAL; | 462 | return -EINVAL; |
463 | #endif | 463 | #endif |
464 | 464 | ||
465 | if (WARN_ON(wiphy->coalesce && | ||
466 | (!wiphy->coalesce->n_rules || | ||
467 | !wiphy->coalesce->n_patterns) && | ||
468 | (!wiphy->coalesce->pattern_min_len || | ||
469 | wiphy->coalesce->pattern_min_len > | ||
470 | wiphy->coalesce->pattern_max_len))) | ||
471 | return -EINVAL; | ||
472 | |||
465 | if (WARN_ON(wiphy->ap_sme_capa && | 473 | if (WARN_ON(wiphy->ap_sme_capa && |
466 | !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME))) | 474 | !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME))) |
467 | return -EINVAL; | 475 | return -EINVAL; |
@@ -668,6 +676,7 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
668 | rdev_set_wakeup(rdev, false); | 676 | rdev_set_wakeup(rdev, false); |
669 | #endif | 677 | #endif |
670 | cfg80211_rdev_free_wowlan(rdev); | 678 | cfg80211_rdev_free_wowlan(rdev); |
679 | cfg80211_rdev_free_coalesce(rdev); | ||
671 | } | 680 | } |
672 | EXPORT_SYMBOL(wiphy_unregister); | 681 | EXPORT_SYMBOL(wiphy_unregister); |
673 | 682 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index a6b45bf00f33..9ad43c619c54 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -79,6 +79,8 @@ struct cfg80211_registered_device { | |||
79 | /* netlink port which started critical protocol (0 means not started) */ | 79 | /* netlink port which started critical protocol (0 means not started) */ |
80 | u32 crit_proto_nlportid; | 80 | u32 crit_proto_nlportid; |
81 | 81 | ||
82 | struct cfg80211_coalesce *coalesce; | ||
83 | |||
82 | /* must be last because of the way we do wiphy_priv(), | 84 | /* must be last because of the way we do wiphy_priv(), |
83 | * and it should at least be aligned to NETDEV_ALIGN */ | 85 | * and it should at least be aligned to NETDEV_ALIGN */ |
84 | struct wiphy wiphy __aligned(NETDEV_ALIGN); | 86 | struct wiphy wiphy __aligned(NETDEV_ALIGN); |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 30c49202ee4d..0553fd4d85ae 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
@@ -167,9 +167,12 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
167 | * basic rates | 167 | * basic rates |
168 | */ | 168 | */ |
169 | if (!setup->basic_rates) { | 169 | if (!setup->basic_rates) { |
170 | enum nl80211_bss_scan_width scan_width; | ||
170 | struct ieee80211_supported_band *sband = | 171 | struct ieee80211_supported_band *sband = |
171 | rdev->wiphy.bands[setup->chandef.chan->band]; | 172 | rdev->wiphy.bands[setup->chandef.chan->band]; |
172 | setup->basic_rates = ieee80211_mandatory_rates(sband); | 173 | scan_width = cfg80211_chandef_to_scan_width(&setup->chandef); |
174 | setup->basic_rates = ieee80211_mandatory_rates(sband, | ||
175 | scan_width); | ||
173 | } | 176 | } |
174 | 177 | ||
175 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) | 178 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef)) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 25d217d90807..160c1f7c6091 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -403,6 +403,14 @@ nl80211_wowlan_tcp_policy[NUM_NL80211_WOWLAN_TCP] = { | |||
403 | [NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 }, | 403 | [NL80211_WOWLAN_TCP_WAKE_MASK] = { .len = 1 }, |
404 | }; | 404 | }; |
405 | 405 | ||
406 | /* policy for coalesce rule attributes */ | ||
407 | static const struct nla_policy | ||
408 | nl80211_coalesce_policy[NUM_NL80211_ATTR_COALESCE_RULE] = { | ||
409 | [NL80211_ATTR_COALESCE_RULE_DELAY] = { .type = NLA_U32 }, | ||
410 | [NL80211_ATTR_COALESCE_RULE_CONDITION] = { .type = NLA_U32 }, | ||
411 | [NL80211_ATTR_COALESCE_RULE_PKT_PATTERN] = { .type = NLA_NESTED }, | ||
412 | }; | ||
413 | |||
406 | /* policy for GTK rekey offload attributes */ | 414 | /* policy for GTK rekey offload attributes */ |
407 | static const struct nla_policy | 415 | static const struct nla_policy |
408 | nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = { | 416 | nl80211_rekey_policy[NUM_NL80211_REKEY_DATA] = { |
@@ -974,7 +982,7 @@ static int nl80211_send_wowlan(struct sk_buff *msg, | |||
974 | return -ENOBUFS; | 982 | return -ENOBUFS; |
975 | 983 | ||
976 | if (dev->wiphy.wowlan->n_patterns) { | 984 | if (dev->wiphy.wowlan->n_patterns) { |
977 | struct nl80211_wowlan_pattern_support pat = { | 985 | struct nl80211_pattern_support pat = { |
978 | .max_patterns = dev->wiphy.wowlan->n_patterns, | 986 | .max_patterns = dev->wiphy.wowlan->n_patterns, |
979 | .min_pattern_len = dev->wiphy.wowlan->pattern_min_len, | 987 | .min_pattern_len = dev->wiphy.wowlan->pattern_min_len, |
980 | .max_pattern_len = dev->wiphy.wowlan->pattern_max_len, | 988 | .max_pattern_len = dev->wiphy.wowlan->pattern_max_len, |
@@ -995,6 +1003,27 @@ static int nl80211_send_wowlan(struct sk_buff *msg, | |||
995 | } | 1003 | } |
996 | #endif | 1004 | #endif |
997 | 1005 | ||
1006 | static int nl80211_send_coalesce(struct sk_buff *msg, | ||
1007 | struct cfg80211_registered_device *dev) | ||
1008 | { | ||
1009 | struct nl80211_coalesce_rule_support rule; | ||
1010 | |||
1011 | if (!dev->wiphy.coalesce) | ||
1012 | return 0; | ||
1013 | |||
1014 | rule.max_rules = dev->wiphy.coalesce->n_rules; | ||
1015 | rule.max_delay = dev->wiphy.coalesce->max_delay; | ||
1016 | rule.pat.max_patterns = dev->wiphy.coalesce->n_patterns; | ||
1017 | rule.pat.min_pattern_len = dev->wiphy.coalesce->pattern_min_len; | ||
1018 | rule.pat.max_pattern_len = dev->wiphy.coalesce->pattern_max_len; | ||
1019 | rule.pat.max_pkt_offset = dev->wiphy.coalesce->max_pkt_offset; | ||
1020 | |||
1021 | if (nla_put(msg, NL80211_ATTR_COALESCE_RULE, sizeof(rule), &rule)) | ||
1022 | return -ENOBUFS; | ||
1023 | |||
1024 | return 0; | ||
1025 | } | ||
1026 | |||
998 | static int nl80211_send_band_rateinfo(struct sk_buff *msg, | 1027 | static int nl80211_send_band_rateinfo(struct sk_buff *msg, |
999 | struct ieee80211_supported_band *sband) | 1028 | struct ieee80211_supported_band *sband) |
1000 | { | 1029 | { |
@@ -1513,6 +1542,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
1513 | dev->wiphy.vht_capa_mod_mask)) | 1542 | dev->wiphy.vht_capa_mod_mask)) |
1514 | goto nla_put_failure; | 1543 | goto nla_put_failure; |
1515 | 1544 | ||
1545 | state->split_start++; | ||
1546 | break; | ||
1547 | case 10: | ||
1548 | if (nl80211_send_coalesce(msg, dev)) | ||
1549 | goto nla_put_failure; | ||
1550 | |||
1516 | /* done */ | 1551 | /* done */ |
1517 | state->split_start = 0; | 1552 | state->split_start = 0; |
1518 | break; | 1553 | break; |
@@ -5639,6 +5674,7 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, | |||
5639 | goto nla_put_failure; | 5674 | goto nla_put_failure; |
5640 | if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) || | 5675 | if (nla_put_u16(msg, NL80211_BSS_CAPABILITY, res->capability) || |
5641 | nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) || | 5676 | nla_put_u32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq) || |
5677 | nla_put_u32(msg, NL80211_BSS_CHAN_WIDTH, res->scan_width) || | ||
5642 | nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO, | 5678 | nla_put_u32(msg, NL80211_BSS_SEEN_MS_AGO, |
5643 | jiffies_to_msecs(jiffies - intbss->ts))) | 5679 | jiffies_to_msecs(jiffies - intbss->ts))) |
5644 | goto nla_put_failure; | 5680 | goto nla_put_failure; |
@@ -6319,6 +6355,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
6319 | return -EINVAL; | 6355 | return -EINVAL; |
6320 | 6356 | ||
6321 | switch (ibss.chandef.width) { | 6357 | switch (ibss.chandef.width) { |
6358 | case NL80211_CHAN_WIDTH_5: | ||
6359 | case NL80211_CHAN_WIDTH_10: | ||
6322 | case NL80211_CHAN_WIDTH_20_NOHT: | 6360 | case NL80211_CHAN_WIDTH_20_NOHT: |
6323 | break; | 6361 | break; |
6324 | case NL80211_CHAN_WIDTH_20: | 6362 | case NL80211_CHAN_WIDTH_20: |
@@ -6346,6 +6384,19 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) | |||
6346 | return err; | 6384 | return err; |
6347 | } | 6385 | } |
6348 | 6386 | ||
6387 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) | ||
6388 | memcpy(&ibss.ht_capa_mask, | ||
6389 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]), | ||
6390 | sizeof(ibss.ht_capa_mask)); | ||
6391 | |||
6392 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { | ||
6393 | if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) | ||
6394 | return -EINVAL; | ||
6395 | memcpy(&ibss.ht_capa, | ||
6396 | nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]), | ||
6397 | sizeof(ibss.ht_capa)); | ||
6398 | } | ||
6399 | |||
6349 | if (info->attrs[NL80211_ATTR_MCAST_RATE] && | 6400 | if (info->attrs[NL80211_ATTR_MCAST_RATE] && |
6350 | !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate, | 6401 | !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate, |
6351 | nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) | 6402 | nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]))) |
@@ -7593,12 +7644,11 @@ static int nl80211_send_wowlan_patterns(struct sk_buff *msg, | |||
7593 | if (!nl_pat) | 7644 | if (!nl_pat) |
7594 | return -ENOBUFS; | 7645 | return -ENOBUFS; |
7595 | pat_len = wowlan->patterns[i].pattern_len; | 7646 | pat_len = wowlan->patterns[i].pattern_len; |
7596 | if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK, | 7647 | if (nla_put(msg, NL80211_PKTPAT_MASK, DIV_ROUND_UP(pat_len, 8), |
7597 | DIV_ROUND_UP(pat_len, 8), | ||
7598 | wowlan->patterns[i].mask) || | 7648 | wowlan->patterns[i].mask) || |
7599 | nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | 7649 | nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len, |
7600 | pat_len, wowlan->patterns[i].pattern) || | 7650 | wowlan->patterns[i].pattern) || |
7601 | nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET, | 7651 | nla_put_u32(msg, NL80211_PKTPAT_OFFSET, |
7602 | wowlan->patterns[i].pkt_offset)) | 7652 | wowlan->patterns[i].pkt_offset)) |
7603 | return -ENOBUFS; | 7653 | return -ENOBUFS; |
7604 | nla_nest_end(msg, nl_pat); | 7654 | nla_nest_end(msg, nl_pat); |
@@ -7939,7 +7989,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7939 | struct nlattr *pat; | 7989 | struct nlattr *pat; |
7940 | int n_patterns = 0; | 7990 | int n_patterns = 0; |
7941 | int rem, pat_len, mask_len, pkt_offset; | 7991 | int rem, pat_len, mask_len, pkt_offset; |
7942 | struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; | 7992 | struct nlattr *pat_tb[NUM_NL80211_PKTPAT]; |
7943 | 7993 | ||
7944 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | 7994 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], |
7945 | rem) | 7995 | rem) |
@@ -7958,26 +8008,25 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7958 | 8008 | ||
7959 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | 8009 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], |
7960 | rem) { | 8010 | rem) { |
7961 | nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT, | 8011 | nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), |
7962 | nla_data(pat), nla_len(pat), NULL); | 8012 | nla_len(pat), NULL); |
7963 | err = -EINVAL; | 8013 | err = -EINVAL; |
7964 | if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] || | 8014 | if (!pat_tb[NL80211_PKTPAT_MASK] || |
7965 | !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]) | 8015 | !pat_tb[NL80211_PKTPAT_PATTERN]) |
7966 | goto error; | 8016 | goto error; |
7967 | pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]); | 8017 | pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]); |
7968 | mask_len = DIV_ROUND_UP(pat_len, 8); | 8018 | mask_len = DIV_ROUND_UP(pat_len, 8); |
7969 | if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) != | 8019 | if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len) |
7970 | mask_len) | ||
7971 | goto error; | 8020 | goto error; |
7972 | if (pat_len > wowlan->pattern_max_len || | 8021 | if (pat_len > wowlan->pattern_max_len || |
7973 | pat_len < wowlan->pattern_min_len) | 8022 | pat_len < wowlan->pattern_min_len) |
7974 | goto error; | 8023 | goto error; |
7975 | 8024 | ||
7976 | if (!pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]) | 8025 | if (!pat_tb[NL80211_PKTPAT_OFFSET]) |
7977 | pkt_offset = 0; | 8026 | pkt_offset = 0; |
7978 | else | 8027 | else |
7979 | pkt_offset = nla_get_u32( | 8028 | pkt_offset = nla_get_u32( |
7980 | pat_tb[NL80211_WOWLAN_PKTPAT_OFFSET]); | 8029 | pat_tb[NL80211_PKTPAT_OFFSET]); |
7981 | if (pkt_offset > wowlan->max_pkt_offset) | 8030 | if (pkt_offset > wowlan->max_pkt_offset) |
7982 | goto error; | 8031 | goto error; |
7983 | new_triggers.patterns[i].pkt_offset = pkt_offset; | 8032 | new_triggers.patterns[i].pkt_offset = pkt_offset; |
@@ -7991,11 +8040,11 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
7991 | new_triggers.patterns[i].pattern = | 8040 | new_triggers.patterns[i].pattern = |
7992 | new_triggers.patterns[i].mask + mask_len; | 8041 | new_triggers.patterns[i].mask + mask_len; |
7993 | memcpy(new_triggers.patterns[i].mask, | 8042 | memcpy(new_triggers.patterns[i].mask, |
7994 | nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]), | 8043 | nla_data(pat_tb[NL80211_PKTPAT_MASK]), |
7995 | mask_len); | 8044 | mask_len); |
7996 | new_triggers.patterns[i].pattern_len = pat_len; | 8045 | new_triggers.patterns[i].pattern_len = pat_len; |
7997 | memcpy(new_triggers.patterns[i].pattern, | 8046 | memcpy(new_triggers.patterns[i].pattern, |
7998 | nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]), | 8047 | nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), |
7999 | pat_len); | 8048 | pat_len); |
8000 | i++; | 8049 | i++; |
8001 | } | 8050 | } |
@@ -8034,6 +8083,264 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | |||
8034 | } | 8083 | } |
8035 | #endif | 8084 | #endif |
8036 | 8085 | ||
8086 | static int nl80211_send_coalesce_rules(struct sk_buff *msg, | ||
8087 | struct cfg80211_registered_device *rdev) | ||
8088 | { | ||
8089 | struct nlattr *nl_pats, *nl_pat, *nl_rule, *nl_rules; | ||
8090 | int i, j, pat_len; | ||
8091 | struct cfg80211_coalesce_rules *rule; | ||
8092 | |||
8093 | if (!rdev->coalesce->n_rules) | ||
8094 | return 0; | ||
8095 | |||
8096 | nl_rules = nla_nest_start(msg, NL80211_ATTR_COALESCE_RULE); | ||
8097 | if (!nl_rules) | ||
8098 | return -ENOBUFS; | ||
8099 | |||
8100 | for (i = 0; i < rdev->coalesce->n_rules; i++) { | ||
8101 | nl_rule = nla_nest_start(msg, i + 1); | ||
8102 | if (!nl_rule) | ||
8103 | return -ENOBUFS; | ||
8104 | |||
8105 | rule = &rdev->coalesce->rules[i]; | ||
8106 | if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_DELAY, | ||
8107 | rule->delay)) | ||
8108 | return -ENOBUFS; | ||
8109 | |||
8110 | if (nla_put_u32(msg, NL80211_ATTR_COALESCE_RULE_CONDITION, | ||
8111 | rule->condition)) | ||
8112 | return -ENOBUFS; | ||
8113 | |||
8114 | nl_pats = nla_nest_start(msg, | ||
8115 | NL80211_ATTR_COALESCE_RULE_PKT_PATTERN); | ||
8116 | if (!nl_pats) | ||
8117 | return -ENOBUFS; | ||
8118 | |||
8119 | for (j = 0; j < rule->n_patterns; j++) { | ||
8120 | nl_pat = nla_nest_start(msg, j + 1); | ||
8121 | if (!nl_pat) | ||
8122 | return -ENOBUFS; | ||
8123 | pat_len = rule->patterns[j].pattern_len; | ||
8124 | if (nla_put(msg, NL80211_PKTPAT_MASK, | ||
8125 | DIV_ROUND_UP(pat_len, 8), | ||
8126 | rule->patterns[j].mask) || | ||
8127 | nla_put(msg, NL80211_PKTPAT_PATTERN, pat_len, | ||
8128 | rule->patterns[j].pattern) || | ||
8129 | nla_put_u32(msg, NL80211_PKTPAT_OFFSET, | ||
8130 | rule->patterns[j].pkt_offset)) | ||
8131 | return -ENOBUFS; | ||
8132 | nla_nest_end(msg, nl_pat); | ||
8133 | } | ||
8134 | nla_nest_end(msg, nl_pats); | ||
8135 | nla_nest_end(msg, nl_rule); | ||
8136 | } | ||
8137 | nla_nest_end(msg, nl_rules); | ||
8138 | |||
8139 | return 0; | ||
8140 | } | ||
8141 | |||
8142 | static int nl80211_get_coalesce(struct sk_buff *skb, struct genl_info *info) | ||
8143 | { | ||
8144 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
8145 | struct sk_buff *msg; | ||
8146 | void *hdr; | ||
8147 | |||
8148 | if (!rdev->wiphy.coalesce) | ||
8149 | return -EOPNOTSUPP; | ||
8150 | |||
8151 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
8152 | if (!msg) | ||
8153 | return -ENOMEM; | ||
8154 | |||
8155 | hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, | ||
8156 | NL80211_CMD_GET_COALESCE); | ||
8157 | if (!hdr) | ||
8158 | goto nla_put_failure; | ||
8159 | |||
8160 | if (rdev->coalesce && nl80211_send_coalesce_rules(msg, rdev)) | ||
8161 | goto nla_put_failure; | ||
8162 | |||
8163 | genlmsg_end(msg, hdr); | ||
8164 | return genlmsg_reply(msg, info); | ||
8165 | |||
8166 | nla_put_failure: | ||
8167 | nlmsg_free(msg); | ||
8168 | return -ENOBUFS; | ||
8169 | } | ||
8170 | |||
8171 | void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev) | ||
8172 | { | ||
8173 | struct cfg80211_coalesce *coalesce = rdev->coalesce; | ||
8174 | int i, j; | ||
8175 | struct cfg80211_coalesce_rules *rule; | ||
8176 | |||
8177 | if (!coalesce) | ||
8178 | return; | ||
8179 | |||
8180 | for (i = 0; i < coalesce->n_rules; i++) { | ||
8181 | rule = &coalesce->rules[i]; | ||
8182 | for (j = 0; j < rule->n_patterns; j++) | ||
8183 | kfree(rule->patterns[j].mask); | ||
8184 | kfree(rule->patterns); | ||
8185 | } | ||
8186 | kfree(coalesce->rules); | ||
8187 | kfree(coalesce); | ||
8188 | rdev->coalesce = NULL; | ||
8189 | } | ||
8190 | |||
8191 | static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev, | ||
8192 | struct nlattr *rule, | ||
8193 | struct cfg80211_coalesce_rules *new_rule) | ||
8194 | { | ||
8195 | int err, i; | ||
8196 | const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce; | ||
8197 | struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat; | ||
8198 | int rem, pat_len, mask_len, pkt_offset, n_patterns = 0; | ||
8199 | struct nlattr *pat_tb[NUM_NL80211_PKTPAT]; | ||
8200 | |||
8201 | err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule), | ||
8202 | nla_len(rule), nl80211_coalesce_policy); | ||
8203 | if (err) | ||
8204 | return err; | ||
8205 | |||
8206 | if (tb[NL80211_ATTR_COALESCE_RULE_DELAY]) | ||
8207 | new_rule->delay = | ||
8208 | nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]); | ||
8209 | if (new_rule->delay > coalesce->max_delay) | ||
8210 | return -EINVAL; | ||
8211 | |||
8212 | if (tb[NL80211_ATTR_COALESCE_RULE_CONDITION]) | ||
8213 | new_rule->condition = | ||
8214 | nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]); | ||
8215 | if (new_rule->condition != NL80211_COALESCE_CONDITION_MATCH && | ||
8216 | new_rule->condition != NL80211_COALESCE_CONDITION_NO_MATCH) | ||
8217 | return -EINVAL; | ||
8218 | |||
8219 | if (!tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN]) | ||
8220 | return -EINVAL; | ||
8221 | |||
8222 | nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], | ||
8223 | rem) | ||
8224 | n_patterns++; | ||
8225 | if (n_patterns > coalesce->n_patterns) | ||
8226 | return -EINVAL; | ||
8227 | |||
8228 | new_rule->patterns = kcalloc(n_patterns, sizeof(new_rule->patterns[0]), | ||
8229 | GFP_KERNEL); | ||
8230 | if (!new_rule->patterns) | ||
8231 | return -ENOMEM; | ||
8232 | |||
8233 | new_rule->n_patterns = n_patterns; | ||
8234 | i = 0; | ||
8235 | |||
8236 | nla_for_each_nested(pat, tb[NL80211_ATTR_COALESCE_RULE_PKT_PATTERN], | ||
8237 | rem) { | ||
8238 | nla_parse(pat_tb, MAX_NL80211_PKTPAT, nla_data(pat), | ||
8239 | nla_len(pat), NULL); | ||
8240 | if (!pat_tb[NL80211_PKTPAT_MASK] || | ||
8241 | !pat_tb[NL80211_PKTPAT_PATTERN]) | ||
8242 | return -EINVAL; | ||
8243 | pat_len = nla_len(pat_tb[NL80211_PKTPAT_PATTERN]); | ||
8244 | mask_len = DIV_ROUND_UP(pat_len, 8); | ||
8245 | if (nla_len(pat_tb[NL80211_PKTPAT_MASK]) != mask_len) | ||
8246 | return -EINVAL; | ||
8247 | if (pat_len > coalesce->pattern_max_len || | ||
8248 | pat_len < coalesce->pattern_min_len) | ||
8249 | return -EINVAL; | ||
8250 | |||
8251 | if (!pat_tb[NL80211_PKTPAT_OFFSET]) | ||
8252 | pkt_offset = 0; | ||
8253 | else | ||
8254 | pkt_offset = nla_get_u32(pat_tb[NL80211_PKTPAT_OFFSET]); | ||
8255 | if (pkt_offset > coalesce->max_pkt_offset) | ||
8256 | return -EINVAL; | ||
8257 | new_rule->patterns[i].pkt_offset = pkt_offset; | ||
8258 | |||
8259 | new_rule->patterns[i].mask = | ||
8260 | kmalloc(mask_len + pat_len, GFP_KERNEL); | ||
8261 | if (!new_rule->patterns[i].mask) | ||
8262 | return -ENOMEM; | ||
8263 | new_rule->patterns[i].pattern = | ||
8264 | new_rule->patterns[i].mask + mask_len; | ||
8265 | memcpy(new_rule->patterns[i].mask, | ||
8266 | nla_data(pat_tb[NL80211_PKTPAT_MASK]), mask_len); | ||
8267 | new_rule->patterns[i].pattern_len = pat_len; | ||
8268 | memcpy(new_rule->patterns[i].pattern, | ||
8269 | nla_data(pat_tb[NL80211_PKTPAT_PATTERN]), pat_len); | ||
8270 | i++; | ||
8271 | } | ||
8272 | |||
8273 | return 0; | ||
8274 | } | ||
8275 | |||
8276 | static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info) | ||
8277 | { | ||
8278 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
8279 | const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce; | ||
8280 | struct cfg80211_coalesce new_coalesce = {}; | ||
8281 | struct cfg80211_coalesce *n_coalesce; | ||
8282 | int err, rem_rule, n_rules = 0, i, j; | ||
8283 | struct nlattr *rule; | ||
8284 | struct cfg80211_coalesce_rules *tmp_rule; | ||
8285 | |||
8286 | if (!rdev->wiphy.coalesce || !rdev->ops->set_coalesce) | ||
8287 | return -EOPNOTSUPP; | ||
8288 | |||
8289 | if (!info->attrs[NL80211_ATTR_COALESCE_RULE]) { | ||
8290 | cfg80211_rdev_free_coalesce(rdev); | ||
8291 | rdev->ops->set_coalesce(&rdev->wiphy, NULL); | ||
8292 | return 0; | ||
8293 | } | ||
8294 | |||
8295 | nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE], | ||
8296 | rem_rule) | ||
8297 | n_rules++; | ||
8298 | if (n_rules > coalesce->n_rules) | ||
8299 | return -EINVAL; | ||
8300 | |||
8301 | new_coalesce.rules = kcalloc(n_rules, sizeof(new_coalesce.rules[0]), | ||
8302 | GFP_KERNEL); | ||
8303 | if (!new_coalesce.rules) | ||
8304 | return -ENOMEM; | ||
8305 | |||
8306 | new_coalesce.n_rules = n_rules; | ||
8307 | i = 0; | ||
8308 | |||
8309 | nla_for_each_nested(rule, info->attrs[NL80211_ATTR_COALESCE_RULE], | ||
8310 | rem_rule) { | ||
8311 | err = nl80211_parse_coalesce_rule(rdev, rule, | ||
8312 | &new_coalesce.rules[i]); | ||
8313 | if (err) | ||
8314 | goto error; | ||
8315 | |||
8316 | i++; | ||
8317 | } | ||
8318 | |||
8319 | err = rdev->ops->set_coalesce(&rdev->wiphy, &new_coalesce); | ||
8320 | if (err) | ||
8321 | goto error; | ||
8322 | |||
8323 | n_coalesce = kmemdup(&new_coalesce, sizeof(new_coalesce), GFP_KERNEL); | ||
8324 | if (!n_coalesce) { | ||
8325 | err = -ENOMEM; | ||
8326 | goto error; | ||
8327 | } | ||
8328 | cfg80211_rdev_free_coalesce(rdev); | ||
8329 | rdev->coalesce = n_coalesce; | ||
8330 | |||
8331 | return 0; | ||
8332 | error: | ||
8333 | for (i = 0; i < new_coalesce.n_rules; i++) { | ||
8334 | tmp_rule = &new_coalesce.rules[i]; | ||
8335 | for (j = 0; j < tmp_rule->n_patterns; j++) | ||
8336 | kfree(tmp_rule->patterns[j].mask); | ||
8337 | kfree(tmp_rule->patterns); | ||
8338 | } | ||
8339 | kfree(new_coalesce.rules); | ||
8340 | |||
8341 | return err; | ||
8342 | } | ||
8343 | |||
8037 | static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) | 8344 | static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) |
8038 | { | 8345 | { |
8039 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 8346 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -9041,6 +9348,21 @@ static struct genl_ops nl80211_ops[] = { | |||
9041 | .flags = GENL_ADMIN_PERM, | 9348 | .flags = GENL_ADMIN_PERM, |
9042 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | 9349 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | |
9043 | NL80211_FLAG_NEED_RTNL, | 9350 | NL80211_FLAG_NEED_RTNL, |
9351 | }, | ||
9352 | { | ||
9353 | .cmd = NL80211_CMD_GET_COALESCE, | ||
9354 | .doit = nl80211_get_coalesce, | ||
9355 | .policy = nl80211_policy, | ||
9356 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
9357 | NL80211_FLAG_NEED_RTNL, | ||
9358 | }, | ||
9359 | { | ||
9360 | .cmd = NL80211_CMD_SET_COALESCE, | ||
9361 | .doit = nl80211_set_coalesce, | ||
9362 | .policy = nl80211_policy, | ||
9363 | .flags = GENL_ADMIN_PERM, | ||
9364 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
9365 | NL80211_FLAG_NEED_RTNL, | ||
9044 | } | 9366 | } |
9045 | }; | 9367 | }; |
9046 | 9368 | ||
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index a4073e808c13..44341bf53cfc 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -74,4 +74,6 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
74 | enum nl80211_radar_event event, | 74 | enum nl80211_radar_event event, |
75 | struct net_device *netdev, gfp_t gfp); | 75 | struct net_device *netdev, gfp_t gfp); |
76 | 76 | ||
77 | void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); | ||
78 | |||
77 | #endif /* __NET_WIRELESS_NL80211_H */ | 79 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index ae8c186b50d6..ad1e4068ce06 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -651,6 +651,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, | |||
651 | continue; | 651 | continue; |
652 | if (bss->pub.channel != new->pub.channel) | 652 | if (bss->pub.channel != new->pub.channel) |
653 | continue; | 653 | continue; |
654 | if (bss->pub.scan_width != new->pub.scan_width) | ||
655 | continue; | ||
654 | if (rcu_access_pointer(bss->pub.beacon_ies)) | 656 | if (rcu_access_pointer(bss->pub.beacon_ies)) |
655 | continue; | 657 | continue; |
656 | ies = rcu_access_pointer(bss->pub.ies); | 658 | ies = rcu_access_pointer(bss->pub.ies); |
@@ -870,11 +872,12 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | |||
870 | 872 | ||
871 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 873 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
872 | struct cfg80211_bss* | 874 | struct cfg80211_bss* |
873 | cfg80211_inform_bss(struct wiphy *wiphy, | 875 | cfg80211_inform_bss_width(struct wiphy *wiphy, |
874 | struct ieee80211_channel *channel, | 876 | struct ieee80211_channel *channel, |
875 | const u8 *bssid, u64 tsf, u16 capability, | 877 | enum nl80211_bss_scan_width scan_width, |
876 | u16 beacon_interval, const u8 *ie, size_t ielen, | 878 | const u8 *bssid, u64 tsf, u16 capability, |
877 | s32 signal, gfp_t gfp) | 879 | u16 beacon_interval, const u8 *ie, size_t ielen, |
880 | s32 signal, gfp_t gfp) | ||
878 | { | 881 | { |
879 | struct cfg80211_bss_ies *ies; | 882 | struct cfg80211_bss_ies *ies; |
880 | struct cfg80211_internal_bss tmp = {}, *res; | 883 | struct cfg80211_internal_bss tmp = {}, *res; |
@@ -892,6 +895,7 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
892 | 895 | ||
893 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); | 896 | memcpy(tmp.pub.bssid, bssid, ETH_ALEN); |
894 | tmp.pub.channel = channel; | 897 | tmp.pub.channel = channel; |
898 | tmp.pub.scan_width = scan_width; | ||
895 | tmp.pub.signal = signal; | 899 | tmp.pub.signal = signal; |
896 | tmp.pub.beacon_interval = beacon_interval; | 900 | tmp.pub.beacon_interval = beacon_interval; |
897 | tmp.pub.capability = capability; | 901 | tmp.pub.capability = capability; |
@@ -924,14 +928,15 @@ cfg80211_inform_bss(struct wiphy *wiphy, | |||
924 | /* cfg80211_bss_update gives us a referenced result */ | 928 | /* cfg80211_bss_update gives us a referenced result */ |
925 | return &res->pub; | 929 | return &res->pub; |
926 | } | 930 | } |
927 | EXPORT_SYMBOL(cfg80211_inform_bss); | 931 | EXPORT_SYMBOL(cfg80211_inform_bss_width); |
928 | 932 | ||
929 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 933 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
930 | struct cfg80211_bss * | 934 | struct cfg80211_bss * |
931 | cfg80211_inform_bss_frame(struct wiphy *wiphy, | 935 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, |
932 | struct ieee80211_channel *channel, | 936 | struct ieee80211_channel *channel, |
933 | struct ieee80211_mgmt *mgmt, size_t len, | 937 | enum nl80211_bss_scan_width scan_width, |
934 | s32 signal, gfp_t gfp) | 938 | struct ieee80211_mgmt *mgmt, size_t len, |
939 | s32 signal, gfp_t gfp) | ||
935 | { | 940 | { |
936 | struct cfg80211_internal_bss tmp = {}, *res; | 941 | struct cfg80211_internal_bss tmp = {}, *res; |
937 | struct cfg80211_bss_ies *ies; | 942 | struct cfg80211_bss_ies *ies; |
@@ -941,7 +946,8 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
941 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | 946 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != |
942 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | 947 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); |
943 | 948 | ||
944 | trace_cfg80211_inform_bss_frame(wiphy, channel, mgmt, len, signal); | 949 | trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt, |
950 | len, signal); | ||
945 | 951 | ||
946 | if (WARN_ON(!mgmt)) | 952 | if (WARN_ON(!mgmt)) |
947 | return NULL; | 953 | return NULL; |
@@ -976,6 +982,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
976 | 982 | ||
977 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); | 983 | memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); |
978 | tmp.pub.channel = channel; | 984 | tmp.pub.channel = channel; |
985 | tmp.pub.scan_width = scan_width; | ||
979 | tmp.pub.signal = signal; | 986 | tmp.pub.signal = signal; |
980 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 987 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
981 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 988 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
@@ -991,7 +998,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, | |||
991 | /* cfg80211_bss_update gives us a referenced result */ | 998 | /* cfg80211_bss_update gives us a referenced result */ |
992 | return &res->pub; | 999 | return &res->pub; |
993 | } | 1000 | } |
994 | EXPORT_SYMBOL(cfg80211_inform_bss_frame); | 1001 | EXPORT_SYMBOL(cfg80211_inform_bss_width_frame); |
995 | 1002 | ||
996 | void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) | 1003 | void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) |
997 | { | 1004 | { |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index e1534baf2ebb..09af6eb426a8 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -2391,26 +2391,30 @@ TRACE_EVENT(cfg80211_get_bss, | |||
2391 | __entry->capa_mask, __entry->capa_val) | 2391 | __entry->capa_mask, __entry->capa_val) |
2392 | ); | 2392 | ); |
2393 | 2393 | ||
2394 | TRACE_EVENT(cfg80211_inform_bss_frame, | 2394 | TRACE_EVENT(cfg80211_inform_bss_width_frame, |
2395 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, | 2395 | TP_PROTO(struct wiphy *wiphy, struct ieee80211_channel *channel, |
2396 | enum nl80211_bss_scan_width scan_width, | ||
2396 | struct ieee80211_mgmt *mgmt, size_t len, | 2397 | struct ieee80211_mgmt *mgmt, size_t len, |
2397 | s32 signal), | 2398 | s32 signal), |
2398 | TP_ARGS(wiphy, channel, mgmt, len, signal), | 2399 | TP_ARGS(wiphy, channel, scan_width, mgmt, len, signal), |
2399 | TP_STRUCT__entry( | 2400 | TP_STRUCT__entry( |
2400 | WIPHY_ENTRY | 2401 | WIPHY_ENTRY |
2401 | CHAN_ENTRY | 2402 | CHAN_ENTRY |
2403 | __field(enum nl80211_bss_scan_width, scan_width) | ||
2402 | __dynamic_array(u8, mgmt, len) | 2404 | __dynamic_array(u8, mgmt, len) |
2403 | __field(s32, signal) | 2405 | __field(s32, signal) |
2404 | ), | 2406 | ), |
2405 | TP_fast_assign( | 2407 | TP_fast_assign( |
2406 | WIPHY_ASSIGN; | 2408 | WIPHY_ASSIGN; |
2407 | CHAN_ASSIGN(channel); | 2409 | CHAN_ASSIGN(channel); |
2410 | __entry->scan_width = scan_width; | ||
2408 | if (mgmt) | 2411 | if (mgmt) |
2409 | memcpy(__get_dynamic_array(mgmt), mgmt, len); | 2412 | memcpy(__get_dynamic_array(mgmt), mgmt, len); |
2410 | __entry->signal = signal; | 2413 | __entry->signal = signal; |
2411 | ), | 2414 | ), |
2412 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "signal: %d", | 2415 | TP_printk(WIPHY_PR_FMT ", " CHAN_PR_FMT "(scan_width: %d) signal: %d", |
2413 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->signal) | 2416 | WIPHY_PR_ARG, CHAN_PR_ARG, __entry->scan_width, |
2417 | __entry->signal) | ||
2414 | ); | 2418 | ); |
2415 | 2419 | ||
2416 | DECLARE_EVENT_CLASS(cfg80211_bss_evt, | 2420 | DECLARE_EVENT_CLASS(cfg80211_bss_evt, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 74458b7f61eb..ce090c1c5e4f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -33,7 +33,8 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband, | |||
33 | } | 33 | } |
34 | EXPORT_SYMBOL(ieee80211_get_response_rate); | 34 | EXPORT_SYMBOL(ieee80211_get_response_rate); |
35 | 35 | ||
36 | u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband) | 36 | u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband, |
37 | enum nl80211_bss_scan_width scan_width) | ||
37 | { | 38 | { |
38 | struct ieee80211_rate *bitrates; | 39 | struct ieee80211_rate *bitrates; |
39 | u32 mandatory_rates = 0; | 40 | u32 mandatory_rates = 0; |
@@ -43,10 +44,15 @@ u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband) | |||
43 | if (WARN_ON(!sband)) | 44 | if (WARN_ON(!sband)) |
44 | return 1; | 45 | return 1; |
45 | 46 | ||
46 | if (sband->band == IEEE80211_BAND_2GHZ) | 47 | if (sband->band == IEEE80211_BAND_2GHZ) { |
47 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | 48 | if (scan_width == NL80211_BSS_CHAN_WIDTH_5 || |
48 | else | 49 | scan_width == NL80211_BSS_CHAN_WIDTH_10) |
50 | mandatory_flag = IEEE80211_RATE_MANDATORY_G; | ||
51 | else | ||
52 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | ||
53 | } else { | ||
49 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | 54 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; |
55 | } | ||
50 | 56 | ||
51 | bitrates = sband->bitrates; | 57 | bitrates = sband->bitrates; |
52 | for (i = 0; i < sband->n_bitrates; i++) | 58 | for (i = 0; i < sband->n_bitrates; i++) |