diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 24 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mvm.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/scan.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/sta.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/tx.c | 91 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/utils.c | 2 |
7 files changed, 78 insertions, 52 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 73cbba7424f2..9426905de6b2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -504,6 +504,7 @@ struct iwl_scan_offload_profile { | |||
504 | * @match_notify: clients waiting for match found notification | 504 | * @match_notify: clients waiting for match found notification |
505 | * @pass_match: clients waiting for the results | 505 | * @pass_match: clients waiting for the results |
506 | * @active_clients: active clients bitmap - enum scan_framework_client | 506 | * @active_clients: active clients bitmap - enum scan_framework_client |
507 | * @any_beacon_notify: clients waiting for match notification without match | ||
507 | */ | 508 | */ |
508 | struct iwl_scan_offload_profile_cfg { | 509 | struct iwl_scan_offload_profile_cfg { |
509 | struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; | 510 | struct iwl_scan_offload_profile profiles[IWL_SCAN_MAX_PROFILES]; |
@@ -512,7 +513,8 @@ struct iwl_scan_offload_profile_cfg { | |||
512 | u8 match_notify; | 513 | u8 match_notify; |
513 | u8 pass_match; | 514 | u8 pass_match; |
514 | u8 active_clients; | 515 | u8 active_clients; |
515 | u8 reserved[3]; | 516 | u8 any_beacon_notify; |
517 | u8 reserved[2]; | ||
516 | } __packed; | 518 | } __packed; |
517 | 519 | ||
518 | /** | 520 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index c49b5073c251..c35b8661b395 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -246,7 +246,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
246 | else | 246 | else |
247 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 247 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
248 | 248 | ||
249 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { | 249 | if (0 && mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SCHED_SCAN) { |
250 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 250 | hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
251 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; | 251 | hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; |
252 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; | 252 | hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; |
@@ -328,6 +328,24 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, | |||
328 | ieee80211_free_txskb(hw, skb); | 328 | ieee80211_free_txskb(hw, skb); |
329 | } | 329 | } |
330 | 330 | ||
331 | static inline bool iwl_enable_rx_ampdu(const struct iwl_cfg *cfg) | ||
332 | { | ||
333 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) | ||
334 | return false; | ||
335 | return true; | ||
336 | } | ||
337 | |||
338 | static inline bool iwl_enable_tx_ampdu(const struct iwl_cfg *cfg) | ||
339 | { | ||
340 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) | ||
341 | return false; | ||
342 | if (iwlwifi_mod_params.disable_11n & IWL_ENABLE_HT_TXAGG) | ||
343 | return true; | ||
344 | |||
345 | /* enabled by default */ | ||
346 | return true; | ||
347 | } | ||
348 | |||
331 | static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | 349 | static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, |
332 | struct ieee80211_vif *vif, | 350 | struct ieee80211_vif *vif, |
333 | enum ieee80211_ampdu_mlme_action action, | 351 | enum ieee80211_ampdu_mlme_action action, |
@@ -347,7 +365,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
347 | 365 | ||
348 | switch (action) { | 366 | switch (action) { |
349 | case IEEE80211_AMPDU_RX_START: | 367 | case IEEE80211_AMPDU_RX_START: |
350 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_RXAGG) { | 368 | if (!iwl_enable_rx_ampdu(mvm->cfg)) { |
351 | ret = -EINVAL; | 369 | ret = -EINVAL; |
352 | break; | 370 | break; |
353 | } | 371 | } |
@@ -357,7 +375,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
357 | ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); | 375 | ret = iwl_mvm_sta_rx_agg(mvm, sta, tid, 0, false); |
358 | break; | 376 | break; |
359 | case IEEE80211_AMPDU_TX_START: | 377 | case IEEE80211_AMPDU_TX_START: |
360 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) { | 378 | if (!iwl_enable_tx_ampdu(mvm->cfg)) { |
361 | ret = -EINVAL; | 379 | ret = -EINVAL; |
362 | break; | 380 | break; |
363 | } | 381 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index e4ead86f06d6..2b0ba1fc3c82 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -152,7 +152,7 @@ enum iwl_power_scheme { | |||
152 | IWL_POWER_SCHEME_LP | 152 | IWL_POWER_SCHEME_LP |
153 | }; | 153 | }; |
154 | 154 | ||
155 | #define IWL_CONN_MAX_LISTEN_INTERVAL 70 | 155 | #define IWL_CONN_MAX_LISTEN_INTERVAL 10 |
156 | #define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ | 156 | #define IWL_UAPSD_AC_INFO (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ |
157 | IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\ | 157 | IEEE80211_WMM_IE_STA_QOSINFO_AC_VI |\ |
158 | IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\ | 158 | IEEE80211_WMM_IE_STA_QOSINFO_AC_BK |\ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 0e0007960612..742afc429c94 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -344,7 +344,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, | |||
344 | 344 | ||
345 | iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0); | 345 | iwl_mvm_scan_fill_ssids(cmd, req, basic_ssid ? 1 : 0); |
346 | 346 | ||
347 | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL); | 347 | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | |
348 | TX_CMD_FLG_BT_DIS); | ||
348 | cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; | 349 | cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; |
349 | cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); | 350 | cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); |
350 | cmd->tx_cmd.rate_n_flags = | 351 | cmd->tx_cmd.rate_n_flags = |
@@ -807,6 +808,8 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | |||
807 | profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN; | 808 | profile_cfg->active_clients = SCAN_CLIENT_SCHED_SCAN; |
808 | profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN; | 809 | profile_cfg->pass_match = SCAN_CLIENT_SCHED_SCAN; |
809 | profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN; | 810 | profile_cfg->match_notify = SCAN_CLIENT_SCHED_SCAN; |
811 | if (!req->n_match_sets || !req->match_sets[0].ssid.ssid_len) | ||
812 | profile_cfg->any_beacon_notify = SCAN_CLIENT_SCHED_SCAN; | ||
810 | 813 | ||
811 | for (i = 0; i < req->n_match_sets; i++) { | 814 | for (i = 0; i < req->n_match_sets; i++) { |
812 | profile = &profile_cfg->profiles[i]; | 815 | profile = &profile_cfg->profiles[i]; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index ec1812133235..3397f59cd4e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -652,7 +652,7 @@ int iwl_mvm_send_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
652 | { | 652 | { |
653 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 653 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
654 | static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; | 654 | static const u8 _baddr[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
655 | static const u8 *baddr = _baddr; | 655 | const u8 *baddr = _baddr; |
656 | 656 | ||
657 | lockdep_assert_held(&mvm->mutex); | 657 | lockdep_assert_held(&mvm->mutex); |
658 | 658 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 90378c217bc7..76ee486039d7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -659,8 +659,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
659 | rcu_read_lock(); | 659 | rcu_read_lock(); |
660 | 660 | ||
661 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | 661 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); |
662 | /* | ||
663 | * sta can't be NULL otherwise it'd mean that the sta has been freed in | ||
664 | * the firmware while we still have packets for it in the Tx queues. | ||
665 | */ | ||
666 | if (WARN_ON_ONCE(!sta)) | ||
667 | goto out; | ||
662 | 668 | ||
663 | if (!IS_ERR_OR_NULL(sta)) { | 669 | if (!IS_ERR(sta)) { |
664 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 670 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
665 | 671 | ||
666 | if (tid != IWL_TID_NON_QOS) { | 672 | if (tid != IWL_TID_NON_QOS) { |
@@ -675,7 +681,6 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
675 | spin_unlock_bh(&mvmsta->lock); | 681 | spin_unlock_bh(&mvmsta->lock); |
676 | } | 682 | } |
677 | } else { | 683 | } else { |
678 | sta = NULL; | ||
679 | mvmsta = NULL; | 684 | mvmsta = NULL; |
680 | } | 685 | } |
681 | 686 | ||
@@ -683,42 +688,38 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
683 | * If the txq is not an AMPDU queue, there is no chance we freed | 688 | * If the txq is not an AMPDU queue, there is no chance we freed |
684 | * several skbs. Check that out... | 689 | * several skbs. Check that out... |
685 | */ | 690 | */ |
686 | if (txq_id < mvm->first_agg_queue && !WARN_ON(skb_freed > 1) && | 691 | if (txq_id >= mvm->first_agg_queue) |
687 | atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) { | 692 | goto out; |
688 | if (mvmsta) { | 693 | |
689 | /* | 694 | /* We can't free more than one frame at once on a shared queue */ |
690 | * If there are no pending frames for this STA, notify | 695 | WARN_ON(skb_freed > 1); |
691 | * mac80211 that this station can go to sleep in its | 696 | |
692 | * STA table. | 697 | /* If we have still frames from this STA nothing to do here */ |
693 | */ | 698 | if (!atomic_sub_and_test(skb_freed, &mvm->pending_frames[sta_id])) |
694 | if (mvmsta->vif->type == NL80211_IFTYPE_AP) | 699 | goto out; |
695 | ieee80211_sta_block_awake(mvm->hw, sta, false); | 700 | |
696 | /* | 701 | if (mvmsta && mvmsta->vif->type == NL80211_IFTYPE_AP) { |
697 | * We might very well have taken mvmsta pointer while | 702 | /* |
698 | * the station was being removed. The remove flow might | 703 | * If there are no pending frames for this STA, notify |
699 | * have seen a pending_frame (because we didn't take | 704 | * mac80211 that this station can go to sleep in its |
700 | * the lock) even if now the queues are drained. So make | 705 | * STA table. |
701 | * really sure now that this the station is not being | 706 | * If mvmsta is not NULL, sta is valid. |
702 | * removed. If it is, run the drain worker to remove it. | 707 | */ |
703 | */ | 708 | ieee80211_sta_block_awake(mvm->hw, sta, false); |
704 | spin_lock_bh(&mvmsta->lock); | ||
705 | sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); | ||
706 | if (!sta || PTR_ERR(sta) == -EBUSY) { | ||
707 | /* | ||
708 | * Station disappeared in the meantime: | ||
709 | * so we are draining. | ||
710 | */ | ||
711 | set_bit(sta_id, mvm->sta_drained); | ||
712 | schedule_work(&mvm->sta_drained_wk); | ||
713 | } | ||
714 | spin_unlock_bh(&mvmsta->lock); | ||
715 | } else if (!mvmsta && PTR_ERR(sta) == -EBUSY) { | ||
716 | /* Tx response without STA, so we are draining */ | ||
717 | set_bit(sta_id, mvm->sta_drained); | ||
718 | schedule_work(&mvm->sta_drained_wk); | ||
719 | } | ||
720 | } | 709 | } |
721 | 710 | ||
711 | if (PTR_ERR(sta) == -EBUSY || PTR_ERR(sta) == -ENOENT) { | ||
712 | /* | ||
713 | * We are draining and this was the last packet - pre_rcu_remove | ||
714 | * has been called already. We might be after the | ||
715 | * synchronize_net already. | ||
716 | * Don't rely on iwl_mvm_rm_sta to see the empty Tx queues. | ||
717 | */ | ||
718 | set_bit(sta_id, mvm->sta_drained); | ||
719 | schedule_work(&mvm->sta_drained_wk); | ||
720 | } | ||
721 | |||
722 | out: | ||
722 | rcu_read_unlock(); | 723 | rcu_read_unlock(); |
723 | } | 724 | } |
724 | 725 | ||
@@ -821,16 +822,12 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
821 | struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data; | 822 | struct iwl_mvm_ba_notif *ba_notif = (void *)pkt->data; |
822 | struct sk_buff_head reclaimed_skbs; | 823 | struct sk_buff_head reclaimed_skbs; |
823 | struct iwl_mvm_tid_data *tid_data; | 824 | struct iwl_mvm_tid_data *tid_data; |
824 | struct ieee80211_tx_info *info; | ||
825 | struct ieee80211_sta *sta; | 825 | struct ieee80211_sta *sta; |
826 | struct iwl_mvm_sta *mvmsta; | 826 | struct iwl_mvm_sta *mvmsta; |
827 | struct ieee80211_hdr *hdr; | ||
828 | struct sk_buff *skb; | 827 | struct sk_buff *skb; |
829 | int sta_id, tid, freed; | 828 | int sta_id, tid, freed; |
830 | |||
831 | /* "flow" corresponds to Tx queue */ | 829 | /* "flow" corresponds to Tx queue */ |
832 | u16 scd_flow = le16_to_cpu(ba_notif->scd_flow); | 830 | u16 scd_flow = le16_to_cpu(ba_notif->scd_flow); |
833 | |||
834 | /* "ssn" is start of block-ack Tx window, corresponds to index | 831 | /* "ssn" is start of block-ack Tx window, corresponds to index |
835 | * (in Tx queue's circular buffer) of first TFD/frame in window */ | 832 | * (in Tx queue's circular buffer) of first TFD/frame in window */ |
836 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn); | 833 | u16 ba_resp_scd_ssn = le16_to_cpu(ba_notif->scd_ssn); |
@@ -887,22 +884,26 @@ int iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb, | |||
887 | freed = 0; | 884 | freed = 0; |
888 | 885 | ||
889 | skb_queue_walk(&reclaimed_skbs, skb) { | 886 | skb_queue_walk(&reclaimed_skbs, skb) { |
890 | hdr = (struct ieee80211_hdr *)skb->data; | 887 | struct ieee80211_hdr *hdr = (void *)skb->data; |
888 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
891 | 889 | ||
892 | if (ieee80211_is_data_qos(hdr->frame_control)) | 890 | if (ieee80211_is_data_qos(hdr->frame_control)) |
893 | freed++; | 891 | freed++; |
894 | else | 892 | else |
895 | WARN_ON_ONCE(1); | 893 | WARN_ON_ONCE(1); |
896 | 894 | ||
897 | info = IEEE80211_SKB_CB(skb); | ||
898 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); | 895 | iwl_trans_free_tx_cmd(mvm->trans, info->driver_data[1]); |
899 | 896 | ||
897 | memset(&info->status, 0, sizeof(info->status)); | ||
898 | /* Packet was transmitted successfully, failures come as single | ||
899 | * frames because before failing a frame the firmware transmits | ||
900 | * it without aggregation at least once. | ||
901 | */ | ||
902 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
903 | |||
900 | if (freed == 1) { | 904 | if (freed == 1) { |
901 | /* this is the first skb we deliver in this batch */ | 905 | /* this is the first skb we deliver in this batch */ |
902 | /* put the rate scaling data there */ | 906 | /* put the rate scaling data there */ |
903 | info = IEEE80211_SKB_CB(skb); | ||
904 | memset(&info->status, 0, sizeof(info->status)); | ||
905 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
906 | info->flags |= IEEE80211_TX_STAT_AMPDU; | 907 | info->flags |= IEEE80211_TX_STAT_AMPDU; |
907 | info->status.ampdu_ack_len = ba_notif->txed_2_done; | 908 | info->status.ampdu_ack_len = ba_notif->txed_2_done; |
908 | info->status.ampdu_len = ba_notif->txed; | 909 | info->status.ampdu_len = ba_notif->txed; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a4a5e25623c3..86989df69356 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -411,6 +411,8 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
411 | mvm->status, table.valid); | 411 | mvm->status, table.valid); |
412 | } | 412 | } |
413 | 413 | ||
414 | IWL_ERR(mvm, "Loaded firmware version: %s\n", mvm->fw->fw_version); | ||
415 | |||
414 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, | 416 | trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low, |
415 | table.data1, table.data2, table.data3, | 417 | table.data1, table.data2, table.data3, |
416 | table.blink1, table.blink2, table.ilink1, | 418 | table.blink1, table.blink2, table.ilink1, |