diff options
45 files changed, 1297 insertions, 444 deletions
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl index 42e7f030cb16..284ced7a228f 100644 --- a/Documentation/DocBook/80211.tmpl +++ b/Documentation/DocBook/80211.tmpl | |||
@@ -107,8 +107,8 @@ | |||
107 | !Finclude/net/cfg80211.h key_params | 107 | !Finclude/net/cfg80211.h key_params |
108 | !Finclude/net/cfg80211.h survey_info_flags | 108 | !Finclude/net/cfg80211.h survey_info_flags |
109 | !Finclude/net/cfg80211.h survey_info | 109 | !Finclude/net/cfg80211.h survey_info |
110 | !Finclude/net/cfg80211.h beacon_parameters | 110 | !Finclude/net/cfg80211.h cfg80211_beacon_data |
111 | !Finclude/net/cfg80211.h plink_actions | 111 | !Finclude/net/cfg80211.h cfg80211_ap_settings |
112 | !Finclude/net/cfg80211.h station_parameters | 112 | !Finclude/net/cfg80211.h station_parameters |
113 | !Finclude/net/cfg80211.h station_info_flags | 113 | !Finclude/net/cfg80211.h station_info_flags |
114 | !Finclude/net/cfg80211.h rate_info_flags | 114 | !Finclude/net/cfg80211.h rate_info_flags |
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c index c6ea995750db..dd9a18f8dbca 100644 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ b/drivers/net/wireless/hostap/hostap_ap.c | |||
@@ -376,7 +376,7 @@ int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac) | |||
376 | 376 | ||
377 | entry = kmalloc(sizeof(struct mac_entry), GFP_KERNEL); | 377 | entry = kmalloc(sizeof(struct mac_entry), GFP_KERNEL); |
378 | if (entry == NULL) | 378 | if (entry == NULL) |
379 | return -1; | 379 | return -ENOMEM; |
380 | 380 | ||
381 | memcpy(entry->addr, mac, ETH_ALEN); | 381 | memcpy(entry->addr, mac, ETH_ALEN); |
382 | 382 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h index 02c9ebb3b340..84e2c0fcfef6 100644 --- a/drivers/net/wireless/iwlwifi/dvm/commands.h +++ b/drivers/net/wireless/iwlwifi/dvm/commands.h | |||
@@ -1403,6 +1403,7 @@ enum { | |||
1403 | 1403 | ||
1404 | #define AGG_TX_STATUS_MSK 0x00000fff /* bits 0:11 */ | 1404 | #define AGG_TX_STATUS_MSK 0x00000fff /* bits 0:11 */ |
1405 | #define AGG_TX_TRY_MSK 0x0000f000 /* bits 12:15 */ | 1405 | #define AGG_TX_TRY_MSK 0x0000f000 /* bits 12:15 */ |
1406 | #define AGG_TX_TRY_POS 12 | ||
1406 | 1407 | ||
1407 | #define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \ | 1408 | #define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \ |
1408 | AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ | 1409 | AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c index 67e2e1321b40..03f9bc01c0cc 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tt.c +++ b/drivers/net/wireless/iwlwifi/dvm/tt.c | |||
@@ -471,8 +471,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | |||
471 | set_bit(STATUS_CT_KILL, &priv->status); | 471 | set_bit(STATUS_CT_KILL, &priv->status); |
472 | iwl_perform_ct_kill_task(priv, true); | 472 | iwl_perform_ct_kill_task(priv, true); |
473 | } else { | 473 | } else { |
474 | iwl_prepare_ct_kill_task(priv); | ||
475 | tt->state = old_state; | 474 | tt->state = old_state; |
475 | iwl_prepare_ct_kill_task(priv); | ||
476 | } | 476 | } |
477 | } else if (old_state == IWL_TI_CT_KILL && | 477 | } else if (old_state == IWL_TI_CT_KILL && |
478 | tt->state != IWL_TI_CT_KILL) { | 478 | tt->state != IWL_TI_CT_KILL) { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index d1dccb361391..6aec2df3bb27 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -908,6 +908,12 @@ static void iwlagn_count_agg_tx_err_status(struct iwl_priv *priv, u16 status) | |||
908 | } | 908 | } |
909 | } | 909 | } |
910 | 910 | ||
911 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) | ||
912 | { | ||
913 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
914 | tx_resp->frame_count) & MAX_SN; | ||
915 | } | ||
916 | |||
911 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | 917 | static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, |
912 | struct iwlagn_tx_resp *tx_resp) | 918 | struct iwlagn_tx_resp *tx_resp) |
913 | { | 919 | { |
@@ -942,9 +948,15 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | |||
942 | if (tx_resp->frame_count == 1) | 948 | if (tx_resp->frame_count == 1) |
943 | return; | 949 | return; |
944 | 950 | ||
951 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d initial_rate 0x%x ssn %d frm_cnt %d\n", | ||
952 | agg->txq_id, | ||
953 | le32_to_cpu(tx_resp->rate_n_flags), | ||
954 | iwlagn_get_scd_ssn(tx_resp), tx_resp->frame_count); | ||
955 | |||
945 | /* Construct bit-map of pending frames within Tx window */ | 956 | /* Construct bit-map of pending frames within Tx window */ |
946 | for (i = 0; i < tx_resp->frame_count; i++) { | 957 | for (i = 0; i < tx_resp->frame_count; i++) { |
947 | u16 fstatus = le16_to_cpu(frame_status[i].status); | 958 | u16 fstatus = le16_to_cpu(frame_status[i].status); |
959 | u8 retry_cnt = (fstatus & AGG_TX_TRY_MSK) >> AGG_TX_TRY_POS; | ||
948 | 960 | ||
949 | if (status & AGG_TX_STATUS_MSK) | 961 | if (status & AGG_TX_STATUS_MSK) |
950 | iwlagn_count_agg_tx_err_status(priv, fstatus); | 962 | iwlagn_count_agg_tx_err_status(priv, fstatus); |
@@ -952,6 +964,14 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, | |||
952 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | | 964 | if (status & (AGG_TX_STATE_FEW_BYTES_MSK | |
953 | AGG_TX_STATE_ABORT_MSK)) | 965 | AGG_TX_STATE_ABORT_MSK)) |
954 | continue; | 966 | continue; |
967 | |||
968 | if (status & AGG_TX_STATUS_MSK || retry_cnt > 1) | ||
969 | IWL_DEBUG_TX_REPLY(priv, | ||
970 | "%d: status %s (0x%04x), try-count (0x%01x)\n", | ||
971 | i, | ||
972 | iwl_get_agg_tx_fail_reason(fstatus), | ||
973 | fstatus & AGG_TX_STATUS_MSK, | ||
974 | retry_cnt); | ||
955 | } | 975 | } |
956 | } | 976 | } |
957 | 977 | ||
@@ -982,12 +1002,6 @@ const char *iwl_get_agg_tx_fail_reason(u16 status) | |||
982 | } | 1002 | } |
983 | #endif /* CONFIG_IWLWIFI_DEBUG */ | 1003 | #endif /* CONFIG_IWLWIFI_DEBUG */ |
984 | 1004 | ||
985 | static inline u32 iwlagn_get_scd_ssn(struct iwlagn_tx_resp *tx_resp) | ||
986 | { | ||
987 | return le32_to_cpup((__le32 *)&tx_resp->status + | ||
988 | tx_resp->frame_count) & MAX_SN; | ||
989 | } | ||
990 | |||
991 | static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) | 1005 | static void iwlagn_count_tx_err_status(struct iwl_priv *priv, u16 status) |
992 | { | 1006 | { |
993 | status &= TX_STATUS_MSK; | 1007 | status &= TX_STATUS_MSK; |
@@ -1119,8 +1133,14 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1119 | 1133 | ||
1120 | spin_lock_bh(&priv->sta_lock); | 1134 | spin_lock_bh(&priv->sta_lock); |
1121 | 1135 | ||
1122 | if (is_agg) | 1136 | if (is_agg) { |
1137 | WARN_ON_ONCE(sta_id >= IWLAGN_STATION_COUNT || | ||
1138 | tid >= IWL_MAX_TID_COUNT); | ||
1139 | if (txq_id != priv->tid_data[sta_id][tid].agg.txq_id) | ||
1140 | IWL_ERR(priv, "txq_id mismatch: %d %d\n", txq_id, | ||
1141 | priv->tid_data[sta_id][tid].agg.txq_id); | ||
1123 | iwl_rx_reply_tx_agg(priv, tx_resp); | 1142 | iwl_rx_reply_tx_agg(priv, tx_resp); |
1143 | } | ||
1124 | 1144 | ||
1125 | __skb_queue_head_init(&skbs); | 1145 | __skb_queue_head_init(&skbs); |
1126 | 1146 | ||
@@ -1224,16 +1244,17 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, | |||
1224 | */ | 1244 | */ |
1225 | if (is_offchannel_skb && freed != 1) | 1245 | if (is_offchannel_skb && freed != 1) |
1226 | IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed); | 1246 | IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed); |
1227 | } | ||
1228 | 1247 | ||
1229 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id, | 1248 | IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id, |
1230 | iwl_get_tx_fail_reason(status), status); | 1249 | iwl_get_tx_fail_reason(status), status); |
1231 | 1250 | ||
1232 | IWL_DEBUG_TX_REPLY(priv, | 1251 | IWL_DEBUG_TX_REPLY(priv, |
1233 | "\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d seq_ctl=0x%x\n", | 1252 | "\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d seq_ctl=0x%x\n", |
1234 | le32_to_cpu(tx_resp->rate_n_flags), | 1253 | le32_to_cpu(tx_resp->rate_n_flags), |
1235 | tx_resp->failure_frame, SEQ_TO_INDEX(sequence), ssn, | 1254 | tx_resp->failure_frame, |
1236 | le16_to_cpu(tx_resp->seq_ctl)); | 1255 | SEQ_TO_INDEX(sequence), ssn, |
1256 | le16_to_cpu(tx_resp->seq_ctl)); | ||
1257 | } | ||
1237 | 1258 | ||
1238 | iwl_check_abort_status(priv, tx_resp->frame_count, status); | 1259 | iwl_check_abort_status(priv, tx_resp->frame_count, status); |
1239 | spin_unlock_bh(&priv->sta_lock); | 1260 | spin_unlock_bh(&priv->sta_lock); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 0854dc338881..341dbc0237ea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -245,6 +245,10 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
245 | * that we should share it with another interface. | 245 | * that we should share it with another interface. |
246 | */ | 246 | */ |
247 | 247 | ||
248 | /* Currently, MAC ID 0 should be used only for the managed vif */ | ||
249 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
250 | __clear_bit(0, data.available_mac_ids); | ||
251 | |||
248 | ieee80211_iterate_active_interfaces_atomic( | 252 | ieee80211_iterate_active_interfaces_atomic( |
249 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, | 253 | mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL, |
250 | iwl_mvm_mac_iface_iterator, &data); | 254 | iwl_mvm_mac_iface_iterator, &data); |
@@ -286,6 +290,9 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
286 | 290 | ||
287 | mvmvif->color = 0; | 291 | mvmvif->color = 0; |
288 | 292 | ||
293 | INIT_LIST_HEAD(&mvmvif->time_event_data.list); | ||
294 | mvmvif->time_event_data.id = TE_MAX; | ||
295 | |||
289 | /* No need to allocate data queues to P2P Device MAC.*/ | 296 | /* No need to allocate data queues to P2P Device MAC.*/ |
290 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { | 297 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { |
291 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 298 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
@@ -328,9 +335,6 @@ static int iwl_mvm_mac_ctxt_allocate_resources(struct iwl_mvm *mvm, | |||
328 | mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT; | 335 | mvmvif->bcast_sta.sta_id = IWL_MVM_STATION_COUNT; |
329 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; | 336 | mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; |
330 | 337 | ||
331 | INIT_LIST_HEAD(&mvmvif->time_event_data.list); | ||
332 | mvmvif->time_event_data.id = TE_MAX; | ||
333 | |||
334 | return 0; | 338 | return 0; |
335 | 339 | ||
336 | exit_fail: | 340 | exit_fail: |
@@ -585,10 +589,43 @@ static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm, | |||
585 | struct iwl_mac_data_sta *ctxt_sta) | 589 | struct iwl_mac_data_sta *ctxt_sta) |
586 | { | 590 | { |
587 | /* We need the dtim_period to set the MAC as associated */ | 591 | /* We need the dtim_period to set the MAC as associated */ |
588 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) | 592 | if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) { |
593 | u32 dtim_offs; | ||
594 | |||
595 | /* | ||
596 | * The DTIM count counts down, so when it is N that means N | ||
597 | * more beacon intervals happen until the DTIM TBTT. Therefore | ||
598 | * add this to the current time. If that ends up being in the | ||
599 | * future, the firmware will handle it. | ||
600 | * | ||
601 | * Also note that the system_timestamp (which we get here as | ||
602 | * "sync_device_ts") and TSF timestamp aren't at exactly the | ||
603 | * same offset in the frame -- the TSF is at the first symbol | ||
604 | * of the TSF, the system timestamp is at signal acquisition | ||
605 | * time. This means there's an offset between them of at most | ||
606 | * a few hundred microseconds (24 * 8 bits + PLCP time gives | ||
607 | * 384us in the longest case), this is currently not relevant | ||
608 | * as the firmware wakes up around 2ms before the TBTT. | ||
609 | */ | ||
610 | dtim_offs = vif->bss_conf.sync_dtim_count * | ||
611 | vif->bss_conf.beacon_int; | ||
612 | /* convert TU to usecs */ | ||
613 | dtim_offs *= 1024; | ||
614 | |||
615 | ctxt_sta->dtim_tsf = | ||
616 | cpu_to_le64(vif->bss_conf.sync_tsf + dtim_offs); | ||
617 | ctxt_sta->dtim_time = | ||
618 | cpu_to_le32(vif->bss_conf.sync_device_ts + dtim_offs); | ||
619 | |||
620 | IWL_DEBUG_INFO(mvm, "DTIM TBTT is 0x%llx/0x%x, offset %d\n", | ||
621 | le64_to_cpu(ctxt_sta->dtim_tsf), | ||
622 | le32_to_cpu(ctxt_sta->dtim_time), | ||
623 | dtim_offs); | ||
624 | |||
589 | ctxt_sta->is_assoc = cpu_to_le32(1); | 625 | ctxt_sta->is_assoc = cpu_to_le32(1); |
590 | else | 626 | } else { |
591 | ctxt_sta->is_assoc = cpu_to_le32(0); | 627 | ctxt_sta->is_assoc = cpu_to_le32(0); |
628 | } | ||
592 | 629 | ||
593 | ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int); | 630 | ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int); |
594 | ctxt_sta->bi_reciprocal = | 631 | ctxt_sta->bi_reciprocal = |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e27eb9724112..e8264e11b12d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -113,10 +113,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
113 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 113 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
114 | IEEE80211_HW_QUEUE_CONTROL | | 114 | IEEE80211_HW_QUEUE_CONTROL | |
115 | IEEE80211_HW_WANT_MONITOR_VIF | | 115 | IEEE80211_HW_WANT_MONITOR_VIF | |
116 | IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | | ||
117 | IEEE80211_HW_SUPPORTS_PS | | 116 | IEEE80211_HW_SUPPORTS_PS | |
118 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 117 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
119 | IEEE80211_HW_AMPDU_AGGREGATION; | 118 | IEEE80211_HW_AMPDU_AGGREGATION | |
119 | IEEE80211_HW_TIMING_BEACON_ONLY; | ||
120 | 120 | ||
121 | hw->queues = IWL_FIRST_AMPDU_QUEUE; | 121 | hw->queues = IWL_FIRST_AMPDU_QUEUE; |
122 | hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE; | 122 | hw->offchannel_tx_hw_queue = IWL_OFFCHANNEL_QUEUE; |
@@ -857,7 +857,6 @@ iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw, | |||
857 | bool more_data) | 857 | bool more_data) |
858 | { | 858 | { |
859 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 859 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
860 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
861 | 860 | ||
862 | /* TODO: how do we tell the fw to send frames for a specific TID */ | 861 | /* TODO: how do we tell the fw to send frames for a specific TID */ |
863 | 862 | ||
@@ -865,8 +864,7 @@ iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw, | |||
865 | * The fw will send EOSP notification when the last frame will be | 864 | * The fw will send EOSP notification when the last frame will be |
866 | * transmitted. | 865 | * transmitted. |
867 | */ | 866 | */ |
868 | iwl_mvm_sta_modify_sleep_tx_count(mvm, mvmsta->sta_id, reason, | 867 | iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames); |
869 | num_frames); | ||
870 | } | 868 | } |
871 | 869 | ||
872 | static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | 870 | static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, |
@@ -890,7 +888,7 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | |||
890 | case STA_NOTIFY_AWAKE: | 888 | case STA_NOTIFY_AWAKE: |
891 | if (WARN_ON(mvmsta->sta_id == IWL_INVALID_STATION)) | 889 | if (WARN_ON(mvmsta->sta_id == IWL_INVALID_STATION)) |
892 | break; | 890 | break; |
893 | iwl_mvm_sta_modify_ps_wake(mvm, mvmsta->sta_id); | 891 | iwl_mvm_sta_modify_ps_wake(mvm, sta); |
894 | break; | 892 | break; |
895 | default: | 893 | default: |
896 | break; | 894 | break; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 3f3ce91ad5c2..3f40ab05bbd8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -267,6 +267,7 @@ int iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
267 | 267 | ||
268 | /* rx_status carries information about the packet to mac80211 */ | 268 | /* rx_status carries information about the packet to mac80211 */ |
269 | rx_status.mactime = le64_to_cpu(phy_info->timestamp); | 269 | rx_status.mactime = le64_to_cpu(phy_info->timestamp); |
270 | rx_status.device_timestamp = le32_to_cpu(phy_info->system_timestamp); | ||
270 | rx_status.band = | 271 | rx_status.band = |
271 | (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? | 272 | (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ? |
272 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 273 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 406c53ad0a49..9b21b92aa8d1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -292,7 +292,12 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
292 | cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); | 292 | cmd->rxon_flags = iwl_mvm_scan_rxon_flags(req); |
293 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | | 293 | cmd->filter_flags = cpu_to_le32(MAC_FILTER_ACCEPT_GRP | |
294 | MAC_FILTER_IN_BEACON); | 294 | MAC_FILTER_IN_BEACON); |
295 | cmd->type = SCAN_TYPE_FORCED; | 295 | |
296 | if (vif->type == NL80211_IFTYPE_P2P_DEVICE) | ||
297 | cmd->type = cpu_to_le32(SCAN_TYPE_DISCOVERY_FORCED); | ||
298 | else | ||
299 | cmd->type = cpu_to_le32(SCAN_TYPE_FORCED); | ||
300 | |||
296 | cmd->repeats = cpu_to_le32(1); | 301 | cmd->repeats = cpu_to_le32(1); |
297 | 302 | ||
298 | /* | 303 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index a1eb692d7fad..861a7f9f8e7f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -1188,13 +1188,16 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm, | |||
1188 | rcu_read_unlock(); | 1188 | rcu_read_unlock(); |
1189 | } | 1189 | } |
1190 | 1190 | ||
1191 | void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, int sta_id) | 1191 | void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, |
1192 | struct ieee80211_sta *sta) | ||
1192 | { | 1193 | { |
1194 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
1193 | struct iwl_mvm_add_sta_cmd cmd = { | 1195 | struct iwl_mvm_add_sta_cmd cmd = { |
1194 | .add_modify = STA_MODE_MODIFY, | 1196 | .add_modify = STA_MODE_MODIFY, |
1195 | .sta_id = sta_id, | 1197 | .sta_id = mvmsta->sta_id, |
1196 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, | 1198 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, |
1197 | .sleep_state_flags = cpu_to_le16(STA_SLEEP_STATE_AWAKE), | 1199 | .sleep_state_flags = cpu_to_le16(STA_SLEEP_STATE_AWAKE), |
1200 | .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), | ||
1198 | }; | 1201 | }; |
1199 | int ret; | 1202 | int ret; |
1200 | 1203 | ||
@@ -1208,18 +1211,21 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, int sta_id) | |||
1208 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); | 1211 | IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); |
1209 | } | 1212 | } |
1210 | 1213 | ||
1211 | void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, int sta_id, | 1214 | void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, |
1215 | struct ieee80211_sta *sta, | ||
1212 | enum ieee80211_frame_release_type reason, | 1216 | enum ieee80211_frame_release_type reason, |
1213 | u16 cnt) | 1217 | u16 cnt) |
1214 | { | 1218 | { |
1215 | u16 sleep_state_flags = | 1219 | u16 sleep_state_flags = |
1216 | (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? | 1220 | (reason == IEEE80211_FRAME_RELEASE_UAPSD) ? |
1217 | STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; | 1221 | STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL; |
1222 | struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv; | ||
1218 | struct iwl_mvm_add_sta_cmd cmd = { | 1223 | struct iwl_mvm_add_sta_cmd cmd = { |
1219 | .add_modify = STA_MODE_MODIFY, | 1224 | .add_modify = STA_MODE_MODIFY, |
1220 | .sta_id = sta_id, | 1225 | .sta_id = mvmsta->sta_id, |
1221 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, | 1226 | .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, |
1222 | .sleep_tx_count = cpu_to_le16(cnt), | 1227 | .sleep_tx_count = cpu_to_le16(cnt), |
1228 | .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), | ||
1223 | /* | 1229 | /* |
1224 | * Same modify mask for sleep_tx_count and sleep_state_flags so | 1230 | * Same modify mask for sleep_tx_count and sleep_state_flags so |
1225 | * we must set the sleep_state_flags too. | 1231 | * we must set the sleep_state_flags too. |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h index bdd7c5ed8222..896f88ac8145 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/iwlwifi/mvm/sta.h | |||
@@ -362,8 +362,10 @@ int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
362 | struct iwl_mvm_int_sta *bsta); | 362 | struct iwl_mvm_int_sta *bsta); |
363 | int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta); | 363 | int iwl_mvm_rm_bcast_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *bsta); |
364 | void iwl_mvm_sta_drained_wk(struct work_struct *wk); | 364 | void iwl_mvm_sta_drained_wk(struct work_struct *wk); |
365 | void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, int sta_id); | 365 | void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm, |
366 | void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, int sta_id, | 366 | struct ieee80211_sta *sta); |
367 | void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, | ||
368 | struct ieee80211_sta *sta, | ||
367 | enum ieee80211_frame_release_type reason, | 369 | enum ieee80211_frame_release_type reason, |
368 | u16 cnt); | 370 | u16 cnt); |
369 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, | 371 | int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index c09b71f23759..e437e02c7149 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -248,6 +248,11 @@ static bool iwl_mvm_time_event_response(struct iwl_notif_wait_data *notif_wait, | |||
248 | } | 248 | } |
249 | 249 | ||
250 | resp = (void *)pkt->data; | 250 | resp = (void *)pkt->data; |
251 | |||
252 | /* we should never get a response to another TIME_EVENT_CMD here */ | ||
253 | if (WARN_ON_ONCE(le32_to_cpu(resp->id) != te_data->id)) | ||
254 | return false; | ||
255 | |||
251 | te_data->uid = le32_to_cpu(resp->unique_id); | 256 | te_data->uid = le32_to_cpu(resp->unique_id); |
252 | IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n", | 257 | IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n", |
253 | te_data->uid); | 258 | te_data->uid); |
@@ -265,6 +270,9 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm, | |||
265 | 270 | ||
266 | lockdep_assert_held(&mvm->mutex); | 271 | lockdep_assert_held(&mvm->mutex); |
267 | 272 | ||
273 | IWL_DEBUG_TE(mvm, "Add new TE, duration %d TU\n", | ||
274 | le32_to_cpu(te_cmd->duration)); | ||
275 | |||
268 | spin_lock_bh(&mvm->time_event_lock); | 276 | spin_lock_bh(&mvm->time_event_lock); |
269 | if (WARN_ON(te_data->id != TE_MAX)) { | 277 | if (WARN_ON(te_data->id != TE_MAX)) { |
270 | spin_unlock_bh(&mvm->time_event_lock); | 278 | spin_unlock_bh(&mvm->time_event_lock); |
@@ -413,7 +421,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm, | |||
413 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); | 421 | cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); |
414 | 422 | ||
415 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); | 423 | IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id)); |
416 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_ASYNC, | 424 | ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC, |
417 | sizeof(time_cmd), &time_cmd); | 425 | sizeof(time_cmd), &time_cmd); |
418 | if (WARN_ON(ret)) | 426 | if (WARN_ON(ret)) |
419 | return; | 427 | return; |
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c new file mode 100644 index 000000000000..cf43b3c29250 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11ac.c | |||
@@ -0,0 +1,261 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: 802.11ac | ||
3 | * | ||
4 | * Copyright (C) 2013, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
17 | * this warranty disclaimer. | ||
18 | */ | ||
19 | |||
20 | #include "decl.h" | ||
21 | #include "ioctl.h" | ||
22 | #include "fw.h" | ||
23 | #include "main.h" | ||
24 | #include "11ac.h" | ||
25 | |||
26 | /* This function converts the 2-bit MCS map to the highest long GI | ||
27 | * VHT data rate. | ||
28 | */ | ||
29 | static u16 | ||
30 | mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv, | ||
31 | u8 bands, u16 mcs_map) | ||
32 | { | ||
33 | u8 i, nss, max_mcs; | ||
34 | u16 max_rate = 0; | ||
35 | u32 usr_vht_cap_info = 0; | ||
36 | struct mwifiex_adapter *adapter = priv->adapter; | ||
37 | /* tables of the MCS map to the highest data rate (in Mbps) | ||
38 | * supported for long GI | ||
39 | */ | ||
40 | u16 max_rate_lgi_80MHZ[8][3] = { | ||
41 | {0x124, 0x15F, 0x186}, /* NSS = 1 */ | ||
42 | {0x249, 0x2BE, 0x30C}, /* NSS = 2 */ | ||
43 | {0x36D, 0x41D, 0x492}, /* NSS = 3 */ | ||
44 | {0x492, 0x57C, 0x618}, /* NSS = 4 */ | ||
45 | {0x5B6, 0x6DB, 0x79E}, /* NSS = 5 */ | ||
46 | {0x6DB, 0x83A, 0x0}, /* NSS = 6 */ | ||
47 | {0x7FF, 0x999, 0xAAA}, /* NSS = 7 */ | ||
48 | {0x924, 0xAF8, 0xC30} /* NSS = 8 */ | ||
49 | }; | ||
50 | u16 max_rate_lgi_160MHZ[8][3] = { | ||
51 | {0x249, 0x2BE, 0x30C}, /* NSS = 1 */ | ||
52 | {0x492, 0x57C, 0x618}, /* NSS = 2 */ | ||
53 | {0x6DB, 0x83A, 0x0}, /* NSS = 3 */ | ||
54 | {0x924, 0xAF8, 0xC30}, /* NSS = 4 */ | ||
55 | {0xB6D, 0xDB6, 0xF3C}, /* NSS = 5 */ | ||
56 | {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */ | ||
57 | {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */ | ||
58 | {0x1248, 0x15F0, 0x1860} /* NSS = 8 */ | ||
59 | }; | ||
60 | |||
61 | if (bands & BAND_AAC) | ||
62 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; | ||
63 | else | ||
64 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; | ||
65 | |||
66 | /* find the max NSS supported */ | ||
67 | nss = 0; | ||
68 | for (i = 0; i < 8; i++) { | ||
69 | max_mcs = (mcs_map >> (2 * i)) & 0x3; | ||
70 | if (max_mcs < 3) | ||
71 | nss = i; | ||
72 | } | ||
73 | max_mcs = (mcs_map >> (2 * nss)) & 0x3; | ||
74 | |||
75 | /* if max_mcs is 3, nss must be 0 (SS = 1). Thus, max mcs is MCS 9 */ | ||
76 | if (max_mcs >= 3) | ||
77 | max_mcs = 2; | ||
78 | |||
79 | if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) { | ||
80 | /* support 160 MHz */ | ||
81 | max_rate = max_rate_lgi_160MHZ[nss][max_mcs]; | ||
82 | if (!max_rate) | ||
83 | /* MCS9 is not supported in NSS6 */ | ||
84 | max_rate = max_rate_lgi_160MHZ[nss][max_mcs - 1]; | ||
85 | } else { | ||
86 | max_rate = max_rate_lgi_80MHZ[nss][max_mcs]; | ||
87 | if (!max_rate) | ||
88 | /* MCS9 is not supported in NSS3 */ | ||
89 | max_rate = max_rate_lgi_80MHZ[nss][max_mcs - 1]; | ||
90 | } | ||
91 | |||
92 | return max_rate; | ||
93 | } | ||
94 | |||
95 | static void | ||
96 | mwifiex_fill_vht_cap_info(struct mwifiex_private *priv, | ||
97 | struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands) | ||
98 | { | ||
99 | struct mwifiex_adapter *adapter = priv->adapter; | ||
100 | |||
101 | if (bands & BAND_A) | ||
102 | vht_cap->vht_cap.vht_cap_info = | ||
103 | cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a); | ||
104 | else | ||
105 | vht_cap->vht_cap.vht_cap_info = | ||
106 | cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg); | ||
107 | } | ||
108 | |||
109 | static void | ||
110 | mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, | ||
111 | struct mwifiex_ie_types_vhtcap *vht_cap, u8 bands) | ||
112 | { | ||
113 | struct mwifiex_adapter *adapter = priv->adapter; | ||
114 | u16 mcs_map_user, mcs_map_resp, mcs_map_result; | ||
115 | u16 mcs_user, mcs_resp, nss, tmp; | ||
116 | |||
117 | /* Fill VHT cap info */ | ||
118 | mwifiex_fill_vht_cap_info(priv, vht_cap, bands); | ||
119 | |||
120 | /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */ | ||
121 | mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support); | ||
122 | mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.rx_mcs_map); | ||
123 | mcs_map_result = 0; | ||
124 | |||
125 | for (nss = 1; nss <= 8; nss++) { | ||
126 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); | ||
127 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); | ||
128 | |||
129 | if ((mcs_user == NO_NSS_SUPPORT) || | ||
130 | (mcs_resp == NO_NSS_SUPPORT)) | ||
131 | SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT); | ||
132 | else | ||
133 | SET_VHTNSSMCS(mcs_map_result, nss, | ||
134 | min(mcs_user, mcs_resp)); | ||
135 | } | ||
136 | |||
137 | vht_cap->vht_cap.supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result); | ||
138 | |||
139 | tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); | ||
140 | vht_cap->vht_cap.supp_mcs.rx_highest = cpu_to_le16(tmp); | ||
141 | |||
142 | /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */ | ||
143 | mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support); | ||
144 | mcs_map_resp = le16_to_cpu(vht_cap->vht_cap.supp_mcs.tx_mcs_map); | ||
145 | mcs_map_result = 0; | ||
146 | |||
147 | for (nss = 1; nss <= 8; nss++) { | ||
148 | mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); | ||
149 | mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); | ||
150 | if ((mcs_user == NO_NSS_SUPPORT) || | ||
151 | (mcs_resp == NO_NSS_SUPPORT)) | ||
152 | SET_VHTNSSMCS(mcs_map_result, nss, NO_NSS_SUPPORT); | ||
153 | else | ||
154 | SET_VHTNSSMCS(mcs_map_result, nss, | ||
155 | min(mcs_user, mcs_resp)); | ||
156 | } | ||
157 | |||
158 | vht_cap->vht_cap.supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result); | ||
159 | |||
160 | tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); | ||
161 | vht_cap->vht_cap.supp_mcs.tx_highest = cpu_to_le16(tmp); | ||
162 | |||
163 | return; | ||
164 | } | ||
165 | |||
166 | int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | ||
167 | struct mwifiex_bssdescriptor *bss_desc, | ||
168 | u8 **buffer) | ||
169 | { | ||
170 | struct mwifiex_ie_types_vhtcap *vht_cap; | ||
171 | struct mwifiex_ie_types_oper_mode_ntf *oper_ntf; | ||
172 | struct ieee_types_oper_mode_ntf *ieee_oper_ntf; | ||
173 | struct mwifiex_ie_types_vht_oper *vht_op; | ||
174 | struct mwifiex_adapter *adapter = priv->adapter; | ||
175 | u8 supp_chwd_set; | ||
176 | u32 usr_vht_cap_info; | ||
177 | int ret_len = 0; | ||
178 | |||
179 | if (bss_desc->bss_band & BAND_A) | ||
180 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; | ||
181 | else | ||
182 | usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; | ||
183 | |||
184 | /* VHT Capabilities IE */ | ||
185 | if (bss_desc->bcn_vht_cap) { | ||
186 | vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer; | ||
187 | memset(vht_cap, 0, sizeof(*vht_cap)); | ||
188 | vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY); | ||
189 | vht_cap->header.len = | ||
190 | cpu_to_le16(sizeof(struct ieee80211_vht_cap)); | ||
191 | memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header), | ||
192 | (u8 *)bss_desc->bcn_vht_cap + | ||
193 | sizeof(struct ieee_types_header), | ||
194 | le16_to_cpu(vht_cap->header.len)); | ||
195 | |||
196 | mwifiex_fill_vht_cap_tlv(priv, vht_cap, bss_desc->bss_band); | ||
197 | *buffer += sizeof(*vht_cap); | ||
198 | ret_len += sizeof(*vht_cap); | ||
199 | } | ||
200 | |||
201 | /* VHT Operation IE */ | ||
202 | if (bss_desc->bcn_vht_oper) { | ||
203 | if (priv->bss_mode == HostCmd_BSS_MODE_IBSS) { | ||
204 | vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer; | ||
205 | memset(vht_op, 0, sizeof(*vht_op)); | ||
206 | vht_op->header.type = | ||
207 | cpu_to_le16(WLAN_EID_VHT_OPERATION); | ||
208 | vht_op->header.len = cpu_to_le16(sizeof(*vht_op) - | ||
209 | sizeof(struct mwifiex_ie_types_header)); | ||
210 | memcpy((u8 *)vht_op + | ||
211 | sizeof(struct mwifiex_ie_types_header), | ||
212 | (u8 *)bss_desc->bcn_vht_oper + | ||
213 | sizeof(struct ieee_types_header), | ||
214 | le16_to_cpu(vht_op->header.len)); | ||
215 | |||
216 | /* negotiate the channel width and central freq | ||
217 | * and keep the central freq as the peer suggests | ||
218 | */ | ||
219 | supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info); | ||
220 | |||
221 | switch (supp_chwd_set) { | ||
222 | case 0: | ||
223 | vht_op->chan_width = | ||
224 | min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ, | ||
225 | bss_desc->bcn_vht_oper->chan_width); | ||
226 | break; | ||
227 | case 1: | ||
228 | vht_op->chan_width = | ||
229 | min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ, | ||
230 | bss_desc->bcn_vht_oper->chan_width); | ||
231 | break; | ||
232 | case 2: | ||
233 | vht_op->chan_width = | ||
234 | min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ, | ||
235 | bss_desc->bcn_vht_oper->chan_width); | ||
236 | break; | ||
237 | default: | ||
238 | vht_op->chan_width = | ||
239 | IEEE80211_VHT_CHANWIDTH_USE_HT; | ||
240 | break; | ||
241 | } | ||
242 | |||
243 | *buffer += sizeof(*vht_op); | ||
244 | ret_len += sizeof(*vht_op); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /* Operating Mode Notification IE */ | ||
249 | if (bss_desc->oper_mode) { | ||
250 | ieee_oper_ntf = bss_desc->oper_mode; | ||
251 | oper_ntf = (void *)*buffer; | ||
252 | memset(oper_ntf, 0, sizeof(*oper_ntf)); | ||
253 | oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF); | ||
254 | oper_ntf->header.len = cpu_to_le16(sizeof(u8)); | ||
255 | oper_ntf->oper_mode = ieee_oper_ntf->oper_mode; | ||
256 | *buffer += sizeof(*oper_ntf); | ||
257 | ret_len += sizeof(*oper_ntf); | ||
258 | } | ||
259 | |||
260 | return ret_len; | ||
261 | } | ||
diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h new file mode 100644 index 000000000000..80fd1ba46200 --- /dev/null +++ b/drivers/net/wireless/mwifiex/11ac.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: 802.11ac | ||
3 | * | ||
4 | * Copyright (C) 2013, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
17 | * this warranty disclaimer. | ||
18 | */ | ||
19 | |||
20 | #ifndef _MWIFIEX_11AC_H_ | ||
21 | #define _MWIFIEX_11AC_H_ | ||
22 | |||
23 | int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, | ||
24 | struct mwifiex_bssdescriptor *bss_desc, | ||
25 | u8 **buffer); | ||
26 | #endif /* _MWIFIEX_11AC_H_ */ | ||
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 25596ab0c576..45f19716687e 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -250,7 +250,8 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, | |||
250 | * - Setting HT Tx capability and HT Tx information fields | 250 | * - Setting HT Tx capability and HT Tx information fields |
251 | * - Ensuring correct endian-ness | 251 | * - Ensuring correct endian-ness |
252 | */ | 252 | */ |
253 | int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, | 253 | int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, |
254 | struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
254 | struct mwifiex_ds_11n_tx_cfg *txcfg) | 255 | struct mwifiex_ds_11n_tx_cfg *txcfg) |
255 | { | 256 | { |
256 | struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; | 257 | struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; |
@@ -260,6 +261,10 @@ int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, | |||
260 | htcfg->action = cpu_to_le16(cmd_action); | 261 | htcfg->action = cpu_to_le16(cmd_action); |
261 | htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); | 262 | htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); |
262 | htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); | 263 | htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); |
264 | |||
265 | if (priv->adapter->is_hw_11ac_capable) | ||
266 | htcfg->misc_config = cpu_to_le16(txcfg->misc_config); | ||
267 | |||
263 | return 0; | 268 | return 0; |
264 | } | 269 | } |
265 | 270 | ||
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 29a4c02479d6..375db01442bf 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -28,9 +28,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv, | |||
28 | struct host_cmd_ds_command *resp); | 28 | struct host_cmd_ds_command *resp); |
29 | int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | 29 | int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, |
30 | struct host_cmd_ds_command *resp); | 30 | struct host_cmd_ds_command *resp); |
31 | int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, | 31 | int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, |
32 | struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
32 | struct mwifiex_ds_11n_tx_cfg *txcfg); | 33 | struct mwifiex_ds_11n_tx_cfg *txcfg); |
33 | |||
34 | int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, | 34 | int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, |
35 | struct mwifiex_bssdescriptor *bss_desc, | 35 | struct mwifiex_bssdescriptor *bss_desc, |
36 | u8 **buffer); | 36 | u8 **buffer); |
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index dd0410d2d465..97b245cbafd8 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
@@ -23,6 +23,7 @@ mwifiex-y += util.o | |||
23 | mwifiex-y += txrx.o | 23 | mwifiex-y += txrx.o |
24 | mwifiex-y += wmm.o | 24 | mwifiex-y += wmm.o |
25 | mwifiex-y += 11n.o | 25 | mwifiex-y += 11n.o |
26 | mwifiex-y += 11ac.o | ||
26 | mwifiex-y += 11n_aggr.o | 27 | mwifiex-y += 11n_aggr.o |
27 | mwifiex-y += 11n_rxreorder.o | 28 | mwifiex-y += 11n_rxreorder.o |
28 | mwifiex-y += scan.o | 29 | mwifiex-y += scan.o |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index dc5357c0098f..a44023a7bd57 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -834,6 +834,66 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
834 | return ret; | 834 | return ret; |
835 | } | 835 | } |
836 | 836 | ||
837 | static void | ||
838 | mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, | ||
839 | struct rate_info *rate) | ||
840 | { | ||
841 | struct mwifiex_adapter *adapter = priv->adapter; | ||
842 | |||
843 | if (adapter->is_hw_11ac_capable) { | ||
844 | /* bit[1-0]: 00=LG 01=HT 10=VHT */ | ||
845 | if (tx_htinfo & BIT(0)) { | ||
846 | /* HT */ | ||
847 | rate->mcs = priv->tx_rate; | ||
848 | rate->flags |= RATE_INFO_FLAGS_MCS; | ||
849 | } | ||
850 | if (tx_htinfo & BIT(1)) { | ||
851 | /* VHT */ | ||
852 | rate->mcs = priv->tx_rate & 0x0F; | ||
853 | rate->flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
854 | } | ||
855 | |||
856 | if (tx_htinfo & (BIT(1) | BIT(0))) { | ||
857 | /* HT or VHT */ | ||
858 | switch (tx_htinfo & (BIT(3) | BIT(2))) { | ||
859 | case 0: | ||
860 | /* This will be 20MHz */ | ||
861 | break; | ||
862 | case (BIT(2)): | ||
863 | rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
864 | break; | ||
865 | case (BIT(3)): | ||
866 | rate->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
867 | break; | ||
868 | case (BIT(3) | BIT(2)): | ||
869 | rate->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
870 | break; | ||
871 | } | ||
872 | |||
873 | if (tx_htinfo & BIT(4)) | ||
874 | rate->flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
875 | |||
876 | if ((priv->tx_rate >> 4) == 1) | ||
877 | rate->nss = 2; | ||
878 | else | ||
879 | rate->nss = 1; | ||
880 | } | ||
881 | } else { | ||
882 | /* | ||
883 | * Bit 0 in tx_htinfo indicates that current Tx rate | ||
884 | * is 11n rate. Valid MCS index values for us are 0 to 15. | ||
885 | */ | ||
886 | if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { | ||
887 | rate->mcs = priv->tx_rate; | ||
888 | rate->flags |= RATE_INFO_FLAGS_MCS; | ||
889 | if (tx_htinfo & BIT(1)) | ||
890 | rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
891 | if (tx_htinfo & BIT(2)) | ||
892 | rate->flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
893 | } | ||
894 | } | ||
895 | } | ||
896 | |||
837 | /* | 897 | /* |
838 | * This function dumps the station information on a buffer. | 898 | * This function dumps the station information on a buffer. |
839 | * | 899 | * |
@@ -873,20 +933,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, | |||
873 | HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, | 933 | HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, |
874 | &priv->dtim_period); | 934 | &priv->dtim_period); |
875 | 935 | ||
876 | /* | 936 | mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate); |
877 | * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid | ||
878 | * MCS index values for us are 0 to 15. | ||
879 | */ | ||
880 | if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { | ||
881 | sinfo->txrate.mcs = priv->tx_rate; | ||
882 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | ||
883 | /* 40MHz rate */ | ||
884 | if (priv->tx_htinfo & BIT(1)) | ||
885 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
886 | /* SGI enabled */ | ||
887 | if (priv->tx_htinfo & BIT(2)) | ||
888 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
889 | } | ||
890 | 937 | ||
891 | sinfo->signal_avg = priv->bcn_rssi_avg; | 938 | sinfo->signal_avg = priv->bcn_rssi_avg; |
892 | sinfo->rx_bytes = priv->stats.rx_bytes; | 939 | sinfo->rx_bytes = priv->stats.rx_bytes; |
@@ -1295,20 +1342,22 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
1295 | /* Set appropriate bands */ | 1342 | /* Set appropriate bands */ |
1296 | if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { | 1343 | if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { |
1297 | bss_cfg->band_cfg = BAND_CONFIG_BG; | 1344 | bss_cfg->band_cfg = BAND_CONFIG_BG; |
1345 | config_bands = BAND_B | BAND_G; | ||
1298 | 1346 | ||
1299 | if (cfg80211_get_chandef_type(¶ms->chandef) == | 1347 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) |
1300 | NL80211_CHAN_NO_HT) | 1348 | config_bands |= BAND_GN; |
1301 | config_bands = BAND_B | BAND_G; | 1349 | |
1302 | else | 1350 | if (params->chandef.width > NL80211_CHAN_WIDTH_40) |
1303 | config_bands = BAND_B | BAND_G | BAND_GN; | 1351 | config_bands |= BAND_GAC; |
1304 | } else { | 1352 | } else { |
1305 | bss_cfg->band_cfg = BAND_CONFIG_A; | 1353 | bss_cfg->band_cfg = BAND_CONFIG_A; |
1354 | config_bands = BAND_A; | ||
1306 | 1355 | ||
1307 | if (cfg80211_get_chandef_type(¶ms->chandef) == | 1356 | if (params->chandef.width > NL80211_CHAN_WIDTH_20_NOHT) |
1308 | NL80211_CHAN_NO_HT) | 1357 | config_bands |= BAND_AN; |
1309 | config_bands = BAND_A; | 1358 | |
1310 | else | 1359 | if (params->chandef.width > NL80211_CHAN_WIDTH_40) |
1311 | config_bands = BAND_AN | BAND_A; | 1360 | config_bands |= BAND_AAC; |
1312 | } | 1361 | } |
1313 | 1362 | ||
1314 | if (!((config_bands | priv->adapter->fw_bands) & | 1363 | if (!((config_bands | priv->adapter->fw_bands) & |
@@ -1879,6 +1928,79 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1879 | return 0; | 1928 | return 0; |
1880 | } | 1929 | } |
1881 | 1930 | ||
1931 | static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, | ||
1932 | struct mwifiex_private *priv) | ||
1933 | { | ||
1934 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1935 | u32 vht_cap = 0, cap = adapter->hw_dot_11ac_dev_cap; | ||
1936 | |||
1937 | vht_info->vht_supported = true; | ||
1938 | |||
1939 | switch (GET_VHTCAP_MAXMPDULEN(cap)) { | ||
1940 | case 0x00: | ||
1941 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; | ||
1942 | break; | ||
1943 | case 0x01: | ||
1944 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | ||
1945 | break; | ||
1946 | case 0x10: | ||
1947 | vht_cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454; | ||
1948 | break; | ||
1949 | default: | ||
1950 | dev_err(adapter->dev, "unsupported MAX MPDU len\n"); | ||
1951 | break; | ||
1952 | } | ||
1953 | |||
1954 | if (ISSUPP_11ACVHTHTCVHT(cap)) | ||
1955 | vht_cap |= IEEE80211_VHT_CAP_HTC_VHT; | ||
1956 | |||
1957 | if (ISSUPP_11ACVHTTXOPPS(cap)) | ||
1958 | vht_cap |= IEEE80211_VHT_CAP_VHT_TXOP_PS; | ||
1959 | |||
1960 | if (ISSUPP_11ACMURXBEAMFORMEE(cap)) | ||
1961 | vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE; | ||
1962 | |||
1963 | if (ISSUPP_11ACMUTXBEAMFORMEE(cap)) | ||
1964 | vht_cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE; | ||
1965 | |||
1966 | if (ISSUPP_11ACSUBEAMFORMER(cap)) | ||
1967 | vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE; | ||
1968 | |||
1969 | if (ISSUPP_11ACSUBEAMFORMEE(cap)) | ||
1970 | vht_cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | ||
1971 | |||
1972 | if (ISSUPP_11ACRXSTBC(cap)) | ||
1973 | vht_cap |= IEEE80211_VHT_CAP_RXSTBC_1; | ||
1974 | |||
1975 | if (ISSUPP_11ACTXSTBC(cap)) | ||
1976 | vht_cap |= IEEE80211_VHT_CAP_TXSTBC; | ||
1977 | |||
1978 | if (ISSUPP_11ACSGI160(cap)) | ||
1979 | vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_160; | ||
1980 | |||
1981 | if (ISSUPP_11ACSGI80(cap)) | ||
1982 | vht_cap |= IEEE80211_VHT_CAP_SHORT_GI_80; | ||
1983 | |||
1984 | if (ISSUPP_11ACLDPC(cap)) | ||
1985 | vht_cap |= IEEE80211_VHT_CAP_RXLDPC; | ||
1986 | |||
1987 | if (ISSUPP_11ACBW8080(cap)) | ||
1988 | vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; | ||
1989 | |||
1990 | if (ISSUPP_11ACBW160(cap)) | ||
1991 | vht_cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
1992 | |||
1993 | vht_info->cap = vht_cap; | ||
1994 | |||
1995 | /* Update MCS support for VHT */ | ||
1996 | vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( | ||
1997 | adapter->hw_dot_11ac_mcs_support & 0xFFFF); | ||
1998 | vht_info->vht_mcs.rx_highest = 0; | ||
1999 | vht_info->vht_mcs.tx_mcs_map = cpu_to_le16( | ||
2000 | adapter->hw_dot_11ac_mcs_support >> 16); | ||
2001 | vht_info->vht_mcs.tx_highest = 0; | ||
2002 | } | ||
2003 | |||
1882 | /* | 2004 | /* |
1883 | * This function sets up the CFG802.11 specific HT capability fields | 2005 | * This function sets up the CFG802.11 specific HT capability fields |
1884 | * with default values. | 2006 | * with default values. |
@@ -2092,11 +2214,18 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2092 | priv->netdev = dev; | 2214 | priv->netdev = dev; |
2093 | 2215 | ||
2094 | mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); | 2216 | mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); |
2217 | if (adapter->is_hw_11ac_capable) | ||
2218 | mwifiex_setup_vht_caps( | ||
2219 | &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv); | ||
2095 | 2220 | ||
2096 | if (adapter->config_bands & BAND_A) | 2221 | if (adapter->config_bands & BAND_A) |
2097 | mwifiex_setup_ht_caps( | 2222 | mwifiex_setup_ht_caps( |
2098 | &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); | 2223 | &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); |
2099 | 2224 | ||
2225 | if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable) | ||
2226 | mwifiex_setup_vht_caps( | ||
2227 | &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); | ||
2228 | |||
2100 | dev_net_set(dev, wiphy_net(wiphy)); | 2229 | dev_net_set(dev, wiphy_net(wiphy)); |
2101 | dev->ieee80211_ptr = priv->wdev; | 2230 | dev->ieee80211_ptr = priv->wdev; |
2102 | dev->ieee80211_ptr->iftype = priv->bss_mode; | 2231 | dev->ieee80211_ptr->iftype = priv->bss_mode; |
diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c index f69300f93f42..988552dece75 100644 --- a/drivers/net/wireless/mwifiex/cfp.c +++ b/drivers/net/wireless/mwifiex/cfp.c | |||
@@ -106,8 +106,8 @@ u8 *mwifiex_11d_code_2_region(u8 code) | |||
106 | * This function maps an index in supported rates table into | 106 | * This function maps an index in supported rates table into |
107 | * the corresponding data rate. | 107 | * the corresponding data rate. |
108 | */ | 108 | */ |
109 | u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index, | 109 | u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, |
110 | u8 ht_info) | 110 | u8 index, u8 ht_info) |
111 | { | 111 | { |
112 | /* | 112 | /* |
113 | * For every mcs_rate line, the first 8 bytes are for stream 1x1, | 113 | * For every mcs_rate line, the first 8 bytes are for stream 1x1, |
@@ -130,10 +130,155 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index, | |||
130 | { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, | 130 | { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, |
131 | 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } | 131 | 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } |
132 | }; | 132 | }; |
133 | /* AC rates */ | ||
134 | u16 ac_mcs_rate_nss1[8][10] = { | ||
135 | /* LG 160M */ | ||
136 | { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, | ||
137 | 0x492, 0x57C, 0x618 }, | ||
138 | |||
139 | /* SG 160M */ | ||
140 | { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, | ||
141 | 0x514, 0x618, 0x6C6 }, | ||
142 | |||
143 | /* LG 80M */ | ||
144 | { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, | ||
145 | 0x249, 0x2BE, 0x30C }, | ||
146 | |||
147 | /* SG 80M */ | ||
148 | { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, | ||
149 | 0x28A, 0x30C, 0x363 }, | ||
150 | |||
151 | /* LG 40M */ | ||
152 | { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, | ||
153 | 0x10E, 0x144, 0x168 }, | ||
154 | |||
155 | /* SG 40M */ | ||
156 | { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, | ||
157 | 0x12C, 0x168, 0x190 }, | ||
158 | |||
159 | /* LG 20M */ | ||
160 | { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 }, | ||
161 | |||
162 | /* SG 20M */ | ||
163 | { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 }, | ||
164 | }; | ||
165 | /* NSS2 note: the value in the table is 2 multiplier of the actual | ||
166 | * rate | ||
167 | */ | ||
168 | u16 ac_mcs_rate_nss2[8][10] = { | ||
169 | /* LG 160M */ | ||
170 | { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, | ||
171 | 0x924, 0xAF8, 0xC30 }, | ||
172 | |||
173 | /* SG 160M */ | ||
174 | { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, | ||
175 | 0xA28, 0xC30, 0xD8B }, | ||
176 | |||
177 | /* LG 80M */ | ||
178 | { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, | ||
179 | 0x492, 0x57C, 0x618 }, | ||
180 | |||
181 | /* SG 80M */ | ||
182 | { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, | ||
183 | 0x514, 0x618, 0x6C6 }, | ||
184 | |||
185 | /* LG 40M */ | ||
186 | { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, | ||
187 | 0x21C, 0x288, 0x2D0 }, | ||
188 | |||
189 | /* SG 40M */ | ||
190 | { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, | ||
191 | 0x258, 0x2D0, 0x320 }, | ||
192 | |||
193 | /* LG 20M */ | ||
194 | { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, | ||
195 | 0x138, 0x00 }, | ||
196 | |||
197 | /* SG 20M */ | ||
198 | { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, | ||
199 | 0x15B, 0x00 }, | ||
200 | }; | ||
201 | u32 rate = 0; | ||
202 | u8 mcs_index = 0; | ||
203 | u8 bw = 0; | ||
204 | u8 gi = 0; | ||
205 | |||
206 | if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) { | ||
207 | mcs_index = min(index & 0xF, 9); | ||
208 | |||
209 | /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */ | ||
210 | bw = (ht_info & 0xC) >> 2; | ||
211 | |||
212 | /* LGI: gi =0, SGI: gi = 1 */ | ||
213 | gi = (ht_info & 0x10) >> 4; | ||
214 | |||
215 | if ((index >> 4) == 1) /* NSS = 2 */ | ||
216 | rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index]; | ||
217 | else /* NSS = 1 */ | ||
218 | rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index]; | ||
219 | } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) { | ||
220 | /* 20M: bw=0, 40M: bw=1 */ | ||
221 | bw = (ht_info & 0xC) >> 2; | ||
222 | |||
223 | /* LGI: gi =0, SGI: gi = 1 */ | ||
224 | gi = (ht_info & 0x10) >> 4; | ||
225 | |||
226 | if (index == MWIFIEX_RATE_BITMAP_MCS0) { | ||
227 | if (gi == 1) | ||
228 | rate = 0x0D; /* MCS 32 SGI rate */ | ||
229 | else | ||
230 | rate = 0x0C; /* MCS 32 LGI rate */ | ||
231 | } else if (index < 16) { | ||
232 | if ((bw == 1) || (bw == 0)) | ||
233 | rate = mcs_rate[2 * (1 - bw) + gi][index]; | ||
234 | else | ||
235 | rate = mwifiex_data_rates[0]; | ||
236 | } else { | ||
237 | rate = mwifiex_data_rates[0]; | ||
238 | } | ||
239 | } else { | ||
240 | /* 11n non-HT rates */ | ||
241 | if (index >= MWIFIEX_SUPPORTED_RATES_EXT) | ||
242 | index = 0; | ||
243 | rate = mwifiex_data_rates[index]; | ||
244 | } | ||
245 | |||
246 | return rate; | ||
247 | } | ||
248 | |||
249 | /* This function maps an index in supported rates table into | ||
250 | * the corresponding data rate. | ||
251 | */ | ||
252 | u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, | ||
253 | u8 index, u8 ht_info) | ||
254 | { | ||
255 | /* For every mcs_rate line, the first 8 bytes are for stream 1x1, | ||
256 | * and all 16 bytes are for stream 2x2. | ||
257 | */ | ||
258 | u16 mcs_rate[4][16] = { | ||
259 | /* LGI 40M */ | ||
260 | { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, | ||
261 | 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, | ||
262 | |||
263 | /* SGI 40M */ | ||
264 | { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, | ||
265 | 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, | ||
266 | |||
267 | /* LGI 20M */ | ||
268 | { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, | ||
269 | 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, | ||
270 | |||
271 | /* SGI 20M */ | ||
272 | { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, | ||
273 | 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } | ||
274 | }; | ||
133 | u32 mcs_num_supp = | 275 | u32 mcs_num_supp = |
134 | (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; | 276 | (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; |
135 | u32 rate; | 277 | u32 rate; |
136 | 278 | ||
279 | if (priv->adapter->is_hw_11ac_capable) | ||
280 | return mwifiex_index_to_acs_data_rate(priv, index, ht_info); | ||
281 | |||
137 | if (ht_info & BIT(0)) { | 282 | if (ht_info & BIT(0)) { |
138 | if (index == MWIFIEX_RATE_BITMAP_MCS0) { | 283 | if (index == MWIFIEX_RATE_BITMAP_MCS0) { |
139 | if (ht_info & BIT(2)) | 284 | if (ht_info & BIT(2)) |
@@ -269,6 +414,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
269 | { | 414 | { |
270 | u32 k = 0; | 415 | u32 k = 0; |
271 | struct mwifiex_adapter *adapter = priv->adapter; | 416 | struct mwifiex_adapter *adapter = priv->adapter; |
417 | |||
272 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { | 418 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { |
273 | switch (adapter->config_bands) { | 419 | switch (adapter->config_bands) { |
274 | case BAND_B: | 420 | case BAND_B: |
@@ -279,6 +425,7 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
279 | break; | 425 | break; |
280 | case BAND_G: | 426 | case BAND_G: |
281 | case BAND_G | BAND_GN: | 427 | case BAND_G | BAND_GN: |
428 | case BAND_G | BAND_GN | BAND_GAC: | ||
282 | dev_dbg(adapter->dev, "info: infra band=%d " | 429 | dev_dbg(adapter->dev, "info: infra band=%d " |
283 | "supported_rates_g\n", adapter->config_bands); | 430 | "supported_rates_g\n", adapter->config_bands); |
284 | k = mwifiex_copy_rates(rates, k, supported_rates_g, | 431 | k = mwifiex_copy_rates(rates, k, supported_rates_g, |
@@ -288,7 +435,11 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
288 | case BAND_A | BAND_B | BAND_G: | 435 | case BAND_A | BAND_B | BAND_G: |
289 | case BAND_A | BAND_B: | 436 | case BAND_A | BAND_B: |
290 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: | 437 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: |
438 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: | ||
439 | case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | | ||
440 | BAND_AAC | BAND_GAC: | ||
291 | case BAND_B | BAND_G | BAND_GN: | 441 | case BAND_B | BAND_G | BAND_GN: |
442 | case BAND_B | BAND_G | BAND_GN | BAND_GAC: | ||
292 | dev_dbg(adapter->dev, "info: infra band=%d " | 443 | dev_dbg(adapter->dev, "info: infra band=%d " |
293 | "supported_rates_bg\n", adapter->config_bands); | 444 | "supported_rates_bg\n", adapter->config_bands); |
294 | k = mwifiex_copy_rates(rates, k, supported_rates_bg, | 445 | k = mwifiex_copy_rates(rates, k, supported_rates_bg, |
@@ -301,14 +452,18 @@ u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) | |||
301 | k = mwifiex_copy_rates(rates, k, supported_rates_a, | 452 | k = mwifiex_copy_rates(rates, k, supported_rates_a, |
302 | sizeof(supported_rates_a)); | 453 | sizeof(supported_rates_a)); |
303 | break; | 454 | break; |
455 | case BAND_AN: | ||
304 | case BAND_A | BAND_AN: | 456 | case BAND_A | BAND_AN: |
457 | case BAND_A | BAND_AN | BAND_AAC: | ||
305 | case BAND_A | BAND_G | BAND_AN | BAND_GN: | 458 | case BAND_A | BAND_G | BAND_AN | BAND_GN: |
459 | case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC: | ||
306 | dev_dbg(adapter->dev, "info: infra band=%d " | 460 | dev_dbg(adapter->dev, "info: infra band=%d " |
307 | "supported_rates_a\n", adapter->config_bands); | 461 | "supported_rates_a\n", adapter->config_bands); |
308 | k = mwifiex_copy_rates(rates, k, supported_rates_a, | 462 | k = mwifiex_copy_rates(rates, k, supported_rates_a, |
309 | sizeof(supported_rates_a)); | 463 | sizeof(supported_rates_a)); |
310 | break; | 464 | break; |
311 | case BAND_GN: | 465 | case BAND_GN: |
466 | case BAND_GN | BAND_GAC: | ||
312 | dev_dbg(adapter->dev, "info: infra band=%d " | 467 | dev_dbg(adapter->dev, "info: infra band=%d " |
313 | "supported_rates_n\n", adapter->config_bands); | 468 | "supported_rates_n\n", adapter->config_bands); |
314 | k = mwifiex_copy_rates(rates, k, supported_rates_n, | 469 | k = mwifiex_copy_rates(rates, k, supported_rates_n, |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 2b125beecf2c..20a6c5555873 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "main.h" | 24 | #include "main.h" |
25 | #include "wmm.h" | 25 | #include "wmm.h" |
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11ac.h" | ||
27 | 28 | ||
28 | /* | 29 | /* |
29 | * This function initializes a command node. | 30 | * This function initializes a command node. |
@@ -1465,6 +1466,24 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
1465 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); | 1466 | adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); |
1466 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); | 1467 | adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); |
1467 | 1468 | ||
1469 | if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { | ||
1470 | adapter->is_hw_11ac_capable = true; | ||
1471 | |||
1472 | /* Copy 11AC cap */ | ||
1473 | adapter->hw_dot_11ac_dev_cap = | ||
1474 | le32_to_cpu(hw_spec->dot_11ac_dev_cap); | ||
1475 | adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap; | ||
1476 | adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap; | ||
1477 | |||
1478 | /* Copy 11AC mcs */ | ||
1479 | adapter->hw_dot_11ac_mcs_support = | ||
1480 | le32_to_cpu(hw_spec->dot_11ac_mcs_support); | ||
1481 | adapter->usr_dot_11ac_mcs_support = | ||
1482 | adapter->hw_dot_11ac_mcs_support; | ||
1483 | } else { | ||
1484 | adapter->is_hw_11ac_capable = false; | ||
1485 | } | ||
1486 | |||
1468 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", | 1487 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: fw_release_number- %#x\n", |
1469 | adapter->fw_release_number); | 1488 | adapter->fw_release_number); |
1470 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", | 1489 | dev_dbg(adapter->dev, "info: GET_HW_SPEC: permanent addr: %pM\n", |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index ebe2f6a7984c..25acb0682c56 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -49,13 +49,23 @@ struct tx_packet_hdr { | |||
49 | #define A_SUPPORTED_RATES 9 | 49 | #define A_SUPPORTED_RATES 9 |
50 | #define HOSTCMD_SUPPORTED_RATES 14 | 50 | #define HOSTCMD_SUPPORTED_RATES 14 |
51 | #define N_SUPPORTED_RATES 3 | 51 | #define N_SUPPORTED_RATES 3 |
52 | #define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN) | 52 | #define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN | \ |
53 | BAND_AN | BAND_GAC | BAND_AAC) | ||
53 | 54 | ||
54 | #define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11)) | 55 | #define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \ |
56 | BIT(12) | BIT(13)) | ||
55 | #define IS_SUPPORT_MULTI_BANDS(adapter) \ | 57 | #define IS_SUPPORT_MULTI_BANDS(adapter) \ |
56 | (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) | 58 | (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) |
59 | |||
60 | /* shift bit 12 and bit 13 in fw_cap_info from the firmware to bit 13 and 14 | ||
61 | * for 11ac so that bit 11 is for GN, bit 12 for AN, bit 13 for GAC, and bit | ||
62 | * bit 14 for AAC, in order to be compatible with the band capability | ||
63 | * defined in the driver after right shift of 8 bits. | ||
64 | */ | ||
57 | #define GET_FW_DEFAULT_BANDS(adapter) \ | 65 | #define GET_FW_DEFAULT_BANDS(adapter) \ |
58 | ((adapter->fw_cap_info >> 8) & ALL_802_11_BANDS) | 66 | (((((adapter->fw_cap_info & 0x3000) << 1) | \ |
67 | (adapter->fw_cap_info & ~0xF000)) >> 8) & \ | ||
68 | ALL_802_11_BANDS) | ||
59 | 69 | ||
60 | #define HostCmd_WEP_KEY_INDEX_MASK 0x3fff | 70 | #define HostCmd_WEP_KEY_INDEX_MASK 0x3fff |
61 | 71 | ||
@@ -216,6 +226,47 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
216 | 226 | ||
217 | #define LLC_SNAP_LEN 8 | 227 | #define LLC_SNAP_LEN 8 |
218 | 228 | ||
229 | /* HW_SPEC fw_cap_info */ | ||
230 | |||
231 | #define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & (BIT(13)|BIT(14))) | ||
232 | |||
233 | #define GET_VHTCAP_MAXMPDULEN(vht_cap_info) (vht_cap_info & 0x3) | ||
234 | #define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) | ||
235 | #define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) | ||
236 | #define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ | ||
237 | (2 * (nss - 1))) | ||
238 | #define NO_NSS_SUPPORT 0x3 | ||
239 | |||
240 | /* HW_SPEC: HTC-VHT supported */ | ||
241 | #define ISSUPP_11ACVHTHTCVHT(Dot11acDevCap) (Dot11acDevCap & BIT(22)) | ||
242 | /* HW_SPEC: VHT TXOP PS support */ | ||
243 | #define ISSUPP_11ACVHTTXOPPS(Dot11acDevCap) (Dot11acDevCap & BIT(21)) | ||
244 | /* HW_SPEC: MU RX beamformee support */ | ||
245 | #define ISSUPP_11ACMURXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(20)) | ||
246 | /* HW_SPEC: MU TX beamformee support */ | ||
247 | #define ISSUPP_11ACMUTXBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(19)) | ||
248 | /* HW_SPEC: SU Beamformee support */ | ||
249 | #define ISSUPP_11ACSUBEAMFORMEE(Dot11acDevCap) (Dot11acDevCap & BIT(10)) | ||
250 | /* HW_SPEC: SU Beamformer support */ | ||
251 | #define ISSUPP_11ACSUBEAMFORMER(Dot11acDevCap) (Dot11acDevCap & BIT(9)) | ||
252 | /* HW_SPEC: Rx STBC support */ | ||
253 | #define ISSUPP_11ACRXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(8)) | ||
254 | /* HW_SPEC: Tx STBC support */ | ||
255 | #define ISSUPP_11ACTXSTBC(Dot11acDevCap) (Dot11acDevCap & BIT(7)) | ||
256 | /* HW_SPEC: Short GI support for 160MHz BW */ | ||
257 | #define ISSUPP_11ACSGI160(Dot11acDevCap) (Dot11acDevCap & BIT(6)) | ||
258 | /* HW_SPEC: Short GI support for 80MHz BW */ | ||
259 | #define ISSUPP_11ACSGI80(Dot11acDevCap) (Dot11acDevCap & BIT(5)) | ||
260 | /* HW_SPEC: LDPC coding support */ | ||
261 | #define ISSUPP_11ACLDPC(Dot11acDevCap) (Dot11acDevCap & BIT(4)) | ||
262 | /* HW_SPEC: Channel BW 20/40/80/160/80+80 MHz support */ | ||
263 | #define ISSUPP_11ACBW8080(Dot11acDevCap) (Dot11acDevCap & BIT(3)) | ||
264 | /* HW_SPEC: Channel BW 20/40/80/160 MHz support */ | ||
265 | #define ISSUPP_11ACBW160(Dot11acDevCap) (Dot11acDevCap & BIT(2)) | ||
266 | |||
267 | #define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) | ||
268 | #define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) | ||
269 | |||
219 | #define MOD_CLASS_HR_DSSS 0x03 | 270 | #define MOD_CLASS_HR_DSSS 0x03 |
220 | #define MOD_CLASS_OFDM 0x07 | 271 | #define MOD_CLASS_OFDM 0x07 |
221 | #define MOD_CLASS_HT 0x08 | 272 | #define MOD_CLASS_HT 0x08 |
@@ -455,9 +506,22 @@ struct rxpd { | |||
455 | u8 rx_rate; | 506 | u8 rx_rate; |
456 | s8 snr; | 507 | s8 snr; |
457 | s8 nf; | 508 | s8 nf; |
458 | /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 | 509 | |
510 | /* For: Non-802.11 AC cards | ||
511 | * | ||
512 | * Ht Info [Bit 0] RxRate format: LG=0, HT=1 | ||
459 | * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 | 513 | * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 |
460 | * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ | 514 | * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 |
515 | * | ||
516 | * For: 802.11 AC cards | ||
517 | * [Bit 1] [Bit 0] RxRate format: legacy rate = 00 HT = 01 VHT = 10 | ||
518 | * [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 = 00 BW40 = 01 | ||
519 | * BW80 = 10 BW160 = 11 | ||
520 | * [Bit 4] HT/VHT Guard interval LGI = 0 SGI = 1 | ||
521 | * [Bit 5] STBC support Enabled = 1 | ||
522 | * [Bit 6] LDPC support Enabled = 1 | ||
523 | * [Bit 7] Reserved | ||
524 | */ | ||
461 | u8 ht_info; | 525 | u8 ht_info; |
462 | u8 reserved; | 526 | u8 reserved; |
463 | } __packed; | 527 | } __packed; |
@@ -680,7 +744,11 @@ struct host_cmd_ds_get_hw_spec { | |||
680 | __le32 dot_11n_dev_cap; | 744 | __le32 dot_11n_dev_cap; |
681 | u8 dev_mcs_support; | 745 | u8 dev_mcs_support; |
682 | __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ | 746 | __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ |
683 | __le16 reserved_4; | 747 | __le16 mgmt_buf_count; /* mgmt IE buffer count */ |
748 | __le32 reserved_5; | ||
749 | __le32 reserved_6; | ||
750 | __le32 dot_11ac_dev_cap; | ||
751 | __le32 dot_11ac_mcs_support; | ||
684 | } __packed; | 752 | } __packed; |
685 | 753 | ||
686 | struct host_cmd_ds_802_11_rssi_info { | 754 | struct host_cmd_ds_802_11_rssi_info { |
@@ -786,6 +854,12 @@ union ieee_types_phy_param_set { | |||
786 | struct ieee_types_ds_param_set ds_param_set; | 854 | struct ieee_types_ds_param_set ds_param_set; |
787 | } __packed; | 855 | } __packed; |
788 | 856 | ||
857 | struct ieee_types_oper_mode_ntf { | ||
858 | u8 element_id; | ||
859 | u8 len; | ||
860 | u8 oper_mode; | ||
861 | } __packed; | ||
862 | |||
789 | struct host_cmd_ds_802_11_ad_hoc_start { | 863 | struct host_cmd_ds_802_11_ad_hoc_start { |
790 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 864 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
791 | u8 bss_mode; | 865 | u8 bss_mode; |
@@ -846,11 +920,27 @@ struct host_cmd_ds_802_11_get_log { | |||
846 | __le32 wep_icv_err_cnt[4]; | 920 | __le32 wep_icv_err_cnt[4]; |
847 | }; | 921 | }; |
848 | 922 | ||
923 | /* Enumeration for rate format */ | ||
924 | enum _mwifiex_rate_format { | ||
925 | MWIFIEX_RATE_FORMAT_LG = 0, | ||
926 | MWIFIEX_RATE_FORMAT_HT, | ||
927 | MWIFIEX_RATE_FORMAT_VHT, | ||
928 | MWIFIEX_RATE_FORMAT_AUTO = 0xFF, | ||
929 | }; | ||
930 | |||
849 | struct host_cmd_ds_tx_rate_query { | 931 | struct host_cmd_ds_tx_rate_query { |
850 | u8 tx_rate; | 932 | u8 tx_rate; |
851 | /* Ht Info [Bit 0] RxRate format: LG=0, HT=1 | 933 | /* Tx Rate Info: For 802.11 AC cards |
934 | * | ||
935 | * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2 | ||
936 | * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3 | ||
937 | * [Bit 4] HT/VHT Guard Interval: LGI = 0, SGI = 1 | ||
938 | * | ||
939 | * For non-802.11 AC cards | ||
940 | * Ht Info [Bit 0] RxRate format: LG=0, HT=1 | ||
852 | * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 | 941 | * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 |
853 | * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 */ | 942 | * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 |
943 | */ | ||
854 | u8 ht_info; | 944 | u8 ht_info; |
855 | } __packed; | 945 | } __packed; |
856 | 946 | ||
@@ -1096,6 +1186,7 @@ struct host_cmd_ds_11n_cfg { | |||
1096 | __le16 action; | 1186 | __le16 action; |
1097 | __le16 ht_tx_cap; | 1187 | __le16 ht_tx_cap; |
1098 | __le16 ht_tx_info; | 1188 | __le16 ht_tx_info; |
1189 | __le16 misc_config; /* Needed for 802.11AC cards only */ | ||
1099 | } __packed; | 1190 | } __packed; |
1100 | 1191 | ||
1101 | struct host_cmd_ds_txbuf_cfg { | 1192 | struct host_cmd_ds_txbuf_cfg { |
@@ -1183,6 +1274,26 @@ struct mwifiex_ie_types_htcap { | |||
1183 | struct ieee80211_ht_cap ht_cap; | 1274 | struct ieee80211_ht_cap ht_cap; |
1184 | } __packed; | 1275 | } __packed; |
1185 | 1276 | ||
1277 | struct mwifiex_ie_types_vhtcap { | ||
1278 | struct mwifiex_ie_types_header header; | ||
1279 | struct ieee80211_vht_cap vht_cap; | ||
1280 | } __packed; | ||
1281 | |||
1282 | struct mwifiex_ie_types_oper_mode_ntf { | ||
1283 | struct mwifiex_ie_types_header header; | ||
1284 | u8 oper_mode; | ||
1285 | } __packed; | ||
1286 | |||
1287 | /* VHT Operations IE */ | ||
1288 | struct mwifiex_ie_types_vht_oper { | ||
1289 | struct mwifiex_ie_types_header header; | ||
1290 | u8 chan_width; | ||
1291 | u8 chan_center_freq_1; | ||
1292 | u8 chan_center_freq_2; | ||
1293 | /* Basic MCS set map, each 2 bits stands for a NSS */ | ||
1294 | u16 basic_mcs_map; | ||
1295 | } __packed; | ||
1296 | |||
1186 | struct mwifiex_ie_types_wmmcap { | 1297 | struct mwifiex_ie_types_wmmcap { |
1187 | struct mwifiex_ie_types_header header; | 1298 | struct mwifiex_ie_types_header header; |
1188 | struct mwifiex_types_wmm_info wmm_info; | 1299 | struct mwifiex_types_wmm_info wmm_info; |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index f3d9d0445529..d85e6eb1f58a 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -60,6 +60,8 @@ enum { | |||
60 | BAND_A = 4, | 60 | BAND_A = 4, |
61 | BAND_GN = 8, | 61 | BAND_GN = 8, |
62 | BAND_AN = 16, | 62 | BAND_AN = 16, |
63 | BAND_GAC = 32, | ||
64 | BAND_AAC = 64, | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | #define MWIFIEX_WPA_PASSHPHRASE_LEN 64 | 67 | #define MWIFIEX_WPA_PASSHPHRASE_LEN 64 |
@@ -103,6 +105,7 @@ struct mwifiex_uap_bss_param { | |||
103 | struct wpa_param wpa_cfg; | 105 | struct wpa_param wpa_cfg; |
104 | struct wep_key wep_cfg[NUM_WEP_KEYS]; | 106 | struct wep_key wep_cfg[NUM_WEP_KEYS]; |
105 | struct ieee80211_ht_cap ht_cap; | 107 | struct ieee80211_ht_cap ht_cap; |
108 | struct ieee80211_vht_cap vht_cap; | ||
106 | u8 rates[MWIFIEX_SUPPORTED_RATES]; | 109 | u8 rates[MWIFIEX_SUPPORTED_RATES]; |
107 | u32 sta_ao_timer; | 110 | u32 sta_ao_timer; |
108 | u32 ps_sta_ao_timer; | 111 | u32 ps_sta_ao_timer; |
@@ -272,6 +275,7 @@ struct mwifiex_ds_pm_cfg { | |||
272 | struct mwifiex_ds_11n_tx_cfg { | 275 | struct mwifiex_ds_11n_tx_cfg { |
273 | u16 tx_htcap; | 276 | u16 tx_htcap; |
274 | u16 tx_htinfo; | 277 | u16 tx_htinfo; |
278 | u16 misc_config; /* Needed for 802.11AC cards only */ | ||
275 | }; | 279 | }; |
276 | 280 | ||
277 | struct mwifiex_ds_11n_amsdu_aggr_ctrl { | 281 | struct mwifiex_ds_11n_amsdu_aggr_ctrl { |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index a537297866c6..246aa62a4817 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "main.h" | 24 | #include "main.h" |
25 | #include "wmm.h" | 25 | #include "wmm.h" |
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11ac.h" | ||
27 | 28 | ||
28 | #define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) | 29 | #define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) |
29 | 30 | ||
@@ -512,6 +513,12 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, | |||
512 | priv->adapter->config_bands & BAND_AN)) | 513 | priv->adapter->config_bands & BAND_AN)) |
513 | mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); | 514 | mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); |
514 | 515 | ||
516 | if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && | ||
517 | !bss_desc->disable_11n && !bss_desc->disable_11ac && | ||
518 | (priv->adapter->config_bands & BAND_GAC || | ||
519 | priv->adapter->config_bands & BAND_AAC)) | ||
520 | mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos); | ||
521 | |||
515 | /* Append vendor specific IE TLV */ | 522 | /* Append vendor specific IE TLV */ |
516 | mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); | 523 | mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); |
517 | 524 | ||
@@ -1421,6 +1428,7 @@ mwifiex_band_to_radio_type(u8 band) | |||
1421 | case BAND_A: | 1428 | case BAND_A: |
1422 | case BAND_AN: | 1429 | case BAND_AN: |
1423 | case BAND_A | BAND_AN: | 1430 | case BAND_A | BAND_AN: |
1431 | case BAND_A | BAND_AN | BAND_AAC: | ||
1424 | return HostCmd_SCAN_RADIO_TYPE_A; | 1432 | return HostCmd_SCAN_RADIO_TYPE_A; |
1425 | case BAND_B: | 1433 | case BAND_B: |
1426 | case BAND_G: | 1434 | case BAND_G: |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index ac799a046eb7..553adfb0aa81 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -295,6 +295,13 @@ struct mwifiex_bssdescriptor { | |||
295 | u16 bss_co_2040_offset; | 295 | u16 bss_co_2040_offset; |
296 | u8 *bcn_ext_cap; | 296 | u8 *bcn_ext_cap; |
297 | u16 ext_cap_offset; | 297 | u16 ext_cap_offset; |
298 | struct ieee80211_vht_cap *bcn_vht_cap; | ||
299 | u16 vht_cap_offset; | ||
300 | struct ieee80211_vht_operation *bcn_vht_oper; | ||
301 | u16 vht_info_offset; | ||
302 | struct ieee_types_oper_mode_ntf *oper_mode; | ||
303 | u16 oper_mode_offset; | ||
304 | u8 disable_11ac; | ||
298 | struct ieee_types_vendor_specific *bcn_wpa_ie; | 305 | struct ieee_types_vendor_specific *bcn_wpa_ie; |
299 | u16 wpa_offset; | 306 | u16 wpa_offset; |
300 | struct ieee_types_generic *bcn_rsn_ie; | 307 | struct ieee_types_generic *bcn_rsn_ie; |
@@ -499,6 +506,7 @@ struct mwifiex_private { | |||
499 | u16 rsn_idx; | 506 | u16 rsn_idx; |
500 | struct timer_list scan_delay_timer; | 507 | struct timer_list scan_delay_timer; |
501 | u8 ap_11n_enabled; | 508 | u8 ap_11n_enabled; |
509 | u8 ap_11ac_enabled; | ||
502 | u32 mgmt_frame_mask; | 510 | u32 mgmt_frame_mask; |
503 | struct mwifiex_roc_cfg roc_cfg; | 511 | struct mwifiex_roc_cfg roc_cfg; |
504 | }; | 512 | }; |
@@ -722,6 +730,15 @@ struct mwifiex_adapter { | |||
722 | u16 max_mgmt_ie_index; | 730 | u16 max_mgmt_ie_index; |
723 | u8 scan_delay_cnt; | 731 | u8 scan_delay_cnt; |
724 | u8 empty_tx_q_cnt; | 732 | u8 empty_tx_q_cnt; |
733 | |||
734 | /* 11AC */ | ||
735 | u32 is_hw_11ac_capable; | ||
736 | u32 hw_dot_11ac_dev_cap; | ||
737 | u32 hw_dot_11ac_mcs_support; | ||
738 | u32 usr_dot_11ac_dev_cap_bg; | ||
739 | u32 usr_dot_11ac_dev_cap_a; | ||
740 | u32 usr_dot_11ac_mcs_support; | ||
741 | |||
725 | atomic_t is_tx_received; | 742 | atomic_t is_tx_received; |
726 | atomic_t pending_bridged_pkts; | 743 | atomic_t pending_bridged_pkts; |
727 | }; | 744 | }; |
@@ -864,8 +881,10 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, | |||
864 | int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); | 881 | int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); |
865 | struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv, | 882 | struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv, |
866 | u8 band, u16 channel, u32 freq); | 883 | u8 band, u16 channel, u32 freq); |
867 | u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index, | 884 | u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, |
868 | u8 ht_info); | 885 | u8 index, u8 ht_info); |
886 | u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, | ||
887 | u8 index, u8 ht_info); | ||
869 | u32 mwifiex_find_freq_from_band_chan(u8, u8); | 888 | u32 mwifiex_find_freq_from_band_chan(u8, u8); |
870 | int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, | 889 | int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, |
871 | u8 **buffer); | 890 | u8 **buffer); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 492655c048d1..4b54bcf382f3 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -1023,10 +1023,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) | |||
1023 | adapter->data_sent = false; | 1023 | adapter->data_sent = false; |
1024 | 1024 | ||
1025 | if (card->txbd_flush) { | 1025 | if (card->txbd_flush) { |
1026 | if (((card->txbd_wrptr & reg->tx_mask) == | 1026 | if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) |
1027 | (card->txbd_rdptr & reg->tx_mask)) && | ||
1028 | ((card->txbd_wrptr & reg->tx_rollover_ind) != | ||
1029 | (card->txbd_rdptr & reg->tx_rollover_ind))) | ||
1030 | card->txbd_flush = 0; | 1027 | card->txbd_flush = 0; |
1031 | else | 1028 | else |
1032 | mwifiex_clean_pcie_ring_buf(adapter); | 1029 | mwifiex_clean_pcie_ring_buf(adapter); |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index e0cce1b52d55..bb60c2754a97 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1250,6 +1250,23 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
1250 | sizeof(struct ieee_types_header) - | 1250 | sizeof(struct ieee_types_header) - |
1251 | bss_entry->beacon_buf); | 1251 | bss_entry->beacon_buf); |
1252 | break; | 1252 | break; |
1253 | case WLAN_EID_VHT_CAPABILITY: | ||
1254 | bss_entry->disable_11ac = false; | ||
1255 | bss_entry->bcn_vht_cap = | ||
1256 | (void *)(current_ptr + | ||
1257 | sizeof(struct ieee_types_header)); | ||
1258 | bss_entry->vht_cap_offset = | ||
1259 | (u16)((u8 *)bss_entry->bcn_vht_cap - | ||
1260 | bss_entry->beacon_buf); | ||
1261 | break; | ||
1262 | case WLAN_EID_VHT_OPERATION: | ||
1263 | bss_entry->bcn_vht_oper = | ||
1264 | (void *)(current_ptr + | ||
1265 | sizeof(struct ieee_types_header)); | ||
1266 | bss_entry->vht_info_offset = | ||
1267 | (u16)((u8 *)bss_entry->bcn_vht_oper - | ||
1268 | bss_entry->beacon_buf); | ||
1269 | break; | ||
1253 | case WLAN_EID_BSS_COEX_2040: | 1270 | case WLAN_EID_BSS_COEX_2040: |
1254 | bss_entry->bcn_bss_co_2040 = current_ptr + | 1271 | bss_entry->bcn_bss_co_2040 = current_ptr + |
1255 | sizeof(struct ieee_types_header); | 1272 | sizeof(struct ieee_types_header); |
@@ -1264,6 +1281,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, | |||
1264 | sizeof(struct ieee_types_header) - | 1281 | sizeof(struct ieee_types_header) - |
1265 | bss_entry->beacon_buf); | 1282 | bss_entry->beacon_buf); |
1266 | break; | 1283 | break; |
1284 | case WLAN_EID_OPMODE_NOTIF: | ||
1285 | bss_entry->oper_mode = | ||
1286 | (void *)(current_ptr + | ||
1287 | sizeof(struct ieee_types_header)); | ||
1288 | bss_entry->oper_mode_offset = | ||
1289 | (u16)((u8 *)bss_entry->oper_mode - | ||
1290 | bss_entry->beacon_buf); | ||
1291 | break; | ||
1267 | default: | 1292 | default: |
1268 | break; | 1293 | break; |
1269 | } | 1294 | } |
@@ -1479,20 +1504,26 @@ static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv, | |||
1479 | priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; | 1504 | priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL; |
1480 | priv->curr_bss_params.bss_descriptor.wapi_offset = 0; | 1505 | priv->curr_bss_params.bss_descriptor.wapi_offset = 0; |
1481 | priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; | 1506 | priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL; |
1482 | priv->curr_bss_params.bss_descriptor.ht_cap_offset = | 1507 | priv->curr_bss_params.bss_descriptor.ht_cap_offset = 0; |
1483 | 0; | ||
1484 | priv->curr_bss_params.bss_descriptor.bcn_ht_oper = NULL; | 1508 | priv->curr_bss_params.bss_descriptor.bcn_ht_oper = NULL; |
1485 | priv->curr_bss_params.bss_descriptor.ht_info_offset = | 1509 | priv->curr_bss_params.bss_descriptor.ht_info_offset = 0; |
1486 | 0; | 1510 | priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = NULL; |
1487 | priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 = | 1511 | priv->curr_bss_params.bss_descriptor.bss_co_2040_offset = 0; |
1488 | NULL; | ||
1489 | priv->curr_bss_params.bss_descriptor. | ||
1490 | bss_co_2040_offset = 0; | ||
1491 | priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; | 1512 | priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL; |
1492 | priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; | 1513 | priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0; |
1493 | priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; | 1514 | priv->curr_bss_params.bss_descriptor.beacon_buf = NULL; |
1494 | priv->curr_bss_params.bss_descriptor.beacon_buf_size = | 1515 | priv->curr_bss_params.bss_descriptor.beacon_buf_size = 0; |
1495 | 0; | 1516 | priv->curr_bss_params.bss_descriptor.bcn_vht_cap = NULL; |
1517 | priv->curr_bss_params.bss_descriptor.vht_cap_offset = 0; | ||
1518 | priv->curr_bss_params.bss_descriptor.bcn_vht_oper = NULL; | ||
1519 | priv->curr_bss_params.bss_descriptor.vht_info_offset = 0; | ||
1520 | priv->curr_bss_params.bss_descriptor.oper_mode = NULL; | ||
1521 | priv->curr_bss_params.bss_descriptor.oper_mode_offset = 0; | ||
1522 | |||
1523 | /* Disable 11ac by default. Enable it only where there | ||
1524 | * exist VHT_CAP IE in AP beacon | ||
1525 | */ | ||
1526 | priv->curr_bss_params.bss_descriptor.disable_11ac = true; | ||
1496 | 1527 | ||
1497 | /* Make a copy of current BSSID descriptor */ | 1528 | /* Make a copy of current BSSID descriptor */ |
1498 | memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, | 1529 | memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, |
@@ -2022,6 +2053,14 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) | |||
2022 | (curr_bss->beacon_buf + | 2053 | (curr_bss->beacon_buf + |
2023 | curr_bss->ht_info_offset); | 2054 | curr_bss->ht_info_offset); |
2024 | 2055 | ||
2056 | if (curr_bss->bcn_vht_cap) | ||
2057 | curr_bss->bcn_ht_cap = (void *)(curr_bss->beacon_buf + | ||
2058 | curr_bss->vht_cap_offset); | ||
2059 | |||
2060 | if (curr_bss->bcn_vht_oper) | ||
2061 | curr_bss->bcn_ht_oper = (void *)(curr_bss->beacon_buf + | ||
2062 | curr_bss->vht_info_offset); | ||
2063 | |||
2025 | if (curr_bss->bcn_bss_co_2040) | 2064 | if (curr_bss->bcn_bss_co_2040) |
2026 | curr_bss->bcn_bss_co_2040 = | 2065 | curr_bss->bcn_bss_co_2040 = |
2027 | (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset); | 2066 | (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset); |
@@ -2029,6 +2068,10 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv) | |||
2029 | if (curr_bss->bcn_ext_cap) | 2068 | if (curr_bss->bcn_ext_cap) |
2030 | curr_bss->bcn_ext_cap = curr_bss->beacon_buf + | 2069 | curr_bss->bcn_ext_cap = curr_bss->beacon_buf + |
2031 | curr_bss->ext_cap_offset; | 2070 | curr_bss->ext_cap_offset; |
2071 | |||
2072 | if (curr_bss->oper_mode) | ||
2073 | curr_bss->oper_mode = (void *)(curr_bss->beacon_buf + | ||
2074 | curr_bss->oper_mode_offset); | ||
2032 | } | 2075 | } |
2033 | 2076 | ||
2034 | /* | 2077 | /* |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c4607859d59d..c55c5bb93134 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -1230,7 +1230,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1230 | data_buf); | 1230 | data_buf); |
1231 | break; | 1231 | break; |
1232 | case HostCmd_CMD_11N_CFG: | 1232 | case HostCmd_CMD_11N_CFG: |
1233 | ret = mwifiex_cmd_11n_cfg(cmd_ptr, cmd_action, data_buf); | 1233 | ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf); |
1234 | break; | 1234 | break; |
1235 | case HostCmd_CMD_WMM_GET_STATUS: | 1235 | case HostCmd_CMD_WMM_GET_STATUS: |
1236 | dev_dbg(priv->adapter->dev, | 1236 | dev_dbg(priv->adapter->dev, |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 847056415ac9..4669f8d9389f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "main.h" | 24 | #include "main.h" |
25 | #include "wmm.h" | 25 | #include "wmm.h" |
26 | #include "11n.h" | 26 | #include "11n.h" |
27 | #include "11ac.h" | ||
27 | 28 | ||
28 | 29 | ||
29 | /* | 30 | /* |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 7eef74564a92..9f33c92c90f5 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -281,9 +281,10 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
281 | 281 | ||
282 | if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) | 282 | if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) |
283 | == HostCmd_SCAN_RADIO_TYPE_BG) | 283 | == HostCmd_SCAN_RADIO_TYPE_BG) |
284 | config_bands = BAND_B | BAND_G | BAND_GN; | 284 | config_bands = BAND_B | BAND_G | BAND_GN | |
285 | BAND_GAC; | ||
285 | else | 286 | else |
286 | config_bands = BAND_A | BAND_AN; | 287 | config_bands = BAND_A | BAND_AN | BAND_AAC; |
287 | 288 | ||
288 | if (!((config_bands | adapter->fw_bands) & | 289 | if (!((config_bands | adapter->fw_bands) & |
289 | ~adapter->fw_bands)) | 290 | ~adapter->fw_bands)) |
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 01624dcaf73e..7744f42de1ea 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
@@ -804,10 +804,15 @@ static inline int ezusb_8051_cpucs(struct ezusb_priv *upriv, int reset) | |||
804 | static int ezusb_firmware_download(struct ezusb_priv *upriv, | 804 | static int ezusb_firmware_download(struct ezusb_priv *upriv, |
805 | struct ez_usb_fw *fw) | 805 | struct ez_usb_fw *fw) |
806 | { | 806 | { |
807 | u8 fw_buffer[FW_BUF_SIZE]; | 807 | u8 *fw_buffer; |
808 | int retval, addr; | 808 | int retval, addr; |
809 | int variant_offset; | 809 | int variant_offset; |
810 | 810 | ||
811 | fw_buffer = kmalloc(FW_BUF_SIZE, GFP_KERNEL); | ||
812 | if (!fw_buffer) { | ||
813 | printk(KERN_ERR PFX "Out of memory for firmware buffer.\n"); | ||
814 | return -ENOMEM; | ||
815 | } | ||
811 | /* | 816 | /* |
812 | * This byte is 1 and should be replaced with 0. The offset is | 817 | * This byte is 1 and should be replaced with 0. The offset is |
813 | * 0x10AD in version 0.0.6. The byte in question should follow | 818 | * 0x10AD in version 0.0.6. The byte in question should follow |
@@ -859,6 +864,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv, | |||
859 | printk(KERN_ERR PFX "Firmware download failed, error %d\n", | 864 | printk(KERN_ERR PFX "Firmware download failed, error %d\n", |
860 | retval); | 865 | retval); |
861 | exit: | 866 | exit: |
867 | kfree(fw_buffer); | ||
862 | return retval; | 868 | return retval; |
863 | } | 869 | } |
864 | 870 | ||
@@ -1681,7 +1687,8 @@ static int ezusb_probe(struct usb_interface *interface, | |||
1681 | firmware.code = fw_entry->data; | 1687 | firmware.code = fw_entry->data; |
1682 | } | 1688 | } |
1683 | if (firmware.size && firmware.code) { | 1689 | if (firmware.size && firmware.code) { |
1684 | ezusb_firmware_download(upriv, &firmware); | 1690 | if (ezusb_firmware_download(upriv, &firmware)) |
1691 | goto error; | ||
1685 | } else { | 1692 | } else { |
1686 | err("No firmware to download"); | 1693 | err("No firmware to download"); |
1687 | goto error; | 1694 | goto error; |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 476eaef5e4a9..156b52732f3d 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -42,8 +42,12 @@ | |||
42 | 42 | ||
43 | static void usbctrl_async_callback(struct urb *urb) | 43 | static void usbctrl_async_callback(struct urb *urb) |
44 | { | 44 | { |
45 | if (urb) | 45 | if (urb) { |
46 | kfree(urb->context); | 46 | /* free dr */ |
47 | kfree(urb->setup_packet); | ||
48 | /* free databuf */ | ||
49 | kfree(urb->transfer_buffer); | ||
50 | } | ||
47 | } | 51 | } |
48 | 52 | ||
49 | static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, | 53 | static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, |
@@ -55,39 +59,47 @@ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, | |||
55 | u8 reqtype; | 59 | u8 reqtype; |
56 | struct usb_ctrlrequest *dr; | 60 | struct usb_ctrlrequest *dr; |
57 | struct urb *urb; | 61 | struct urb *urb; |
58 | struct rtl819x_async_write_data { | 62 | const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE; |
59 | u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE]; | 63 | u8 *databuf; |
60 | struct usb_ctrlrequest dr; | 64 | |
61 | } *buf; | 65 | if (WARN_ON_ONCE(len > databuf_maxlen)) |
66 | len = databuf_maxlen; | ||
62 | 67 | ||
63 | pipe = usb_sndctrlpipe(udev, 0); /* write_out */ | 68 | pipe = usb_sndctrlpipe(udev, 0); /* write_out */ |
64 | reqtype = REALTEK_USB_VENQT_WRITE; | 69 | reqtype = REALTEK_USB_VENQT_WRITE; |
65 | 70 | ||
66 | buf = kmalloc(sizeof(*buf), GFP_ATOMIC); | 71 | dr = kmalloc(sizeof(*dr), GFP_ATOMIC); |
67 | if (!buf) | 72 | if (!dr) |
68 | return -ENOMEM; | 73 | return -ENOMEM; |
69 | 74 | ||
75 | databuf = kmalloc(databuf_maxlen, GFP_ATOMIC); | ||
76 | if (!databuf) { | ||
77 | kfree(dr); | ||
78 | return -ENOMEM; | ||
79 | } | ||
80 | |||
70 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 81 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
71 | if (!urb) { | 82 | if (!urb) { |
72 | kfree(buf); | 83 | kfree(databuf); |
84 | kfree(dr); | ||
73 | return -ENOMEM; | 85 | return -ENOMEM; |
74 | } | 86 | } |
75 | 87 | ||
76 | dr = &buf->dr; | ||
77 | |||
78 | dr->bRequestType = reqtype; | 88 | dr->bRequestType = reqtype; |
79 | dr->bRequest = request; | 89 | dr->bRequest = request; |
80 | dr->wValue = cpu_to_le16(value); | 90 | dr->wValue = cpu_to_le16(value); |
81 | dr->wIndex = cpu_to_le16(index); | 91 | dr->wIndex = cpu_to_le16(index); |
82 | dr->wLength = cpu_to_le16(len); | 92 | dr->wLength = cpu_to_le16(len); |
83 | /* data are already in little-endian order */ | 93 | /* data are already in little-endian order */ |
84 | memcpy(buf, pdata, len); | 94 | memcpy(databuf, pdata, len); |
85 | usb_fill_control_urb(urb, udev, pipe, | 95 | usb_fill_control_urb(urb, udev, pipe, |
86 | (unsigned char *)dr, buf, len, | 96 | (unsigned char *)dr, databuf, len, |
87 | usbctrl_async_callback, buf); | 97 | usbctrl_async_callback, NULL); |
88 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 98 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
89 | if (rc < 0) | 99 | if (rc < 0) { |
90 | kfree(buf); | 100 | kfree(databuf); |
101 | kfree(dr); | ||
102 | } | ||
91 | usb_free_urb(urb); | 103 | usb_free_urb(urb); |
92 | return rc; | 104 | return rc; |
93 | } | 105 | } |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 179dcbd8be1c..09d96a8f6c2c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1500,13 +1500,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1500 | return -ENOENT; | 1500 | return -ENOENT; |
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | err = mesh_path_add(dst, sdata); | 1503 | err = mesh_path_add(sdata, dst); |
1504 | if (err) { | 1504 | if (err) { |
1505 | rcu_read_unlock(); | 1505 | rcu_read_unlock(); |
1506 | return err; | 1506 | return err; |
1507 | } | 1507 | } |
1508 | 1508 | ||
1509 | mpath = mesh_path_lookup(dst, sdata); | 1509 | mpath = mesh_path_lookup(sdata, dst); |
1510 | if (!mpath) { | 1510 | if (!mpath) { |
1511 | rcu_read_unlock(); | 1511 | rcu_read_unlock(); |
1512 | return -ENXIO; | 1512 | return -ENXIO; |
@@ -1518,12 +1518,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1518 | } | 1518 | } |
1519 | 1519 | ||
1520 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | 1520 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, |
1521 | u8 *dst) | 1521 | u8 *dst) |
1522 | { | 1522 | { |
1523 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1523 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1524 | 1524 | ||
1525 | if (dst) | 1525 | if (dst) |
1526 | return mesh_path_del(dst, sdata); | 1526 | return mesh_path_del(sdata, dst); |
1527 | 1527 | ||
1528 | mesh_path_flush_by_iface(sdata); | 1528 | mesh_path_flush_by_iface(sdata); |
1529 | return 0; | 1529 | return 0; |
@@ -1547,7 +1547,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
1547 | return -ENOENT; | 1547 | return -ENOENT; |
1548 | } | 1548 | } |
1549 | 1549 | ||
1550 | mpath = mesh_path_lookup(dst, sdata); | 1550 | mpath = mesh_path_lookup(sdata, dst); |
1551 | if (!mpath) { | 1551 | if (!mpath) { |
1552 | rcu_read_unlock(); | 1552 | rcu_read_unlock(); |
1553 | return -ENOENT; | 1553 | return -ENOENT; |
@@ -1611,7 +1611,7 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1611 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1611 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1612 | 1612 | ||
1613 | rcu_read_lock(); | 1613 | rcu_read_lock(); |
1614 | mpath = mesh_path_lookup(dst, sdata); | 1614 | mpath = mesh_path_lookup(sdata, dst); |
1615 | if (!mpath) { | 1615 | if (!mpath) { |
1616 | rcu_read_unlock(); | 1616 | rcu_read_unlock(); |
1617 | return -ENOENT; | 1617 | return -ENOENT; |
@@ -1632,7 +1632,7 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1632 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1632 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1633 | 1633 | ||
1634 | rcu_read_lock(); | 1634 | rcu_read_lock(); |
1635 | mpath = mesh_path_lookup_by_idx(idx, sdata); | 1635 | mpath = mesh_path_lookup_by_idx(sdata, idx); |
1636 | if (!mpath) { | 1636 | if (!mpath) { |
1637 | rcu_read_unlock(); | 1637 | rcu_read_unlock(); |
1638 | return -ENOENT; | 1638 | return -ENOENT; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 86c83084542a..2c059e54e885 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -294,7 +294,8 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) | |||
294 | } | 294 | } |
295 | } | 295 | } |
296 | 296 | ||
297 | if ((sdata->vif.type != NL80211_IFTYPE_AP) || | 297 | if ((sdata->vif.type != NL80211_IFTYPE_AP && |
298 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT) || | ||
298 | !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) { | 299 | !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) { |
299 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; | 300 | sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; |
300 | return 0; | 301 | return 0; |
@@ -695,6 +696,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
695 | 696 | ||
696 | ieee80211_roc_purge(sdata); | 697 | ieee80211_roc_purge(sdata); |
697 | 698 | ||
699 | if (sdata->vif.type == NL80211_IFTYPE_STATION) | ||
700 | ieee80211_mgd_stop(sdata); | ||
701 | |||
698 | /* | 702 | /* |
699 | * Remove all stations associated with this interface. | 703 | * Remove all stations associated with this interface. |
700 | * | 704 | * |
@@ -782,8 +786,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
782 | } | 786 | } |
783 | } | 787 | } |
784 | spin_unlock_irqrestore(&ps->bc_buf.lock, flags); | 788 | spin_unlock_irqrestore(&ps->bc_buf.lock, flags); |
785 | } else if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
786 | ieee80211_mgd_stop(sdata); | ||
787 | } | 789 | } |
788 | 790 | ||
789 | if (going_down) | 791 | if (going_down) |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f9747689d604..d0dd11153a6c 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1173,8 +1173,7 @@ static void __exit ieee80211_exit(void) | |||
1173 | rc80211_minstrel_ht_exit(); | 1173 | rc80211_minstrel_ht_exit(); |
1174 | rc80211_minstrel_exit(); | 1174 | rc80211_minstrel_exit(); |
1175 | 1175 | ||
1176 | if (mesh_allocated) | 1176 | ieee80211s_stop(); |
1177 | ieee80211s_stop(); | ||
1178 | 1177 | ||
1179 | ieee80211_iface_exit(); | 1178 | ieee80211_iface_exit(); |
1180 | 1179 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a77d40ed4e61..29ce2aa87e7b 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #define TMR_RUNNING_MP 1 | 17 | #define TMR_RUNNING_MP 1 |
18 | #define TMR_RUNNING_MPR 2 | 18 | #define TMR_RUNNING_MPR 2 |
19 | 19 | ||
20 | int mesh_allocated; | 20 | static int mesh_allocated; |
21 | static struct kmem_cache *rm_cache; | 21 | static struct kmem_cache *rm_cache; |
22 | 22 | ||
23 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) | 23 | bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) |
@@ -36,6 +36,8 @@ void ieee80211s_init(void) | |||
36 | 36 | ||
37 | void ieee80211s_stop(void) | 37 | void ieee80211s_stop(void) |
38 | { | 38 | { |
39 | if (!mesh_allocated) | ||
40 | return; | ||
39 | mesh_pathtbl_unregister(); | 41 | mesh_pathtbl_unregister(); |
40 | kmem_cache_destroy(rm_cache); | 42 | kmem_cache_destroy(rm_cache); |
41 | } | 43 | } |
@@ -90,24 +92,22 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
90 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && | 92 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && |
91 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && | 93 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && |
92 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) | 94 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))) |
93 | goto mismatch; | 95 | return false; |
94 | 96 | ||
95 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), | 97 | ieee80211_sta_get_rates(local, ie, ieee80211_get_sdata_band(sdata), |
96 | &basic_rates); | 98 | &basic_rates); |
97 | 99 | ||
98 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 100 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
99 | goto mismatch; | 101 | return false; |
100 | 102 | ||
101 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | 103 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
102 | ie->ht_operation, &sta_chan_def); | 104 | ie->ht_operation, &sta_chan_def); |
103 | 105 | ||
104 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, | 106 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, |
105 | &sta_chan_def)) | 107 | &sta_chan_def)) |
106 | goto mismatch; | 108 | return false; |
107 | 109 | ||
108 | return true; | 110 | return true; |
109 | mismatch: | ||
110 | return false; | ||
111 | } | 111 | } |
112 | 112 | ||
113 | /** | 113 | /** |
@@ -118,7 +118,7 @@ mismatch: | |||
118 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 118 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
119 | { | 119 | { |
120 | return (ie->mesh_config->meshconf_cap & | 120 | return (ie->mesh_config->meshconf_cap & |
121 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | 121 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; |
122 | } | 122 | } |
123 | 123 | ||
124 | /** | 124 | /** |
@@ -196,11 +196,12 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
196 | if (!sdata->u.mesh.rmc) | 196 | if (!sdata->u.mesh.rmc) |
197 | return; | 197 | return; |
198 | 198 | ||
199 | for (i = 0; i < RMC_BUCKETS; i++) | 199 | for (i = 0; i < RMC_BUCKETS; i++) { |
200 | list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { | 200 | list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { |
201 | list_del(&p->list); | 201 | list_del(&p->list); |
202 | kmem_cache_free(rm_cache, p); | 202 | kmem_cache_free(rm_cache, p); |
203 | } | 203 | } |
204 | } | ||
204 | 205 | ||
205 | kfree(rmc); | 206 | kfree(rmc); |
206 | sdata->u.mesh.rmc = NULL; | 207 | sdata->u.mesh.rmc = NULL; |
@@ -209,6 +210,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
209 | /** | 210 | /** |
210 | * mesh_rmc_check - Check frame in recent multicast cache and add if absent. | 211 | * mesh_rmc_check - Check frame in recent multicast cache and add if absent. |
211 | * | 212 | * |
213 | * @sdata: interface | ||
212 | * @sa: source address | 214 | * @sa: source address |
213 | * @mesh_hdr: mesh_header | 215 | * @mesh_hdr: mesh_header |
214 | * | 216 | * |
@@ -218,8 +220,8 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) | |||
218 | * received this frame lately. If the frame is not in the cache, it is added to | 220 | * received this frame lately. If the frame is not in the cache, it is added to |
219 | * it. | 221 | * it. |
220 | */ | 222 | */ |
221 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | 223 | int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, |
222 | struct ieee80211_sub_if_data *sdata) | 224 | const u8 *sa, struct ieee80211s_hdr *mesh_hdr) |
223 | { | 225 | { |
224 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; | 226 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
225 | u32 seqnum = 0; | 227 | u32 seqnum = 0; |
@@ -233,12 +235,11 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
233 | list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { | 235 | list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { |
234 | ++entries; | 236 | ++entries; |
235 | if (time_after(jiffies, p->exp_time) || | 237 | if (time_after(jiffies, p->exp_time) || |
236 | (entries == RMC_QUEUE_MAX_LEN)) { | 238 | entries == RMC_QUEUE_MAX_LEN) { |
237 | list_del(&p->list); | 239 | list_del(&p->list); |
238 | kmem_cache_free(rm_cache, p); | 240 | kmem_cache_free(rm_cache, p); |
239 | --entries; | 241 | --entries; |
240 | } else if ((seqnum == p->seqnum) && | 242 | } else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa)) |
241 | (ether_addr_equal(sa, p->sa))) | ||
242 | return -1; | 243 | return -1; |
243 | } | 244 | } |
244 | 245 | ||
@@ -253,8 +254,8 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
253 | return 0; | 254 | return 0; |
254 | } | 255 | } |
255 | 256 | ||
256 | int | 257 | int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, |
257 | mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | 258 | struct sk_buff *skb) |
258 | { | 259 | { |
259 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 260 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
260 | u8 *pos, neighbors; | 261 | u8 *pos, neighbors; |
@@ -285,19 +286,18 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
285 | /* Mesh capability */ | 286 | /* Mesh capability */ |
286 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; | 287 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; |
287 | *pos |= ifmsh->accepting_plinks ? | 288 | *pos |= ifmsh->accepting_plinks ? |
288 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 289 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
289 | /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ | 290 | /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ |
290 | *pos |= ifmsh->ps_peers_deep_sleep ? | 291 | *pos |= ifmsh->ps_peers_deep_sleep ? |
291 | IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; | 292 | IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; |
292 | *pos++ |= ifmsh->adjusting_tbtt ? | 293 | *pos++ |= ifmsh->adjusting_tbtt ? |
293 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; | 294 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; |
294 | *pos++ = 0x00; | 295 | *pos++ = 0x00; |
295 | 296 | ||
296 | return 0; | 297 | return 0; |
297 | } | 298 | } |
298 | 299 | ||
299 | int | 300 | int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
300 | mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
301 | { | 301 | { |
302 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 302 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
303 | u8 *pos; | 303 | u8 *pos; |
@@ -314,8 +314,8 @@ mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
314 | return 0; | 314 | return 0; |
315 | } | 315 | } |
316 | 316 | ||
317 | int mesh_add_awake_window_ie(struct sk_buff *skb, | 317 | static int mesh_add_awake_window_ie(struct ieee80211_sub_if_data *sdata, |
318 | struct ieee80211_sub_if_data *sdata) | 318 | struct sk_buff *skb) |
319 | { | 319 | { |
320 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 320 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
321 | u8 *pos; | 321 | u8 *pos; |
@@ -337,8 +337,8 @@ int mesh_add_awake_window_ie(struct sk_buff *skb, | |||
337 | return 0; | 337 | return 0; |
338 | } | 338 | } |
339 | 339 | ||
340 | int | 340 | int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata, |
341 | mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | 341 | struct sk_buff *skb) |
342 | { | 342 | { |
343 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 343 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
344 | u8 offset, len; | 344 | u8 offset, len; |
@@ -361,8 +361,7 @@ mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
361 | return 0; | 361 | return 0; |
362 | } | 362 | } |
363 | 363 | ||
364 | int | 364 | int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
365 | mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | ||
366 | { | 365 | { |
367 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 366 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
368 | u8 len = 0; | 367 | u8 len = 0; |
@@ -390,8 +389,8 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
390 | return 0; | 389 | return 0; |
391 | } | 390 | } |
392 | 391 | ||
393 | int mesh_add_ds_params_ie(struct sk_buff *skb, | 392 | static int mesh_add_ds_params_ie(struct ieee80211_sub_if_data *sdata, |
394 | struct ieee80211_sub_if_data *sdata) | 393 | struct sk_buff *skb) |
395 | { | 394 | { |
396 | struct ieee80211_chanctx_conf *chanctx_conf; | 395 | struct ieee80211_chanctx_conf *chanctx_conf; |
397 | struct ieee80211_channel *chan; | 396 | struct ieee80211_channel *chan; |
@@ -417,8 +416,8 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
417 | return 0; | 416 | return 0; |
418 | } | 417 | } |
419 | 418 | ||
420 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | 419 | int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, |
421 | struct ieee80211_sub_if_data *sdata) | 420 | struct sk_buff *skb) |
422 | { | 421 | { |
423 | struct ieee80211_local *local = sdata->local; | 422 | struct ieee80211_local *local = sdata->local; |
424 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 423 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
@@ -439,8 +438,8 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
439 | return 0; | 438 | return 0; |
440 | } | 439 | } |
441 | 440 | ||
442 | int mesh_add_ht_oper_ie(struct sk_buff *skb, | 441 | int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, |
443 | struct ieee80211_sub_if_data *sdata) | 442 | struct sk_buff *skb) |
444 | { | 443 | { |
445 | struct ieee80211_local *local = sdata->local; | 444 | struct ieee80211_local *local = sdata->local; |
446 | struct ieee80211_chanctx_conf *chanctx_conf; | 445 | struct ieee80211_chanctx_conf *chanctx_conf; |
@@ -475,6 +474,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
475 | 474 | ||
476 | return 0; | 475 | return 0; |
477 | } | 476 | } |
477 | |||
478 | static void ieee80211_mesh_path_timer(unsigned long data) | 478 | static void ieee80211_mesh_path_timer(unsigned long data) |
479 | { | 479 | { |
480 | struct ieee80211_sub_if_data *sdata = | 480 | struct ieee80211_sub_if_data *sdata = |
@@ -520,7 +520,7 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | |||
520 | 520 | ||
521 | /** | 521 | /** |
522 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame | 522 | * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame |
523 | * @hdr: 802.11 frame header | 523 | * @hdr: 802.11 frame header |
524 | * @fc: frame control field | 524 | * @fc: frame control field |
525 | * @meshda: destination address in the mesh | 525 | * @meshda: destination address in the mesh |
526 | * @meshsa: source address address in the mesh. Same as TA, as frame is | 526 | * @meshsa: source address address in the mesh. Same as TA, as frame is |
@@ -551,8 +551,8 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
551 | 551 | ||
552 | /** | 552 | /** |
553 | * ieee80211_new_mesh_header - create a new mesh header | 553 | * ieee80211_new_mesh_header - create a new mesh header |
554 | * @meshhdr: uninitialized mesh header | ||
555 | * @sdata: mesh interface to be used | 554 | * @sdata: mesh interface to be used |
555 | * @meshhdr: uninitialized mesh header | ||
556 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 | 556 | * @addr4or5: 1st address in the ae header, which may correspond to address 4 |
557 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may | 557 | * (if addr6 is NULL) or address 5 (if addr6 is present). It may |
558 | * be NULL. | 558 | * be NULL. |
@@ -561,32 +561,38 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | |||
561 | * | 561 | * |
562 | * Return the header length. | 562 | * Return the header length. |
563 | */ | 563 | */ |
564 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 564 | int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, |
565 | struct ieee80211_sub_if_data *sdata, char *addr4or5, | 565 | struct ieee80211s_hdr *meshhdr, |
566 | char *addr6) | 566 | const char *addr4or5, const char *addr6) |
567 | { | 567 | { |
568 | int aelen = 0; | 568 | if (WARN_ON(!addr4or5 && addr6)) |
569 | BUG_ON(!addr4or5 && addr6); | 569 | return 0; |
570 | |||
570 | memset(meshhdr, 0, sizeof(*meshhdr)); | 571 | memset(meshhdr, 0, sizeof(*meshhdr)); |
572 | |||
571 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; | 573 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
574 | |||
575 | /* FIXME: racy -- TX on multiple queues can be concurrent */ | ||
572 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); | 576 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
573 | sdata->u.mesh.mesh_seqnum++; | 577 | sdata->u.mesh.mesh_seqnum++; |
578 | |||
574 | if (addr4or5 && !addr6) { | 579 | if (addr4or5 && !addr6) { |
575 | meshhdr->flags |= MESH_FLAGS_AE_A4; | 580 | meshhdr->flags |= MESH_FLAGS_AE_A4; |
576 | aelen += ETH_ALEN; | ||
577 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); | 581 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
582 | return 2 * ETH_ALEN; | ||
578 | } else if (addr4or5 && addr6) { | 583 | } else if (addr4or5 && addr6) { |
579 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; | 584 | meshhdr->flags |= MESH_FLAGS_AE_A5_A6; |
580 | aelen += 2 * ETH_ALEN; | ||
581 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); | 585 | memcpy(meshhdr->eaddr1, addr4or5, ETH_ALEN); |
582 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); | 586 | memcpy(meshhdr->eaddr2, addr6, ETH_ALEN); |
587 | return 3 * ETH_ALEN; | ||
583 | } | 588 | } |
584 | return 6 + aelen; | 589 | |
590 | return ETH_ALEN; | ||
585 | } | 591 | } |
586 | 592 | ||
587 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | 593 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) |
588 | struct ieee80211_if_mesh *ifmsh) | ||
589 | { | 594 | { |
595 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
590 | u32 changed; | 596 | u32 changed; |
591 | 597 | ||
592 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 598 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
@@ -596,7 +602,8 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | |||
596 | ieee80211_mbss_info_change_notify(sdata, changed); | 602 | ieee80211_mbss_info_change_notify(sdata, changed); |
597 | 603 | ||
598 | mod_timer(&ifmsh->housekeeping_timer, | 604 | mod_timer(&ifmsh->housekeeping_timer, |
599 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 605 | round_jiffies(jiffies + |
606 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | ||
600 | } | 607 | } |
601 | 608 | ||
602 | static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) | 609 | static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata) |
@@ -708,7 +715,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
708 | *pos++ = 0x0; | 715 | *pos++ = 0x0; |
709 | 716 | ||
710 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 717 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
711 | mesh_add_ds_params_ie(skb, sdata)) | 718 | mesh_add_ds_params_ie(sdata, skb)) |
712 | goto out_free; | 719 | goto out_free; |
713 | 720 | ||
714 | bcn->head_len = skb->len; | 721 | bcn->head_len = skb->len; |
@@ -719,13 +726,13 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
719 | bcn->tail = bcn->head + bcn->head_len; | 726 | bcn->tail = bcn->head + bcn->head_len; |
720 | 727 | ||
721 | if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 728 | if (ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
722 | mesh_add_rsn_ie(skb, sdata) || | 729 | mesh_add_rsn_ie(sdata, skb) || |
723 | mesh_add_ht_cap_ie(skb, sdata) || | 730 | mesh_add_ht_cap_ie(sdata, skb) || |
724 | mesh_add_ht_oper_ie(skb, sdata) || | 731 | mesh_add_ht_oper_ie(sdata, skb) || |
725 | mesh_add_meshid_ie(skb, sdata) || | 732 | mesh_add_meshid_ie(sdata, skb) || |
726 | mesh_add_meshconf_ie(skb, sdata) || | 733 | mesh_add_meshconf_ie(sdata, skb) || |
727 | mesh_add_awake_window_ie(skb, sdata) || | 734 | mesh_add_awake_window_ie(sdata, skb) || |
728 | mesh_add_vendor_ies(skb, sdata)) | 735 | mesh_add_vendor_ies(sdata, skb)) |
729 | goto out_free; | 736 | goto out_free; |
730 | 737 | ||
731 | bcn->tail_len = skb->len; | 738 | bcn->tail_len = skb->len; |
@@ -918,7 +925,6 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, | |||
918 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 925 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
919 | IEEE80211_STYPE_PROBE_RESP); | 926 | IEEE80211_STYPE_PROBE_RESP); |
920 | memcpy(hdr->da, mgmt->sa, ETH_ALEN); | 927 | memcpy(hdr->da, mgmt->sa, ETH_ALEN); |
921 | mpl_dbg(sdata, "sending probe resp. to %pM\n", hdr->da); | ||
922 | IEEE80211_SKB_CB(presp)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 928 | IEEE80211_SKB_CB(presp)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
923 | ieee80211_tx_skb(sdata, presp); | 929 | ieee80211_tx_skb(sdata, presp); |
924 | out: | 930 | out: |
@@ -1039,7 +1045,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
1039 | mesh_mpp_table_grow(); | 1045 | mesh_mpp_table_grow(); |
1040 | 1046 | ||
1041 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) | 1047 | if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags)) |
1042 | ieee80211_mesh_housekeeping(sdata, ifmsh); | 1048 | ieee80211_mesh_housekeeping(sdata); |
1043 | 1049 | ||
1044 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) | 1050 | if (test_and_clear_bit(MESH_WORK_ROOT, &ifmsh->wrkq_flags)) |
1045 | ieee80211_mesh_rootpath(sdata); | 1051 | ieee80211_mesh_rootpath(sdata); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 1a1da877b1d2..336c88a16687 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -26,12 +26,12 @@ | |||
26 | * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding | 26 | * @MESH_PATH_ACTIVE: the mesh path can be used for forwarding |
27 | * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path | 27 | * @MESH_PATH_RESOLVING: the discovery process is running for this mesh path |
28 | * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence | 28 | * @MESH_PATH_SN_VALID: the mesh path contains a valid destination sequence |
29 | * number | 29 | * number |
30 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be | 30 | * @MESH_PATH_FIXED: the mesh path has been manually set and should not be |
31 | * modified | 31 | * modified |
32 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved | 32 | * @MESH_PATH_RESOLVED: the mesh path can has been resolved |
33 | * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination | 33 | * @MESH_PATH_REQ_QUEUED: there is an unsent path request for this destination |
34 | * already queued up, waiting for the discovery process to start. | 34 | * already queued up, waiting for the discovery process to start. |
35 | * | 35 | * |
36 | * MESH_PATH_RESOLVED is used by the mesh path timer to | 36 | * MESH_PATH_RESOLVED is used by the mesh path timer to |
37 | * decide when to stop or cancel the mesh path discovery. | 37 | * decide when to stop or cancel the mesh path discovery. |
@@ -73,16 +73,16 @@ enum mesh_deferred_task_flags { | |||
73 | * @dst: mesh path destination mac address | 73 | * @dst: mesh path destination mac address |
74 | * @sdata: mesh subif | 74 | * @sdata: mesh subif |
75 | * @next_hop: mesh neighbor to which frames for this destination will be | 75 | * @next_hop: mesh neighbor to which frames for this destination will be |
76 | * forwarded | 76 | * forwarded |
77 | * @timer: mesh path discovery timer | 77 | * @timer: mesh path discovery timer |
78 | * @frame_queue: pending queue for frames sent to this destination while the | 78 | * @frame_queue: pending queue for frames sent to this destination while the |
79 | * path is unresolved | 79 | * path is unresolved |
80 | * @sn: target sequence number | 80 | * @sn: target sequence number |
81 | * @metric: current metric to this destination | 81 | * @metric: current metric to this destination |
82 | * @hop_count: hops to destination | 82 | * @hop_count: hops to destination |
83 | * @exp_time: in jiffies, when the path will expire or when it expired | 83 | * @exp_time: in jiffies, when the path will expire or when it expired |
84 | * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery | 84 | * @discovery_timeout: timeout (lapse in jiffies) used for the last discovery |
85 | * retry | 85 | * retry |
86 | * @discovery_retries: number of discovery retries | 86 | * @discovery_retries: number of discovery retries |
87 | * @flags: mesh path flags, as specified on &enum mesh_path_flags | 87 | * @flags: mesh path flags, as specified on &enum mesh_path_flags |
88 | * @state_lock: mesh path state lock used to protect changes to the | 88 | * @state_lock: mesh path state lock used to protect changes to the |
@@ -206,38 +206,33 @@ struct mesh_rmc { | |||
206 | /* Various */ | 206 | /* Various */ |
207 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 207 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
208 | const u8 *da, const u8 *sa); | 208 | const u8 *da, const u8 *sa); |
209 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 209 | int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata, |
210 | struct ieee80211_sub_if_data *sdata, char *addr4or5, | 210 | struct ieee80211s_hdr *meshhdr, |
211 | char *addr6); | 211 | const char *addr4or5, const char *addr6); |
212 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 212 | int mesh_rmc_check(struct ieee80211_sub_if_data *sdata, |
213 | struct ieee80211_sub_if_data *sdata); | 213 | const u8 *addr, struct ieee80211s_hdr *mesh_hdr); |
214 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | 214 | bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, |
215 | struct ieee802_11_elems *ie); | 215 | struct ieee802_11_elems *ie); |
216 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); | 216 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
217 | void mesh_mgmt_ies_add(struct sk_buff *skb, | 217 | void mesh_mgmt_ies_add(struct ieee80211_sub_if_data *sdata, |
218 | struct ieee80211_sub_if_data *sdata); | 218 | struct sk_buff *skb); |
219 | int mesh_add_meshconf_ie(struct sk_buff *skb, | 219 | int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata, |
220 | struct ieee80211_sub_if_data *sdata); | 220 | struct sk_buff *skb); |
221 | int mesh_add_meshid_ie(struct sk_buff *skb, | 221 | int mesh_add_meshid_ie(struct ieee80211_sub_if_data *sdata, |
222 | struct ieee80211_sub_if_data *sdata); | 222 | struct sk_buff *skb); |
223 | int mesh_add_rsn_ie(struct sk_buff *skb, | 223 | int mesh_add_rsn_ie(struct ieee80211_sub_if_data *sdata, |
224 | struct ieee80211_sub_if_data *sdata); | 224 | struct sk_buff *skb); |
225 | int mesh_add_awake_window_ie(struct sk_buff *skb, | 225 | int mesh_add_vendor_ies(struct ieee80211_sub_if_data *sdata, |
226 | struct ieee80211_sub_if_data *sdata); | 226 | struct sk_buff *skb); |
227 | int mesh_add_vendor_ies(struct sk_buff *skb, | 227 | int mesh_add_ht_cap_ie(struct ieee80211_sub_if_data *sdata, |
228 | struct ieee80211_sub_if_data *sdata); | 228 | struct sk_buff *skb); |
229 | int mesh_add_ds_params_ie(struct sk_buff *skb, | 229 | int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata, |
230 | struct ieee80211_sub_if_data *sdata); | 230 | struct sk_buff *skb); |
231 | int mesh_add_ht_cap_ie(struct sk_buff *skb, | ||
232 | struct ieee80211_sub_if_data *sdata); | ||
233 | int mesh_add_ht_oper_ie(struct sk_buff *skb, | ||
234 | struct ieee80211_sub_if_data *sdata); | ||
235 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 231 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
236 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 232 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
237 | void ieee80211s_init(void); | 233 | void ieee80211s_init(void); |
238 | void ieee80211s_update_metric(struct ieee80211_local *local, | 234 | void ieee80211s_update_metric(struct ieee80211_local *local, |
239 | struct sta_info *sta, struct sk_buff *skb); | 235 | struct sta_info *sta, struct sk_buff *skb); |
240 | void ieee80211s_stop(void); | ||
241 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 236 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
242 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | 237 | int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); |
243 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | 238 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); |
@@ -263,31 +258,32 @@ void ieee80211_mps_frame_release(struct sta_info *sta, | |||
263 | struct ieee802_11_elems *elems); | 258 | struct ieee802_11_elems *elems); |
264 | 259 | ||
265 | /* Mesh paths */ | 260 | /* Mesh paths */ |
266 | int mesh_nexthop_lookup(struct sk_buff *skb, | 261 | int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata, |
267 | struct ieee80211_sub_if_data *sdata); | 262 | struct sk_buff *skb); |
268 | int mesh_nexthop_resolve(struct sk_buff *skb, | 263 | int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, |
269 | struct ieee80211_sub_if_data *sdata); | 264 | struct sk_buff *skb); |
270 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); | 265 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
271 | struct mesh_path *mesh_path_lookup(const u8 *dst, | 266 | struct mesh_path *mesh_path_lookup(struct ieee80211_sub_if_data *sdata, |
272 | struct ieee80211_sub_if_data *sdata); | 267 | const u8 *dst); |
273 | struct mesh_path *mpp_path_lookup(u8 *dst, | 268 | struct mesh_path *mpp_path_lookup(struct ieee80211_sub_if_data *sdata, |
274 | struct ieee80211_sub_if_data *sdata); | 269 | const u8 *dst); |
275 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata); | 270 | int mpp_path_add(struct ieee80211_sub_if_data *sdata, |
276 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | 271 | const u8 *dst, const u8 *mpp); |
277 | struct ieee80211_sub_if_data *sdata); | 272 | struct mesh_path * |
273 | mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx); | ||
278 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 274 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
279 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); | 275 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
280 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 276 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
281 | struct ieee80211_mgmt *mgmt, size_t len); | 277 | struct ieee80211_mgmt *mgmt, size_t len); |
282 | int mesh_path_add(const u8 *dst, struct ieee80211_sub_if_data *sdata); | 278 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst); |
283 | 279 | ||
284 | int mesh_path_add_gate(struct mesh_path *mpath); | 280 | int mesh_path_add_gate(struct mesh_path *mpath); |
285 | int mesh_path_send_to_gates(struct mesh_path *mpath); | 281 | int mesh_path_send_to_gates(struct mesh_path *mpath); |
286 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); | 282 | int mesh_gate_num(struct ieee80211_sub_if_data *sdata); |
283 | |||
287 | /* Mesh plinks */ | 284 | /* Mesh plinks */ |
288 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | 285 | void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, |
289 | u8 *hw_addr, | 286 | u8 *hw_addr, struct ieee802_11_elems *ie); |
290 | struct ieee802_11_elems *ie); | ||
291 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 287 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
292 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 288 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
293 | void mesh_plink_broken(struct sta_info *sta); | 289 | void mesh_plink_broken(struct sta_info *sta); |
@@ -304,19 +300,19 @@ void mesh_sta_cleanup(struct sta_info *sta); | |||
304 | void mesh_mpath_table_grow(void); | 300 | void mesh_mpath_table_grow(void); |
305 | void mesh_mpp_table_grow(void); | 301 | void mesh_mpp_table_grow(void); |
306 | /* Mesh paths */ | 302 | /* Mesh paths */ |
307 | int mesh_path_error_tx(u8 ttl, const u8 *target, __le32 target_sn, | 303 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
308 | __le16 target_rcode, const u8 *ra, | 304 | u8 ttl, const u8 *target, __le32 target_sn, |
309 | struct ieee80211_sub_if_data *sdata); | 305 | __le16 target_rcode, const u8 *ra); |
310 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); | 306 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); |
311 | void mesh_path_flush_pending(struct mesh_path *mpath); | 307 | void mesh_path_flush_pending(struct mesh_path *mpath); |
312 | void mesh_path_tx_pending(struct mesh_path *mpath); | 308 | void mesh_path_tx_pending(struct mesh_path *mpath); |
313 | int mesh_pathtbl_init(void); | 309 | int mesh_pathtbl_init(void); |
314 | void mesh_pathtbl_unregister(void); | 310 | void mesh_pathtbl_unregister(void); |
315 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); | 311 | int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr); |
316 | void mesh_path_timer(unsigned long data); | 312 | void mesh_path_timer(unsigned long data); |
317 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 313 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
318 | void mesh_path_discard_frame(struct sk_buff *skb, | 314 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
319 | struct ieee80211_sub_if_data *sdata); | 315 | struct sk_buff *skb); |
320 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); | 316 | void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); |
321 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); | 317 | void mesh_path_restart(struct ieee80211_sub_if_data *sdata); |
322 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); | 318 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); |
@@ -325,8 +321,6 @@ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); | |||
325 | extern int mesh_paths_generation; | 321 | extern int mesh_paths_generation; |
326 | 322 | ||
327 | #ifdef CONFIG_MAC80211_MESH | 323 | #ifdef CONFIG_MAC80211_MESH |
328 | extern int mesh_allocated; | ||
329 | |||
330 | static inline | 324 | static inline |
331 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 325 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
332 | { | 326 | { |
@@ -371,8 +365,8 @@ void mesh_plink_quiesce(struct sta_info *sta); | |||
371 | void mesh_plink_restart(struct sta_info *sta); | 365 | void mesh_plink_restart(struct sta_info *sta); |
372 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); | 366 | void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata); |
373 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); | 367 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata); |
368 | void ieee80211s_stop(void); | ||
374 | #else | 369 | #else |
375 | #define mesh_allocated 0 | ||
376 | static inline void | 370 | static inline void |
377 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | 371 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} |
378 | static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) | 372 | static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata) |
@@ -385,6 +379,7 @@ static inline bool mesh_path_sel_is_hwmp(struct ieee80211_sub_if_data *sdata) | |||
385 | { return false; } | 379 | { return false; } |
386 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | 380 | static inline void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) |
387 | {} | 381 | {} |
382 | static inline void ieee80211s_stop(void) {} | ||
388 | #endif | 383 | #endif |
389 | 384 | ||
390 | #endif /* IEEE80211S_H */ | 385 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 585c1e26cca8..bdb8d3b14587 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -238,9 +238,9 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, | |||
238 | * also acquires in the TX path. To avoid a deadlock we don't transmit the | 238 | * also acquires in the TX path. To avoid a deadlock we don't transmit the |
239 | * frame directly but add it to the pending queue instead. | 239 | * frame directly but add it to the pending queue instead. |
240 | */ | 240 | */ |
241 | int mesh_path_error_tx(u8 ttl, const u8 *target, __le32 target_sn, | 241 | int mesh_path_error_tx(struct ieee80211_sub_if_data *sdata, |
242 | __le16 target_rcode, const u8 *ra, | 242 | u8 ttl, const u8 *target, __le32 target_sn, |
243 | struct ieee80211_sub_if_data *sdata) | 243 | __le16 target_rcode, const u8 *ra) |
244 | { | 244 | { |
245 | struct ieee80211_local *local = sdata->local; | 245 | struct ieee80211_local *local = sdata->local; |
246 | struct sk_buff *skb; | 246 | struct sk_buff *skb; |
@@ -430,7 +430,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
430 | process = false; | 430 | process = false; |
431 | fresh_info = false; | 431 | fresh_info = false; |
432 | } else { | 432 | } else { |
433 | mpath = mesh_path_lookup(orig_addr, sdata); | 433 | mpath = mesh_path_lookup(sdata, orig_addr); |
434 | if (mpath) { | 434 | if (mpath) { |
435 | spin_lock_bh(&mpath->state_lock); | 435 | spin_lock_bh(&mpath->state_lock); |
436 | if (mpath->flags & MESH_PATH_FIXED) | 436 | if (mpath->flags & MESH_PATH_FIXED) |
@@ -445,8 +445,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
445 | } | 445 | } |
446 | } | 446 | } |
447 | } else { | 447 | } else { |
448 | mesh_path_add(orig_addr, sdata); | 448 | mesh_path_add(sdata, orig_addr); |
449 | mpath = mesh_path_lookup(orig_addr, sdata); | 449 | mpath = mesh_path_lookup(sdata, orig_addr); |
450 | if (!mpath) { | 450 | if (!mpath) { |
451 | rcu_read_unlock(); | 451 | rcu_read_unlock(); |
452 | return 0; | 452 | return 0; |
@@ -478,7 +478,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
478 | else { | 478 | else { |
479 | fresh_info = true; | 479 | fresh_info = true; |
480 | 480 | ||
481 | mpath = mesh_path_lookup(ta, sdata); | 481 | mpath = mesh_path_lookup(sdata, ta); |
482 | if (mpath) { | 482 | if (mpath) { |
483 | spin_lock_bh(&mpath->state_lock); | 483 | spin_lock_bh(&mpath->state_lock); |
484 | if ((mpath->flags & MESH_PATH_FIXED) || | 484 | if ((mpath->flags & MESH_PATH_FIXED) || |
@@ -486,8 +486,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
486 | (last_hop_metric > mpath->metric))) | 486 | (last_hop_metric > mpath->metric))) |
487 | fresh_info = false; | 487 | fresh_info = false; |
488 | } else { | 488 | } else { |
489 | mesh_path_add(ta, sdata); | 489 | mesh_path_add(sdata, ta); |
490 | mpath = mesh_path_lookup(ta, sdata); | 490 | mpath = mesh_path_lookup(sdata, ta); |
491 | if (!mpath) { | 491 | if (!mpath) { |
492 | rcu_read_unlock(); | 492 | rcu_read_unlock(); |
493 | return 0; | 493 | return 0; |
@@ -553,7 +553,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
553 | } else if (is_broadcast_ether_addr(target_addr) && | 553 | } else if (is_broadcast_ether_addr(target_addr) && |
554 | (target_flags & IEEE80211_PREQ_TO_FLAG)) { | 554 | (target_flags & IEEE80211_PREQ_TO_FLAG)) { |
555 | rcu_read_lock(); | 555 | rcu_read_lock(); |
556 | mpath = mesh_path_lookup(orig_addr, sdata); | 556 | mpath = mesh_path_lookup(sdata, orig_addr); |
557 | if (mpath) { | 557 | if (mpath) { |
558 | if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { | 558 | if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) { |
559 | reply = true; | 559 | reply = true; |
@@ -568,7 +568,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
568 | rcu_read_unlock(); | 568 | rcu_read_unlock(); |
569 | } else { | 569 | } else { |
570 | rcu_read_lock(); | 570 | rcu_read_lock(); |
571 | mpath = mesh_path_lookup(target_addr, sdata); | 571 | mpath = mesh_path_lookup(sdata, target_addr); |
572 | if (mpath) { | 572 | if (mpath) { |
573 | if ((!(mpath->flags & MESH_PATH_SN_VALID)) || | 573 | if ((!(mpath->flags & MESH_PATH_SN_VALID)) || |
574 | SN_LT(mpath->sn, target_sn)) { | 574 | SN_LT(mpath->sn, target_sn)) { |
@@ -678,7 +678,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
678 | } | 678 | } |
679 | 679 | ||
680 | rcu_read_lock(); | 680 | rcu_read_lock(); |
681 | mpath = mesh_path_lookup(orig_addr, sdata); | 681 | mpath = mesh_path_lookup(sdata, orig_addr); |
682 | if (mpath) | 682 | if (mpath) |
683 | spin_lock_bh(&mpath->state_lock); | 683 | spin_lock_bh(&mpath->state_lock); |
684 | else | 684 | else |
@@ -736,7 +736,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
736 | target_rcode = PERR_IE_TARGET_RCODE(perr_elem); | 736 | target_rcode = PERR_IE_TARGET_RCODE(perr_elem); |
737 | 737 | ||
738 | rcu_read_lock(); | 738 | rcu_read_lock(); |
739 | mpath = mesh_path_lookup(target_addr, sdata); | 739 | mpath = mesh_path_lookup(sdata, target_addr); |
740 | if (mpath) { | 740 | if (mpath) { |
741 | struct sta_info *sta; | 741 | struct sta_info *sta; |
742 | 742 | ||
@@ -751,9 +751,10 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
751 | spin_unlock_bh(&mpath->state_lock); | 751 | spin_unlock_bh(&mpath->state_lock); |
752 | if (!ifmsh->mshcfg.dot11MeshForwarding) | 752 | if (!ifmsh->mshcfg.dot11MeshForwarding) |
753 | goto endperr; | 753 | goto endperr; |
754 | mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), | 754 | mesh_path_error_tx(sdata, ttl, target_addr, |
755 | cpu_to_le32(target_sn), | ||
755 | cpu_to_le16(target_rcode), | 756 | cpu_to_le16(target_rcode), |
756 | broadcast_addr, sdata); | 757 | broadcast_addr); |
757 | } else | 758 | } else |
758 | spin_unlock_bh(&mpath->state_lock); | 759 | spin_unlock_bh(&mpath->state_lock); |
759 | } | 760 | } |
@@ -801,10 +802,10 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
801 | 802 | ||
802 | metric_txsta = airtime_link_metric_get(local, sta); | 803 | metric_txsta = airtime_link_metric_get(local, sta); |
803 | 804 | ||
804 | mpath = mesh_path_lookup(orig_addr, sdata); | 805 | mpath = mesh_path_lookup(sdata, orig_addr); |
805 | if (!mpath) { | 806 | if (!mpath) { |
806 | mesh_path_add(orig_addr, sdata); | 807 | mesh_path_add(sdata, orig_addr); |
807 | mpath = mesh_path_lookup(orig_addr, sdata); | 808 | mpath = mesh_path_lookup(sdata, orig_addr); |
808 | if (!mpath) { | 809 | if (!mpath) { |
809 | rcu_read_unlock(); | 810 | rcu_read_unlock(); |
810 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 811 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
@@ -861,8 +862,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
861 | 862 | ||
862 | 863 | ||
863 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, | 864 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
864 | struct ieee80211_mgmt *mgmt, | 865 | struct ieee80211_mgmt *mgmt, size_t len) |
865 | size_t len) | ||
866 | { | 866 | { |
867 | struct ieee802_11_elems elems; | 867 | struct ieee802_11_elems elems; |
868 | size_t baselen; | 868 | size_t baselen; |
@@ -1006,7 +1006,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
1006 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); | 1006 | spin_unlock_bh(&ifmsh->mesh_preq_queue_lock); |
1007 | 1007 | ||
1008 | rcu_read_lock(); | 1008 | rcu_read_lock(); |
1009 | mpath = mesh_path_lookup(preq_node->dst, sdata); | 1009 | mpath = mesh_path_lookup(sdata, preq_node->dst); |
1010 | if (!mpath) | 1010 | if (!mpath) |
1011 | goto enddiscovery; | 1011 | goto enddiscovery; |
1012 | 1012 | ||
@@ -1076,8 +1076,8 @@ enddiscovery: | |||
1076 | * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. | 1076 | * Returns: 0 if the next hop was found and -ENOENT if the frame was queued. |
1077 | * skb is freeed here if no mpath could be allocated. | 1077 | * skb is freeed here if no mpath could be allocated. |
1078 | */ | 1078 | */ |
1079 | int mesh_nexthop_resolve(struct sk_buff *skb, | 1079 | int mesh_nexthop_resolve(struct ieee80211_sub_if_data *sdata, |
1080 | struct ieee80211_sub_if_data *sdata) | 1080 | struct sk_buff *skb) |
1081 | { | 1081 | { |
1082 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1082 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1083 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1083 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -1091,17 +1091,17 @@ int mesh_nexthop_resolve(struct sk_buff *skb, | |||
1091 | return 0; | 1091 | return 0; |
1092 | 1092 | ||
1093 | rcu_read_lock(); | 1093 | rcu_read_lock(); |
1094 | err = mesh_nexthop_lookup(skb, sdata); | 1094 | err = mesh_nexthop_lookup(sdata, skb); |
1095 | if (!err) | 1095 | if (!err) |
1096 | goto endlookup; | 1096 | goto endlookup; |
1097 | 1097 | ||
1098 | /* no nexthop found, start resolving */ | 1098 | /* no nexthop found, start resolving */ |
1099 | mpath = mesh_path_lookup(target_addr, sdata); | 1099 | mpath = mesh_path_lookup(sdata, target_addr); |
1100 | if (!mpath) { | 1100 | if (!mpath) { |
1101 | mesh_path_add(target_addr, sdata); | 1101 | mesh_path_add(sdata, target_addr); |
1102 | mpath = mesh_path_lookup(target_addr, sdata); | 1102 | mpath = mesh_path_lookup(sdata, target_addr); |
1103 | if (!mpath) { | 1103 | if (!mpath) { |
1104 | mesh_path_discard_frame(skb, sdata); | 1104 | mesh_path_discard_frame(sdata, skb); |
1105 | err = -ENOSPC; | 1105 | err = -ENOSPC; |
1106 | goto endlookup; | 1106 | goto endlookup; |
1107 | } | 1107 | } |
@@ -1118,12 +1118,13 @@ int mesh_nexthop_resolve(struct sk_buff *skb, | |||
1118 | skb_queue_tail(&mpath->frame_queue, skb); | 1118 | skb_queue_tail(&mpath->frame_queue, skb); |
1119 | err = -ENOENT; | 1119 | err = -ENOENT; |
1120 | if (skb_to_free) | 1120 | if (skb_to_free) |
1121 | mesh_path_discard_frame(skb_to_free, sdata); | 1121 | mesh_path_discard_frame(sdata, skb_to_free); |
1122 | 1122 | ||
1123 | endlookup: | 1123 | endlookup: |
1124 | rcu_read_unlock(); | 1124 | rcu_read_unlock(); |
1125 | return err; | 1125 | return err; |
1126 | } | 1126 | } |
1127 | |||
1127 | /** | 1128 | /** |
1128 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling | 1129 | * mesh_nexthop_lookup - put the appropriate next hop on a mesh frame. Calling |
1129 | * this function is considered "using" the associated mpath, so preempt a path | 1130 | * this function is considered "using" the associated mpath, so preempt a path |
@@ -1134,8 +1135,8 @@ endlookup: | |||
1134 | * | 1135 | * |
1135 | * Returns: 0 if the next hop was found. Nonzero otherwise. | 1136 | * Returns: 0 if the next hop was found. Nonzero otherwise. |
1136 | */ | 1137 | */ |
1137 | int mesh_nexthop_lookup(struct sk_buff *skb, | 1138 | int mesh_nexthop_lookup(struct ieee80211_sub_if_data *sdata, |
1138 | struct ieee80211_sub_if_data *sdata) | 1139 | struct sk_buff *skb) |
1139 | { | 1140 | { |
1140 | struct mesh_path *mpath; | 1141 | struct mesh_path *mpath; |
1141 | struct sta_info *next_hop; | 1142 | struct sta_info *next_hop; |
@@ -1144,7 +1145,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
1144 | int err = -ENOENT; | 1145 | int err = -ENOENT; |
1145 | 1146 | ||
1146 | rcu_read_lock(); | 1147 | rcu_read_lock(); |
1147 | mpath = mesh_path_lookup(target_addr, sdata); | 1148 | mpath = mesh_path_lookup(sdata, target_addr); |
1148 | 1149 | ||
1149 | if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) | 1150 | if (!mpath || !(mpath->flags & MESH_PATH_ACTIVE)) |
1150 | goto endlookup; | 1151 | goto endlookup; |
@@ -1203,8 +1204,7 @@ void mesh_path_timer(unsigned long data) | |||
1203 | } | 1204 | } |
1204 | } | 1205 | } |
1205 | 1206 | ||
1206 | void | 1207 | void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) |
1207 | mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | ||
1208 | { | 1208 | { |
1209 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1209 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
1210 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; | 1210 | u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 2ce4c4023a97..6b3c4e119c63 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -24,9 +24,12 @@ | |||
24 | /* Keep the mean chain length below this constant */ | 24 | /* Keep the mean chain length below this constant */ |
25 | #define MEAN_CHAIN_LEN 2 | 25 | #define MEAN_CHAIN_LEN 2 |
26 | 26 | ||
27 | #define MPATH_EXPIRED(mpath) ((mpath->flags & MESH_PATH_ACTIVE) && \ | 27 | static inline bool mpath_expired(struct mesh_path *mpath) |
28 | time_after(jiffies, mpath->exp_time) && \ | 28 | { |
29 | !(mpath->flags & MESH_PATH_FIXED)) | 29 | return (mpath->flags & MESH_PATH_ACTIVE) && |
30 | time_after(jiffies, mpath->exp_time) && | ||
31 | !(mpath->flags & MESH_PATH_FIXED); | ||
32 | } | ||
30 | 33 | ||
31 | struct mpath_node { | 34 | struct mpath_node { |
32 | struct hlist_node list; | 35 | struct hlist_node list; |
@@ -185,8 +188,8 @@ static u32 mesh_table_hash(const u8 *addr, struct ieee80211_sub_if_data *sdata, | |||
185 | struct mesh_table *tbl) | 188 | struct mesh_table *tbl) |
186 | { | 189 | { |
187 | /* Use last four bytes of hw addr and interface index as hash index */ | 190 | /* Use last four bytes of hw addr and interface index as hash index */ |
188 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) | 191 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, |
189 | & tbl->hash_mask; | 192 | tbl->hash_rnd) & tbl->hash_mask; |
190 | } | 193 | } |
191 | 194 | ||
192 | 195 | ||
@@ -339,7 +342,7 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, | |||
339 | mpath = node->mpath; | 342 | mpath = node->mpath; |
340 | if (mpath->sdata == sdata && | 343 | if (mpath->sdata == sdata && |
341 | ether_addr_equal(dst, mpath->dst)) { | 344 | ether_addr_equal(dst, mpath->dst)) { |
342 | if (MPATH_EXPIRED(mpath)) { | 345 | if (mpath_expired(mpath)) { |
343 | spin_lock_bh(&mpath->state_lock); | 346 | spin_lock_bh(&mpath->state_lock); |
344 | mpath->flags &= ~MESH_PATH_ACTIVE; | 347 | mpath->flags &= ~MESH_PATH_ACTIVE; |
345 | spin_unlock_bh(&mpath->state_lock); | 348 | spin_unlock_bh(&mpath->state_lock); |
@@ -352,20 +355,21 @@ static struct mesh_path *mpath_lookup(struct mesh_table *tbl, const u8 *dst, | |||
352 | 355 | ||
353 | /** | 356 | /** |
354 | * mesh_path_lookup - look up a path in the mesh path table | 357 | * mesh_path_lookup - look up a path in the mesh path table |
355 | * @dst: hardware address (ETH_ALEN length) of destination | ||
356 | * @sdata: local subif | 358 | * @sdata: local subif |
359 | * @dst: hardware address (ETH_ALEN length) of destination | ||
357 | * | 360 | * |
358 | * Returns: pointer to the mesh path structure, or NULL if not found | 361 | * Returns: pointer to the mesh path structure, or NULL if not found |
359 | * | 362 | * |
360 | * Locking: must be called within a read rcu section. | 363 | * Locking: must be called within a read rcu section. |
361 | */ | 364 | */ |
362 | struct mesh_path *mesh_path_lookup(const u8 *dst, | 365 | struct mesh_path * |
363 | struct ieee80211_sub_if_data *sdata) | 366 | mesh_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) |
364 | { | 367 | { |
365 | return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); | 368 | return mpath_lookup(rcu_dereference(mesh_paths), dst, sdata); |
366 | } | 369 | } |
367 | 370 | ||
368 | struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | 371 | struct mesh_path * |
372 | mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst) | ||
369 | { | 373 | { |
370 | return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); | 374 | return mpath_lookup(rcu_dereference(mpp_paths), dst, sdata); |
371 | } | 375 | } |
@@ -380,7 +384,8 @@ struct mesh_path *mpp_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
380 | * | 384 | * |
381 | * Locking: must be called within a read rcu section. | 385 | * Locking: must be called within a read rcu section. |
382 | */ | 386 | */ |
383 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) | 387 | struct mesh_path * |
388 | mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx) | ||
384 | { | 389 | { |
385 | struct mesh_table *tbl = rcu_dereference(mesh_paths); | 390 | struct mesh_table *tbl = rcu_dereference(mesh_paths); |
386 | struct mpath_node *node; | 391 | struct mpath_node *node; |
@@ -392,7 +397,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data | |||
392 | if (sdata && node->mpath->sdata != sdata) | 397 | if (sdata && node->mpath->sdata != sdata) |
393 | continue; | 398 | continue; |
394 | if (j++ == idx) { | 399 | if (j++ == idx) { |
395 | if (MPATH_EXPIRED(node->mpath)) { | 400 | if (mpath_expired(node->mpath)) { |
396 | spin_lock_bh(&node->mpath->state_lock); | 401 | spin_lock_bh(&node->mpath->state_lock); |
397 | node->mpath->flags &= ~MESH_PATH_ACTIVE; | 402 | node->mpath->flags &= ~MESH_PATH_ACTIVE; |
398 | spin_unlock_bh(&node->mpath->state_lock); | 403 | spin_unlock_bh(&node->mpath->state_lock); |
@@ -436,11 +441,10 @@ int mesh_path_add_gate(struct mesh_path *mpath) | |||
436 | spin_lock_bh(&tbl->gates_lock); | 441 | spin_lock_bh(&tbl->gates_lock); |
437 | hlist_add_head_rcu(&new_gate->list, tbl->known_gates); | 442 | hlist_add_head_rcu(&new_gate->list, tbl->known_gates); |
438 | spin_unlock_bh(&tbl->gates_lock); | 443 | spin_unlock_bh(&tbl->gates_lock); |
439 | rcu_read_unlock(); | ||
440 | mpath_dbg(mpath->sdata, | 444 | mpath_dbg(mpath->sdata, |
441 | "Mesh path: Recorded new gate: %pM. %d known gates\n", | 445 | "Mesh path: Recorded new gate: %pM. %d known gates\n", |
442 | mpath->dst, mpath->sdata->u.mesh.num_gates); | 446 | mpath->dst, mpath->sdata->u.mesh.num_gates); |
443 | return 0; | 447 | err = 0; |
444 | err_rcu: | 448 | err_rcu: |
445 | rcu_read_unlock(); | 449 | rcu_read_unlock(); |
446 | return err; | 450 | return err; |
@@ -451,30 +455,27 @@ err_rcu: | |||
451 | * @tbl: table which holds our list of known gates | 455 | * @tbl: table which holds our list of known gates |
452 | * @mpath: gate mpath | 456 | * @mpath: gate mpath |
453 | * | 457 | * |
454 | * Returns: 0 on success | ||
455 | * | ||
456 | * Locking: must be called inside rcu_read_lock() section | 458 | * Locking: must be called inside rcu_read_lock() section |
457 | */ | 459 | */ |
458 | static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) | 460 | static void mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) |
459 | { | 461 | { |
460 | struct mpath_node *gate; | 462 | struct mpath_node *gate; |
461 | struct hlist_node *p, *q; | 463 | struct hlist_node *p, *q; |
462 | 464 | ||
463 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) | 465 | hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) { |
464 | if (gate->mpath == mpath) { | 466 | if (gate->mpath != mpath) |
465 | spin_lock_bh(&tbl->gates_lock); | 467 | continue; |
466 | hlist_del_rcu(&gate->list); | 468 | spin_lock_bh(&tbl->gates_lock); |
467 | kfree_rcu(gate, rcu); | 469 | hlist_del_rcu(&gate->list); |
468 | spin_unlock_bh(&tbl->gates_lock); | 470 | kfree_rcu(gate, rcu); |
469 | mpath->sdata->u.mesh.num_gates--; | 471 | spin_unlock_bh(&tbl->gates_lock); |
470 | mpath->is_gate = false; | 472 | mpath->sdata->u.mesh.num_gates--; |
471 | mpath_dbg(mpath->sdata, | 473 | mpath->is_gate = false; |
472 | "Mesh path: Deleted gate: %pM. %d known gates\n", | 474 | mpath_dbg(mpath->sdata, |
473 | mpath->dst, mpath->sdata->u.mesh.num_gates); | 475 | "Mesh path: Deleted gate: %pM. %d known gates\n", |
474 | break; | 476 | mpath->dst, mpath->sdata->u.mesh.num_gates); |
475 | } | 477 | break; |
476 | 478 | } | |
477 | return 0; | ||
478 | } | 479 | } |
479 | 480 | ||
480 | /** | 481 | /** |
@@ -488,14 +489,14 @@ int mesh_gate_num(struct ieee80211_sub_if_data *sdata) | |||
488 | 489 | ||
489 | /** | 490 | /** |
490 | * mesh_path_add - allocate and add a new path to the mesh path table | 491 | * mesh_path_add - allocate and add a new path to the mesh path table |
491 | * @addr: destination address of the path (ETH_ALEN length) | 492 | * @dst: destination address of the path (ETH_ALEN length) |
492 | * @sdata: local subif | 493 | * @sdata: local subif |
493 | * | 494 | * |
494 | * Returns: 0 on success | 495 | * Returns: 0 on success |
495 | * | 496 | * |
496 | * State: the initial state of the new path is set to 0 | 497 | * State: the initial state of the new path is set to 0 |
497 | */ | 498 | */ |
498 | int mesh_path_add(const u8 *dst, struct ieee80211_sub_if_data *sdata) | 499 | int mesh_path_add(struct ieee80211_sub_if_data *sdata, const u8 *dst) |
499 | { | 500 | { |
500 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 501 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
501 | struct ieee80211_local *local = sdata->local; | 502 | struct ieee80211_local *local = sdata->local; |
@@ -630,7 +631,8 @@ void mesh_mpp_table_grow(void) | |||
630 | write_unlock_bh(&pathtbl_resize_lock); | 631 | write_unlock_bh(&pathtbl_resize_lock); |
631 | } | 632 | } |
632 | 633 | ||
633 | int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | 634 | int mpp_path_add(struct ieee80211_sub_if_data *sdata, |
635 | const u8 *dst, const u8 *mpp) | ||
634 | { | 636 | { |
635 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 637 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
636 | struct ieee80211_local *local = sdata->local; | 638 | struct ieee80211_local *local = sdata->local; |
@@ -739,9 +741,10 @@ void mesh_plink_broken(struct sta_info *sta) | |||
739 | mpath->flags &= ~MESH_PATH_ACTIVE; | 741 | mpath->flags &= ~MESH_PATH_ACTIVE; |
740 | ++mpath->sn; | 742 | ++mpath->sn; |
741 | spin_unlock_bh(&mpath->state_lock); | 743 | spin_unlock_bh(&mpath->state_lock); |
742 | mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, | 744 | mesh_path_error_tx(sdata, |
743 | mpath->dst, cpu_to_le32(mpath->sn), | 745 | sdata->u.mesh.mshcfg.element_ttl, |
744 | reason, bcast, sdata); | 746 | mpath->dst, cpu_to_le32(mpath->sn), |
747 | reason, bcast); | ||
745 | } | 748 | } |
746 | } | 749 | } |
747 | rcu_read_unlock(); | 750 | rcu_read_unlock(); |
@@ -856,7 +859,7 @@ void mesh_path_flush_by_iface(struct ieee80211_sub_if_data *sdata) | |||
856 | * | 859 | * |
857 | * Returns: 0 if successful | 860 | * Returns: 0 if successful |
858 | */ | 861 | */ |
859 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | 862 | int mesh_path_del(struct ieee80211_sub_if_data *sdata, const u8 *addr) |
860 | { | 863 | { |
861 | struct mesh_table *tbl; | 864 | struct mesh_table *tbl; |
862 | struct mesh_path *mpath; | 865 | struct mesh_path *mpath; |
@@ -965,8 +968,8 @@ int mesh_path_send_to_gates(struct mesh_path *mpath) | |||
965 | * | 968 | * |
966 | * Locking: the function must me called within a rcu_read_lock region | 969 | * Locking: the function must me called within a rcu_read_lock region |
967 | */ | 970 | */ |
968 | void mesh_path_discard_frame(struct sk_buff *skb, | 971 | void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata, |
969 | struct ieee80211_sub_if_data *sdata) | 972 | struct sk_buff *skb) |
970 | { | 973 | { |
971 | kfree_skb(skb); | 974 | kfree_skb(skb); |
972 | sdata->u.mesh.mshstats.dropped_frames_no_route++; | 975 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
@@ -984,7 +987,7 @@ void mesh_path_flush_pending(struct mesh_path *mpath) | |||
984 | struct sk_buff *skb; | 987 | struct sk_buff *skb; |
985 | 988 | ||
986 | while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) | 989 | while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL) |
987 | mesh_path_discard_frame(skb, mpath->sdata); | 990 | mesh_path_discard_frame(mpath->sdata, skb); |
988 | } | 991 | } |
989 | 992 | ||
990 | /** | 993 | /** |
@@ -1105,7 +1108,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
1105 | if ((!(mpath->flags & MESH_PATH_RESOLVING)) && | 1108 | if ((!(mpath->flags & MESH_PATH_RESOLVING)) && |
1106 | (!(mpath->flags & MESH_PATH_FIXED)) && | 1109 | (!(mpath->flags & MESH_PATH_FIXED)) && |
1107 | time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) | 1110 | time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE)) |
1108 | mesh_path_del(mpath->dst, mpath->sdata); | 1111 | mesh_path_del(mpath->sdata, mpath->dst); |
1109 | } | 1112 | } |
1110 | rcu_read_unlock(); | 1113 | rcu_read_unlock(); |
1111 | } | 1114 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f7526e509aa8..07d396d57079 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -37,9 +37,31 @@ enum plink_event { | |||
37 | CLS_IGNR | 37 | CLS_IGNR |
38 | }; | 38 | }; |
39 | 39 | ||
40 | static const char * const mplstates[] = { | ||
41 | [NL80211_PLINK_LISTEN] = "LISTEN", | ||
42 | [NL80211_PLINK_OPN_SNT] = "OPN-SNT", | ||
43 | [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", | ||
44 | [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", | ||
45 | [NL80211_PLINK_ESTAB] = "ESTAB", | ||
46 | [NL80211_PLINK_HOLDING] = "HOLDING", | ||
47 | [NL80211_PLINK_BLOCKED] = "BLOCKED" | ||
48 | }; | ||
49 | |||
50 | static const char * const mplevents[] = { | ||
51 | [PLINK_UNDEFINED] = "NONE", | ||
52 | [OPN_ACPT] = "OPN_ACPT", | ||
53 | [OPN_RJCT] = "OPN_RJCT", | ||
54 | [OPN_IGNR] = "OPN_IGNR", | ||
55 | [CNF_ACPT] = "CNF_ACPT", | ||
56 | [CNF_RJCT] = "CNF_RJCT", | ||
57 | [CNF_IGNR] = "CNF_IGNR", | ||
58 | [CLS_ACPT] = "CLS_ACPT", | ||
59 | [CLS_IGNR] = "CLS_IGNR" | ||
60 | }; | ||
61 | |||
40 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 62 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
41 | enum ieee80211_self_protected_actioncode action, | 63 | enum ieee80211_self_protected_actioncode action, |
42 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | 64 | u8 *da, __le16 llid, __le16 plid, __le16 reason); |
43 | 65 | ||
44 | /** | 66 | /** |
45 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine | 67 | * mesh_plink_fsm_restart - restart a mesh peer link finite state machine |
@@ -129,7 +151,6 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
129 | { | 151 | { |
130 | struct ieee80211_local *local = sdata->local; | 152 | struct ieee80211_local *local = sdata->local; |
131 | struct sta_info *sta; | 153 | struct sta_info *sta; |
132 | u32 changed = 0; | ||
133 | u16 ht_opmode; | 154 | u16 ht_opmode; |
134 | bool non_ht_sta = false, ht20_sta = false; | 155 | bool non_ht_sta = false, ht20_sta = false; |
135 | 156 | ||
@@ -142,23 +163,19 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
142 | sta->plink_state != NL80211_PLINK_ESTAB) | 163 | sta->plink_state != NL80211_PLINK_ESTAB) |
143 | continue; | 164 | continue; |
144 | 165 | ||
145 | switch (sta->ch_width) { | 166 | if (sta->sta.bandwidth > IEEE80211_STA_RX_BW_20) |
146 | case NL80211_CHAN_WIDTH_20_NOHT: | 167 | continue; |
147 | mpl_dbg(sdata, | 168 | |
148 | "mesh_plink %pM: nonHT sta (%pM) is present\n", | 169 | if (!sta->sta.ht_cap.ht_supported) { |
149 | sdata->vif.addr, sta->sta.addr); | 170 | mpl_dbg(sdata, "nonHT sta (%pM) is present\n", |
171 | sta->sta.addr); | ||
150 | non_ht_sta = true; | 172 | non_ht_sta = true; |
151 | goto out; | ||
152 | case NL80211_CHAN_WIDTH_20: | ||
153 | mpl_dbg(sdata, | ||
154 | "mesh_plink %pM: HT20 sta (%pM) is present\n", | ||
155 | sdata->vif.addr, sta->sta.addr); | ||
156 | ht20_sta = true; | ||
157 | default: | ||
158 | break; | 173 | break; |
159 | } | 174 | } |
175 | |||
176 | mpl_dbg(sdata, "HT20 sta (%pM) is present\n", sta->sta.addr); | ||
177 | ht20_sta = true; | ||
160 | } | 178 | } |
161 | out: | ||
162 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
163 | 180 | ||
164 | if (non_ht_sta) | 181 | if (non_ht_sta) |
@@ -169,16 +186,13 @@ out: | |||
169 | else | 186 | else |
170 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 187 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
171 | 188 | ||
172 | if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) { | 189 | if (sdata->vif.bss_conf.ht_operation_mode == ht_opmode) |
173 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; | 190 | return 0; |
174 | sdata->u.mesh.mshcfg.ht_opmode = ht_opmode; | ||
175 | changed = BSS_CHANGED_HT; | ||
176 | mpl_dbg(sdata, | ||
177 | "mesh_plink %pM: protection mode changed to %d\n", | ||
178 | sdata->vif.addr, ht_opmode); | ||
179 | } | ||
180 | 191 | ||
181 | return changed; | 192 | sdata->vif.bss_conf.ht_operation_mode = ht_opmode; |
193 | sdata->u.mesh.mshcfg.ht_opmode = ht_opmode; | ||
194 | mpl_dbg(sdata, "selected new HT protection mode %d\n", ht_opmode); | ||
195 | return BSS_CHANGED_HT; | ||
182 | } | 196 | } |
183 | 197 | ||
184 | /** | 198 | /** |
@@ -231,8 +245,9 @@ u32 mesh_plink_deactivate(struct sta_info *sta) | |||
231 | } | 245 | } |
232 | 246 | ||
233 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 247 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
234 | enum ieee80211_self_protected_actioncode action, | 248 | enum ieee80211_self_protected_actioncode action, |
235 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { | 249 | u8 *da, __le16 llid, __le16 plid, __le16 reason) |
250 | { | ||
236 | struct ieee80211_local *local = sdata->local; | 251 | struct ieee80211_local *local = sdata->local; |
237 | struct sk_buff *skb; | 252 | struct sk_buff *skb; |
238 | struct ieee80211_tx_info *info; | 253 | struct ieee80211_tx_info *info; |
@@ -283,13 +298,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
283 | } | 298 | } |
284 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 299 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
285 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || | 300 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
286 | mesh_add_rsn_ie(skb, sdata) || | 301 | mesh_add_rsn_ie(sdata, skb) || |
287 | mesh_add_meshid_ie(skb, sdata) || | 302 | mesh_add_meshid_ie(sdata, skb) || |
288 | mesh_add_meshconf_ie(skb, sdata)) | 303 | mesh_add_meshconf_ie(sdata, skb)) |
289 | goto free; | 304 | goto free; |
290 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ | 305 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ |
291 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | 306 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
292 | if (mesh_add_meshid_ie(skb, sdata)) | 307 | if (mesh_add_meshid_ie(sdata, skb)) |
293 | goto free; | 308 | goto free; |
294 | } | 309 | } |
295 | 310 | ||
@@ -333,12 +348,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
333 | } | 348 | } |
334 | 349 | ||
335 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 350 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
336 | if (mesh_add_ht_cap_ie(skb, sdata) || | 351 | if (mesh_add_ht_cap_ie(sdata, skb) || |
337 | mesh_add_ht_oper_ie(skb, sdata)) | 352 | mesh_add_ht_oper_ie(sdata, skb)) |
338 | goto free; | 353 | goto free; |
339 | } | 354 | } |
340 | 355 | ||
341 | if (mesh_add_vendor_ies(skb, sdata)) | 356 | if (mesh_add_vendor_ies(sdata, skb)) |
342 | goto free; | 357 | goto free; |
343 | 358 | ||
344 | ieee80211_tx_skb(sdata, skb); | 359 | ieee80211_tx_skb(sdata, skb); |
@@ -370,24 +385,18 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata, | |||
370 | if (sta->sta.supp_rates[band] != rates) | 385 | if (sta->sta.supp_rates[band] != rates) |
371 | changed |= IEEE80211_RC_SUPP_RATES_CHANGED; | 386 | changed |= IEEE80211_RC_SUPP_RATES_CHANGED; |
372 | sta->sta.supp_rates[band] = rates; | 387 | sta->sta.supp_rates[band] = rates; |
373 | if (elems->ht_cap_elem && | ||
374 | sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) | ||
375 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | ||
376 | elems->ht_cap_elem, sta); | ||
377 | else | ||
378 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); | ||
379 | 388 | ||
380 | if (elems->ht_operation) { | 389 | if (ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
381 | struct cfg80211_chan_def chandef; | 390 | elems->ht_cap_elem, sta)) |
391 | changed |= IEEE80211_RC_BW_CHANGED; | ||
382 | 392 | ||
383 | if (!(elems->ht_operation->ht_param & | 393 | /* HT peer is operating 20MHz-only */ |
384 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | 394 | if (elems->ht_operation && |
385 | sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; | 395 | !(elems->ht_operation->ht_param & |
386 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, | 396 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { |
387 | elems->ht_operation, &chandef); | 397 | if (sta->sta.bandwidth != IEEE80211_STA_RX_BW_20) |
388 | if (sta->ch_width != chandef.width) | ||
389 | changed |= IEEE80211_RC_BW_CHANGED; | 398 | changed |= IEEE80211_RC_BW_CHANGED; |
390 | sta->ch_width = chandef.width; | 399 | sta->sta.bandwidth = IEEE80211_STA_RX_BW_20; |
391 | } | 400 | } |
392 | 401 | ||
393 | if (insert) | 402 | if (insert) |
@@ -666,8 +675,9 @@ u32 mesh_plink_block(struct sta_info *sta) | |||
666 | } | 675 | } |
667 | 676 | ||
668 | 677 | ||
669 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 678 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, |
670 | size_t len, struct ieee80211_rx_status *rx_status) | 679 | struct ieee80211_mgmt *mgmt, size_t len, |
680 | struct ieee80211_rx_status *rx_status) | ||
671 | { | 681 | { |
672 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; | 682 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; |
673 | struct ieee802_11_elems elems; | 683 | struct ieee802_11_elems elems; |
@@ -680,15 +690,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
680 | u8 *baseaddr; | 690 | u8 *baseaddr; |
681 | u32 changed = 0; | 691 | u32 changed = 0; |
682 | __le16 plid, llid, reason; | 692 | __le16 plid, llid, reason; |
683 | static const char *mplstates[] = { | ||
684 | [NL80211_PLINK_LISTEN] = "LISTEN", | ||
685 | [NL80211_PLINK_OPN_SNT] = "OPN-SNT", | ||
686 | [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", | ||
687 | [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", | ||
688 | [NL80211_PLINK_ESTAB] = "ESTAB", | ||
689 | [NL80211_PLINK_HOLDING] = "HOLDING", | ||
690 | [NL80211_PLINK_BLOCKED] = "BLOCKED" | ||
691 | }; | ||
692 | 693 | ||
693 | /* need action_code, aux */ | 694 | /* need action_code, aux */ |
694 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | 695 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) |
@@ -708,13 +709,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
708 | baselen += 4; | 709 | baselen += 4; |
709 | } | 710 | } |
710 | ieee802_11_parse_elems(baseaddr, len - baselen, &elems); | 711 | ieee802_11_parse_elems(baseaddr, len - baselen, &elems); |
712 | |||
711 | if (!elems.peering) { | 713 | if (!elems.peering) { |
712 | mpl_dbg(sdata, | 714 | mpl_dbg(sdata, |
713 | "Mesh plink: missing necessary peer link ie\n"); | 715 | "Mesh plink: missing necessary peer link ie\n"); |
714 | return; | 716 | return; |
715 | } | 717 | } |
718 | |||
716 | if (elems.rsn_len && | 719 | if (elems.rsn_len && |
717 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | 720 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { |
718 | mpl_dbg(sdata, | 721 | mpl_dbg(sdata, |
719 | "Mesh plink: can't establish link with secure peer\n"); | 722 | "Mesh plink: can't establish link with secure peer\n"); |
720 | return; | 723 | return; |
@@ -733,7 +736,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
733 | } | 736 | } |
734 | 737 | ||
735 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && | 738 | if (ftype != WLAN_SP_MESH_PEERING_CLOSE && |
736 | (!elems.mesh_id || !elems.mesh_config)) { | 739 | (!elems.mesh_id || !elems.mesh_config)) { |
737 | mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); | 740 | mpl_dbg(sdata, "Mesh plink: missing necessary ie\n"); |
738 | return; | 741 | return; |
739 | } | 742 | } |
@@ -859,11 +862,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
859 | } | 862 | } |
860 | } | 863 | } |
861 | 864 | ||
862 | mpl_dbg(sdata, | 865 | mpl_dbg(sdata, "peer %pM in state %s got event %s\n", mgmt->sa, |
863 | "Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", | 866 | mplstates[sta->plink_state], mplevents[event]); |
864 | mgmt->sa, mplstates[sta->plink_state], | ||
865 | le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), | ||
866 | event); | ||
867 | reason = 0; | 867 | reason = 0; |
868 | spin_lock_bh(&sta->lock); | 868 | spin_lock_bh(&sta->lock); |
869 | switch (sta->plink_state) { | 869 | switch (sta->plink_state) { |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index aa8d1e437385..05a256b38e24 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -43,7 +43,7 @@ struct sync_method { | |||
43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) | 43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) |
44 | { | 44 | { |
45 | return (ie->mesh_config->meshconf_cap & | 45 | return (ie->mesh_config->meshconf_cap & |
46 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; | 46 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | 49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) |
@@ -112,7 +112,8 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
112 | 112 | ||
113 | if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { | 113 | if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { |
114 | clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | 114 | clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); |
115 | msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", sta->sta.addr); | 115 | msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", |
116 | sta->sta.addr); | ||
116 | goto no_sync; | 117 | goto no_sync; |
117 | } | 118 | } |
118 | 119 | ||
@@ -129,18 +130,15 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
129 | sta->t_offset = t_t - t_r; | 130 | sta->t_offset = t_t - t_r; |
130 | 131 | ||
131 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | 132 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { |
132 | s64 t_clockdrift = sta->t_offset_setpoint | 133 | s64 t_clockdrift = sta->t_offset_setpoint - sta->t_offset; |
133 | - sta->t_offset; | ||
134 | msync_dbg(sdata, | 134 | msync_dbg(sdata, |
135 | "STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n", | 135 | "STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld\n", |
136 | sta->sta.addr, | 136 | sta->sta.addr, (long long) sta->t_offset, |
137 | (long long) sta->t_offset, | 137 | (long long) sta->t_offset_setpoint, |
138 | (long long) | ||
139 | sta->t_offset_setpoint, | ||
140 | (long long) t_clockdrift); | 138 | (long long) t_clockdrift); |
141 | 139 | ||
142 | if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT || | 140 | if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT || |
143 | t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) { | 141 | t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) { |
144 | msync_dbg(sdata, | 142 | msync_dbg(sdata, |
145 | "STA %pM : t_clockdrift=%lld too large, setpoint reset\n", | 143 | "STA %pM : t_clockdrift=%lld too large, setpoint reset\n", |
146 | sta->sta.addr, | 144 | sta->sta.addr, |
@@ -149,15 +147,10 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
149 | goto no_sync; | 147 | goto no_sync; |
150 | } | 148 | } |
151 | 149 | ||
152 | rcu_read_unlock(); | ||
153 | |||
154 | spin_lock_bh(&ifmsh->sync_offset_lock); | 150 | spin_lock_bh(&ifmsh->sync_offset_lock); |
155 | if (t_clockdrift > | 151 | if (t_clockdrift > ifmsh->sync_offset_clockdrift_max) |
156 | ifmsh->sync_offset_clockdrift_max) | 152 | ifmsh->sync_offset_clockdrift_max = t_clockdrift; |
157 | ifmsh->sync_offset_clockdrift_max | ||
158 | = t_clockdrift; | ||
159 | spin_unlock_bh(&ifmsh->sync_offset_lock); | 153 | spin_unlock_bh(&ifmsh->sync_offset_lock); |
160 | |||
161 | } else { | 154 | } else { |
162 | sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN; | 155 | sta->t_offset_setpoint = sta->t_offset - TOFFSET_SET_MARGIN; |
163 | set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); | 156 | set_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); |
@@ -165,9 +158,7 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
165 | "STA %pM : offset was invalid, sta->t_offset=%lld\n", | 158 | "STA %pM : offset was invalid, sta->t_offset=%lld\n", |
166 | sta->sta.addr, | 159 | sta->sta.addr, |
167 | (long long) sta->t_offset); | 160 | (long long) sta->t_offset); |
168 | rcu_read_unlock(); | ||
169 | } | 161 | } |
170 | return; | ||
171 | 162 | ||
172 | no_sync: | 163 | no_sync: |
173 | rcu_read_unlock(); | 164 | rcu_read_unlock(); |
@@ -177,14 +168,12 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
177 | { | 168 | { |
178 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 169 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
179 | 170 | ||
180 | WARN_ON(ifmsh->mesh_sp_id | 171 | WARN_ON(ifmsh->mesh_sp_id != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); |
181 | != IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET); | ||
182 | BUG_ON(!rcu_read_lock_held()); | 172 | BUG_ON(!rcu_read_lock_held()); |
183 | 173 | ||
184 | spin_lock_bh(&ifmsh->sync_offset_lock); | 174 | spin_lock_bh(&ifmsh->sync_offset_lock); |
185 | 175 | ||
186 | if (ifmsh->sync_offset_clockdrift_max > | 176 | if (ifmsh->sync_offset_clockdrift_max > TOFFSET_MINIMUM_ADJUSTMENT) { |
187 | TOFFSET_MINIMUM_ADJUSTMENT) { | ||
188 | /* Since ajusting the tsf here would | 177 | /* Since ajusting the tsf here would |
189 | * require a possibly blocking call | 178 | * require a possibly blocking call |
190 | * to the driver tsf setter, we punt | 179 | * to the driver tsf setter, we punt |
@@ -193,8 +182,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | |||
193 | msync_dbg(sdata, | 182 | msync_dbg(sdata, |
194 | "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", | 183 | "TBTT : kicking off TBTT adjustment with clockdrift_max=%lld\n", |
195 | ifmsh->sync_offset_clockdrift_max); | 184 | ifmsh->sync_offset_clockdrift_max); |
196 | set_bit(MESH_WORK_DRIFT_ADJUST, | 185 | set_bit(MESH_WORK_DRIFT_ADJUST, &ifmsh->wrkq_flags); |
197 | &ifmsh->wrkq_flags); | ||
198 | 186 | ||
199 | ifmsh->adjusting_tbtt = true; | 187 | ifmsh->adjusting_tbtt = true; |
200 | } else { | 188 | } else { |
@@ -220,14 +208,11 @@ static const struct sync_method sync_methods[] = { | |||
220 | 208 | ||
221 | const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) | 209 | const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method) |
222 | { | 210 | { |
223 | const struct ieee80211_mesh_sync_ops *ops = NULL; | 211 | int i; |
224 | u8 i; | ||
225 | 212 | ||
226 | for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { | 213 | for (i = 0 ; i < ARRAY_SIZE(sync_methods); ++i) { |
227 | if (sync_methods[i].method == method) { | 214 | if (sync_methods[i].method == method) |
228 | ops = &sync_methods[i].ops; | 215 | return &sync_methods[i].ops; |
229 | break; | ||
230 | } | ||
231 | } | 216 | } |
232 | return ops; | 217 | return NULL; |
233 | } | 218 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3acb70b73e22..bb73ed2d20b9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2027,7 +2027,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2027 | /* frame is in RMC, don't forward */ | 2027 | /* frame is in RMC, don't forward */ |
2028 | if (ieee80211_is_data(hdr->frame_control) && | 2028 | if (ieee80211_is_data(hdr->frame_control) && |
2029 | is_multicast_ether_addr(hdr->addr1) && | 2029 | is_multicast_ether_addr(hdr->addr1) && |
2030 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) | 2030 | mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr)) |
2031 | return RX_DROP_MONITOR; | 2031 | return RX_DROP_MONITOR; |
2032 | 2032 | ||
2033 | if (!ieee80211_is_data(hdr->frame_control) || | 2033 | if (!ieee80211_is_data(hdr->frame_control) || |
@@ -2054,9 +2054,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2054 | } | 2054 | } |
2055 | 2055 | ||
2056 | rcu_read_lock(); | 2056 | rcu_read_lock(); |
2057 | mppath = mpp_path_lookup(proxied_addr, sdata); | 2057 | mppath = mpp_path_lookup(sdata, proxied_addr); |
2058 | if (!mppath) { | 2058 | if (!mppath) { |
2059 | mpp_path_add(proxied_addr, mpp_addr, sdata); | 2059 | mpp_path_add(sdata, proxied_addr, mpp_addr); |
2060 | } else { | 2060 | } else { |
2061 | spin_lock_bh(&mppath->state_lock); | 2061 | spin_lock_bh(&mppath->state_lock); |
2062 | if (!ether_addr_equal(mppath->mpp, mpp_addr)) | 2062 | if (!ether_addr_equal(mppath->mpp, mpp_addr)) |
@@ -2104,13 +2104,13 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
2104 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); | 2104 | memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); |
2105 | /* update power mode indication when forwarding */ | 2105 | /* update power mode indication when forwarding */ |
2106 | ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); | 2106 | ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); |
2107 | } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { | 2107 | } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) { |
2108 | /* mesh power mode flags updated in mesh_nexthop_lookup */ | 2108 | /* mesh power mode flags updated in mesh_nexthop_lookup */ |
2109 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); | 2109 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); |
2110 | } else { | 2110 | } else { |
2111 | /* unable to resolve next hop */ | 2111 | /* unable to resolve next hop */ |
2112 | mesh_path_error_tx(ifmsh->mshcfg.element_ttl, fwd_hdr->addr3, | 2112 | mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, |
2113 | 0, reason, fwd_hdr->addr2, sdata); | 2113 | fwd_hdr->addr3, 0, reason, fwd_hdr->addr2); |
2114 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); | 2114 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); |
2115 | kfree_skb(fwd_skb); | 2115 | kfree_skb(fwd_skb); |
2116 | return RX_DROP_MONITOR; | 2116 | return RX_DROP_MONITOR; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 63dfdb5e91da..4947341a2a82 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -285,7 +285,6 @@ struct sta_ampdu_mlme { | |||
285 | * @t_offset: timing offset relative to this host | 285 | * @t_offset: timing offset relative to this host |
286 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 286 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
287 | * calculating clockdrift | 287 | * calculating clockdrift |
288 | * @ch_width: peer's channel width | ||
289 | * @local_pm: local link-specific power save mode | 288 | * @local_pm: local link-specific power save mode |
290 | * @peer_pm: peer-specific power save mode towards local STA | 289 | * @peer_pm: peer-specific power save mode towards local STA |
291 | * @nonpeer_pm: STA power save mode towards non-peer neighbors | 290 | * @nonpeer_pm: STA power save mode towards non-peer neighbors |
@@ -386,7 +385,6 @@ struct sta_info { | |||
386 | struct timer_list plink_timer; | 385 | struct timer_list plink_timer; |
387 | s64 t_offset; | 386 | s64 t_offset; |
388 | s64 t_offset_setpoint; | 387 | s64 t_offset_setpoint; |
389 | enum nl80211_chan_width ch_width; | ||
390 | /* mesh power save */ | 388 | /* mesh power save */ |
391 | enum nl80211_mesh_power_mode local_pm; | 389 | enum nl80211_mesh_power_mode local_pm; |
392 | enum nl80211_mesh_power_mode peer_pm; | 390 | enum nl80211_mesh_power_mode peer_pm; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 1183c4a4fee5..3d7cd2a0582f 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -479,7 +479,7 @@ TRACE_EVENT(drv_set_tim, | |||
479 | 479 | ||
480 | TP_printk( | 480 | TP_printk( |
481 | LOCAL_PR_FMT STA_PR_FMT " set:%d", | 481 | LOCAL_PR_FMT STA_PR_FMT " set:%d", |
482 | LOCAL_PR_ARG, STA_PR_FMT, __entry->set | 482 | LOCAL_PR_ARG, STA_PR_ARG, __entry->set |
483 | ) | 483 | ) |
484 | ); | 484 | ); |
485 | 485 | ||
@@ -1684,7 +1684,7 @@ TRACE_EVENT(api_sta_block_awake, | |||
1684 | 1684 | ||
1685 | TP_printk( | 1685 | TP_printk( |
1686 | LOCAL_PR_FMT STA_PR_FMT " block:%d", | 1686 | LOCAL_PR_FMT STA_PR_FMT " block:%d", |
1687 | LOCAL_PR_ARG, STA_PR_FMT, __entry->block | 1687 | LOCAL_PR_ARG, STA_PR_ARG, __entry->block |
1688 | ) | 1688 | ) |
1689 | ); | 1689 | ); |
1690 | 1690 | ||
@@ -1782,7 +1782,7 @@ TRACE_EVENT(api_eosp, | |||
1782 | 1782 | ||
1783 | TP_printk( | 1783 | TP_printk( |
1784 | LOCAL_PR_FMT STA_PR_FMT, | 1784 | LOCAL_PR_FMT STA_PR_FMT, |
1785 | LOCAL_PR_ARG, STA_PR_FMT | 1785 | LOCAL_PR_ARG, STA_PR_ARG |
1786 | ) | 1786 | ) |
1787 | ); | 1787 | ); |
1788 | 1788 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index fe644f91ae05..5b9602b62405 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1495,7 +1495,7 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | |||
1495 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1495 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1496 | if (ieee80211_is_data(hdr->frame_control) && | 1496 | if (ieee80211_is_data(hdr->frame_control) && |
1497 | is_unicast_ether_addr(hdr->addr1)) { | 1497 | is_unicast_ether_addr(hdr->addr1)) { |
1498 | if (mesh_nexthop_resolve(skb, sdata)) | 1498 | if (mesh_nexthop_resolve(sdata, skb)) |
1499 | return; /* skb queued: don't free */ | 1499 | return; /* skb queued: don't free */ |
1500 | } else { | 1500 | } else { |
1501 | ieee80211_mps_set_frame_flags(sdata, NULL, hdr); | 1501 | ieee80211_mps_set_frame_flags(sdata, NULL, hdr); |
@@ -1844,9 +1844,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1844 | } | 1844 | } |
1845 | 1845 | ||
1846 | if (!is_multicast_ether_addr(skb->data)) { | 1846 | if (!is_multicast_ether_addr(skb->data)) { |
1847 | mpath = mesh_path_lookup(skb->data, sdata); | 1847 | mpath = mesh_path_lookup(sdata, skb->data); |
1848 | if (!mpath) | 1848 | if (!mpath) |
1849 | mppath = mpp_path_lookup(skb->data, sdata); | 1849 | mppath = mpp_path_lookup(sdata, skb->data); |
1850 | } | 1850 | } |
1851 | 1851 | ||
1852 | /* | 1852 | /* |
@@ -1859,8 +1859,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1859 | !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { | 1859 | !(mppath && !ether_addr_equal(mppath->mpp, skb->data))) { |
1860 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1860 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1861 | skb->data, skb->data + ETH_ALEN); | 1861 | skb->data, skb->data + ETH_ALEN); |
1862 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1862 | meshhdrlen = ieee80211_new_mesh_header(sdata, &mesh_hdr, |
1863 | sdata, NULL, NULL); | 1863 | NULL, NULL); |
1864 | } else { | 1864 | } else { |
1865 | /* DS -> MBSS (802.11-2012 13.11.3.3). | 1865 | /* DS -> MBSS (802.11-2012 13.11.3.3). |
1866 | * For unicast with unknown forwarding information, | 1866 | * For unicast with unknown forwarding information, |
@@ -1879,18 +1879,14 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1879 | mesh_da, sdata->vif.addr); | 1879 | mesh_da, sdata->vif.addr); |
1880 | if (is_multicast_ether_addr(mesh_da)) | 1880 | if (is_multicast_ether_addr(mesh_da)) |
1881 | /* DA TA mSA AE:SA */ | 1881 | /* DA TA mSA AE:SA */ |
1882 | meshhdrlen = | 1882 | meshhdrlen = ieee80211_new_mesh_header( |
1883 | ieee80211_new_mesh_header(&mesh_hdr, | 1883 | sdata, &mesh_hdr, |
1884 | sdata, | 1884 | skb->data + ETH_ALEN, NULL); |
1885 | skb->data + ETH_ALEN, | ||
1886 | NULL); | ||
1887 | else | 1885 | else |
1888 | /* RA TA mDA mSA AE:DA SA */ | 1886 | /* RA TA mDA mSA AE:DA SA */ |
1889 | meshhdrlen = | 1887 | meshhdrlen = ieee80211_new_mesh_header( |
1890 | ieee80211_new_mesh_header(&mesh_hdr, | 1888 | sdata, &mesh_hdr, skb->data, |
1891 | sdata, | 1889 | skb->data + ETH_ALEN); |
1892 | skb->data, | ||
1893 | skb->data + ETH_ALEN); | ||
1894 | 1890 | ||
1895 | } | 1891 | } |
1896 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1892 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 580ffeaef3d5..35545ccc30fd 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -3418,19 +3418,10 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | |||
3418 | static int nl80211_set_station_tdls(struct genl_info *info, | 3418 | static int nl80211_set_station_tdls(struct genl_info *info, |
3419 | struct station_parameters *params) | 3419 | struct station_parameters *params) |
3420 | { | 3420 | { |
3421 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
3422 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; | 3421 | struct nlattr *tb[NL80211_STA_WME_MAX + 1]; |
3423 | struct nlattr *nla; | 3422 | struct nlattr *nla; |
3424 | int err; | 3423 | int err; |
3425 | 3424 | ||
3426 | /* Can only set if TDLS ... */ | ||
3427 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
3428 | return -EOPNOTSUPP; | ||
3429 | |||
3430 | /* ... with external setup is supported */ | ||
3431 | if (!(rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) | ||
3432 | return -EOPNOTSUPP; | ||
3433 | |||
3434 | /* Dummy STA entry gets updated once the peer capabilities are known */ | 3425 | /* Dummy STA entry gets updated once the peer capabilities are known */ |
3435 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) | 3426 | if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) |
3436 | params->ht_capa = | 3427 | params->ht_capa = |