diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm')
26 files changed, 1181 insertions, 760 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index b8ee3121fbd2..5c21231e195d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -71,6 +71,9 @@ | |||
71 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) | 71 | #define IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT (100 * USEC_PER_MSEC) |
72 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | 72 | #define IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT (10 * USEC_PER_MSEC) |
73 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) | 73 | #define IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT (10 * USEC_PER_MSEC) |
74 | #define IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT (2 * 1024) /* defined in TU */ | ||
75 | #define IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT (40 * 1024) /* defined in TU */ | ||
76 | #define IWL_MVM_P2P_LOWLATENCY_PS_ENABLE 0 | ||
74 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 77 | #define IWL_MVM_UAPSD_RX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
75 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) | 78 | #define IWL_MVM_UAPSD_TX_DATA_TIMEOUT (50 * USEC_PER_MSEC) |
76 | #define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ | 79 | #define IWL_MVM_UAPSD_QUEUES (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO |\ |
@@ -101,7 +104,7 @@ | |||
101 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 | 104 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 |
102 | #define IWL_MVM_QUOTA_THRESHOLD 4 | 105 | #define IWL_MVM_QUOTA_THRESHOLD 4 |
103 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 | 106 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 |
104 | #define IWL_MVM_RS_DISABLE_P2P_MIMO 0 | 107 | #define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1 |
105 | #define IWL_MVM_TOF_IS_RESPONDER 0 | 108 | #define IWL_MVM_TOF_IS_RESPONDER 0 |
106 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 | 109 | #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 |
107 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 | 110 | #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index 04264e417c1c..85ae902df7c0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -274,18 +274,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
274 | break; | 274 | break; |
275 | case WLAN_CIPHER_SUITE_CCMP: | 275 | case WLAN_CIPHER_SUITE_CCMP: |
276 | if (sta) { | 276 | if (sta) { |
277 | u8 *pn = seq.ccmp.pn; | 277 | u64 pn64; |
278 | 278 | ||
279 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; | 279 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.unicast_rsc; |
280 | aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; | 280 | aes_tx_sc = &data->rsc_tsc->all_tsc_rsc.aes.tsc; |
281 | 281 | ||
282 | ieee80211_get_key_tx_seq(key, &seq); | 282 | pn64 = atomic64_read(&key->tx_pn); |
283 | aes_tx_sc->pn = cpu_to_le64((u64)pn[5] | | 283 | aes_tx_sc->pn = cpu_to_le64(pn64); |
284 | ((u64)pn[4] << 8) | | ||
285 | ((u64)pn[3] << 16) | | ||
286 | ((u64)pn[2] << 24) | | ||
287 | ((u64)pn[1] << 32) | | ||
288 | ((u64)pn[0] << 40)); | ||
289 | } else { | 284 | } else { |
290 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; | 285 | aes_sc = data->rsc_tsc->all_tsc_rsc.aes.multicast_rsc; |
291 | } | 286 | } |
@@ -298,12 +293,12 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
298 | u8 *pn = seq.ccmp.pn; | 293 | u8 *pn = seq.ccmp.pn; |
299 | 294 | ||
300 | ieee80211_get_key_rx_seq(key, i, &seq); | 295 | ieee80211_get_key_rx_seq(key, i, &seq); |
301 | aes_sc->pn = cpu_to_le64((u64)pn[5] | | 296 | aes_sc[i].pn = cpu_to_le64((u64)pn[5] | |
302 | ((u64)pn[4] << 8) | | 297 | ((u64)pn[4] << 8) | |
303 | ((u64)pn[3] << 16) | | 298 | ((u64)pn[3] << 16) | |
304 | ((u64)pn[2] << 24) | | 299 | ((u64)pn[2] << 24) | |
305 | ((u64)pn[1] << 32) | | 300 | ((u64)pn[1] << 32) | |
306 | ((u64)pn[0] << 40)); | 301 | ((u64)pn[0] << 40)); |
307 | } | 302 | } |
308 | data->use_rsc_tsc = true; | 303 | data->use_rsc_tsc = true; |
309 | break; | 304 | break; |
@@ -1170,6 +1165,9 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
1170 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 1165 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
1171 | int ret; | 1166 | int ret; |
1172 | 1167 | ||
1168 | /* make sure the d0i3 exit work is not pending */ | ||
1169 | flush_work(&mvm->d0i3_exit_work); | ||
1170 | |||
1173 | ret = iwl_trans_suspend(mvm->trans); | 1171 | ret = iwl_trans_suspend(mvm->trans); |
1174 | if (ret) | 1172 | if (ret) |
1175 | return ret; | 1173 | return ret; |
@@ -1453,15 +1451,15 @@ static void iwl_mvm_d3_update_gtks(struct ieee80211_hw *hw, | |||
1453 | 1451 | ||
1454 | switch (key->cipher) { | 1452 | switch (key->cipher) { |
1455 | case WLAN_CIPHER_SUITE_CCMP: | 1453 | case WLAN_CIPHER_SUITE_CCMP: |
1456 | iwl_mvm_aes_sc_to_seq(&sc->aes.tsc, &seq); | ||
1457 | iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key); | 1454 | iwl_mvm_set_aes_rx_seq(sc->aes.unicast_rsc, key); |
1455 | atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn)); | ||
1458 | break; | 1456 | break; |
1459 | case WLAN_CIPHER_SUITE_TKIP: | 1457 | case WLAN_CIPHER_SUITE_TKIP: |
1460 | iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); | 1458 | iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq); |
1461 | iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); | 1459 | iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key); |
1460 | ieee80211_set_key_tx_seq(key, &seq); | ||
1462 | break; | 1461 | break; |
1463 | } | 1462 | } |
1464 | ieee80211_set_key_tx_seq(key, &seq); | ||
1465 | 1463 | ||
1466 | /* that's it for this key */ | 1464 | /* that's it for this key */ |
1467 | return; | 1465 | return; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 383a3162046c..7904b41a04c6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c | |||
@@ -511,7 +511,8 @@ static ssize_t iwl_dbgfs_tof_enable_write(struct ieee80211_vif *vif, | |||
511 | { | 511 | { |
512 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 512 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
513 | struct iwl_mvm *mvm = mvmvif->mvm; | 513 | struct iwl_mvm *mvm = mvmvif->mvm; |
514 | int value, ret = -EINVAL; | 514 | u32 value; |
515 | int ret = -EINVAL; | ||
515 | char *data; | 516 | char *data; |
516 | 517 | ||
517 | mutex_lock(&mvm->mutex); | 518 | mutex_lock(&mvm->mutex); |
@@ -599,7 +600,8 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, | |||
599 | { | 600 | { |
600 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 601 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
601 | struct iwl_mvm *mvm = mvmvif->mvm; | 602 | struct iwl_mvm *mvm = mvmvif->mvm; |
602 | int value, ret = 0; | 603 | u32 value; |
604 | int ret = 0; | ||
603 | char *data; | 605 | char *data; |
604 | 606 | ||
605 | mutex_lock(&mvm->mutex); | 607 | mutex_lock(&mvm->mutex); |
@@ -713,11 +715,30 @@ static ssize_t iwl_dbgfs_tof_responder_params_write(struct ieee80211_vif *vif, | |||
713 | goto out; | 715 | goto out; |
714 | } | 716 | } |
715 | 717 | ||
716 | data = iwl_dbgfs_is_match("ctrl_ch_position=", buf); | 718 | data = iwl_dbgfs_is_match("center_freq=", buf); |
717 | if (data) { | 719 | if (data) { |
720 | struct iwl_tof_responder_config_cmd *cmd = | ||
721 | &mvm->tof_data.responder_cfg; | ||
722 | |||
718 | ret = kstrtou32(data, 10, &value); | 723 | ret = kstrtou32(data, 10, &value); |
719 | if (ret == 0) | 724 | if (ret == 0 && value) { |
720 | mvm->tof_data.responder_cfg.ctrl_ch_position = value; | 725 | enum ieee80211_band band = (cmd->channel_num <= 14) ? |
726 | IEEE80211_BAND_2GHZ : | ||
727 | IEEE80211_BAND_5GHZ; | ||
728 | struct ieee80211_channel chn = { | ||
729 | .band = band, | ||
730 | .center_freq = ieee80211_channel_to_frequency( | ||
731 | cmd->channel_num, band), | ||
732 | }; | ||
733 | struct cfg80211_chan_def chandef = { | ||
734 | .chan = &chn, | ||
735 | .center_freq1 = | ||
736 | ieee80211_channel_to_frequency(value, | ||
737 | band), | ||
738 | }; | ||
739 | |||
740 | cmd->ctrl_ch_position = iwl_mvm_get_ctrl_pos(&chandef); | ||
741 | } | ||
721 | goto out; | 742 | goto out; |
722 | } | 743 | } |
723 | 744 | ||
@@ -822,7 +843,8 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, | |||
822 | { | 843 | { |
823 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 844 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
824 | struct iwl_mvm *mvm = mvmvif->mvm; | 845 | struct iwl_mvm *mvm = mvmvif->mvm; |
825 | int value, ret = 0; | 846 | u32 value; |
847 | int ret = 0; | ||
826 | char *data; | 848 | char *data; |
827 | 849 | ||
828 | mutex_lock(&mvm->mutex); | 850 | mutex_lock(&mvm->mutex); |
@@ -892,6 +914,7 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, | |||
892 | goto out; | 914 | goto out; |
893 | } | 915 | } |
894 | memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN); | 916 | memcpy(mvm->tof_data.range_req.macaddr_template, mac, ETH_ALEN); |
917 | goto out; | ||
895 | } | 918 | } |
896 | 919 | ||
897 | data = iwl_dbgfs_is_match("macaddr_mask=", buf); | 920 | data = iwl_dbgfs_is_match("macaddr_mask=", buf); |
@@ -903,21 +926,22 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, | |||
903 | goto out; | 926 | goto out; |
904 | } | 927 | } |
905 | memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN); | 928 | memcpy(mvm->tof_data.range_req.macaddr_mask, mac, ETH_ALEN); |
929 | goto out; | ||
906 | } | 930 | } |
907 | 931 | ||
908 | data = iwl_dbgfs_is_match("ap=", buf); | 932 | data = iwl_dbgfs_is_match("ap=", buf); |
909 | if (data) { | 933 | if (data) { |
910 | struct iwl_tof_range_req_ap_entry ap; | 934 | struct iwl_tof_range_req_ap_entry ap = {}; |
911 | int size = sizeof(struct iwl_tof_range_req_ap_entry); | 935 | int size = sizeof(struct iwl_tof_range_req_ap_entry); |
912 | u16 burst_period; | 936 | u16 burst_period; |
913 | u8 *mac = ap.bssid; | 937 | u8 *mac = ap.bssid; |
914 | unsigned int i; | 938 | unsigned int i; |
915 | 939 | ||
916 | if (sscanf(data, "%u %hhd %hhx %hhx" | 940 | if (sscanf(data, "%u %hhd %hhd %hhd" |
917 | "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" | 941 | "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx" |
918 | "%hhx %hhx %hx" | 942 | "%hhd %hhd %hd" |
919 | "%hhx %hhx %x" | 943 | "%hhd %hhd %d" |
920 | "%hhx %hhx %hhx %hhx", | 944 | "%hhx %hhd %hhd %hhd", |
921 | &i, &ap.channel_num, &ap.bandwidth, | 945 | &i, &ap.channel_num, &ap.bandwidth, |
922 | &ap.ctrl_ch_position, | 946 | &ap.ctrl_ch_position, |
923 | mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, | 947 | mac, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5, |
@@ -944,12 +968,12 @@ static ssize_t iwl_dbgfs_tof_range_request_write(struct ieee80211_vif *vif, | |||
944 | data = iwl_dbgfs_is_match("send_range_request=", buf); | 968 | data = iwl_dbgfs_is_match("send_range_request=", buf); |
945 | if (data) { | 969 | if (data) { |
946 | ret = kstrtou32(data, 10, &value); | 970 | ret = kstrtou32(data, 10, &value); |
947 | if (ret == 0 && value) { | 971 | if (ret == 0 && value) |
948 | ret = iwl_mvm_tof_range_request_cmd(mvm, vif); | 972 | ret = iwl_mvm_tof_range_request_cmd(mvm, vif); |
949 | goto out; | 973 | goto out; |
950 | } | ||
951 | } | 974 | } |
952 | 975 | ||
976 | ret = -EINVAL; | ||
953 | out: | 977 | out: |
954 | mutex_unlock(&mvm->mutex); | 978 | mutex_unlock(&mvm->mutex); |
955 | return ret ?: count; | 979 | return ret ?: count; |
@@ -994,16 +1018,18 @@ static ssize_t iwl_dbgfs_tof_range_request_read(struct file *file, | |||
994 | struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i]; | 1018 | struct iwl_tof_range_req_ap_entry *ap = &cmd->ap[i]; |
995 | 1019 | ||
996 | pos += scnprintf(buf + pos, bufsz - pos, | 1020 | pos += scnprintf(buf + pos, bufsz - pos, |
997 | "ap %.2d: channel_num=%hhx bw=%hhx" | 1021 | "ap %.2d: channel_num=%hhd bw=%hhd" |
998 | " control=%hhx bssid=%pM type=%hhx" | 1022 | " control=%hhd bssid=%pM type=%hhd" |
999 | " num_of_bursts=%hhx burst_period=%hx ftm=%hhx" | 1023 | " num_of_bursts=%hhd burst_period=%hd ftm=%hhd" |
1000 | " retries=%hhx tsf_delta=%x location_req=%hhx " | 1024 | " retries=%hhd tsf_delta=%d" |
1001 | " asap=%hhx enable=%hhx rssi=%hhx\n", | 1025 | " tsf_delta_direction=%hhd location_req=0x%hhx " |
1026 | " asap=%hhd enable=%hhd rssi=%hhd\n", | ||
1002 | i, ap->channel_num, ap->bandwidth, | 1027 | i, ap->channel_num, ap->bandwidth, |
1003 | ap->ctrl_ch_position, ap->bssid, | 1028 | ap->ctrl_ch_position, ap->bssid, |
1004 | ap->measure_type, ap->num_of_bursts, | 1029 | ap->measure_type, ap->num_of_bursts, |
1005 | ap->burst_period, ap->samples_per_burst, | 1030 | ap->burst_period, ap->samples_per_burst, |
1006 | ap->retries_per_sample, ap->tsf_delta, | 1031 | ap->retries_per_sample, ap->tsf_delta, |
1032 | ap->tsf_delta_direction, | ||
1007 | ap->location_req, ap->asap_mode, | 1033 | ap->location_req, ap->asap_mode, |
1008 | ap->enable_dyn_ack, ap->rssi); | 1034 | ap->enable_dyn_ack, ap->rssi); |
1009 | } | 1035 | } |
@@ -1019,7 +1045,8 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, | |||
1019 | { | 1045 | { |
1020 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1046 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
1021 | struct iwl_mvm *mvm = mvmvif->mvm; | 1047 | struct iwl_mvm *mvm = mvmvif->mvm; |
1022 | int value, ret = 0; | 1048 | u32 value; |
1049 | int ret = 0; | ||
1023 | char *data; | 1050 | char *data; |
1024 | 1051 | ||
1025 | mutex_lock(&mvm->mutex); | 1052 | mutex_lock(&mvm->mutex); |
@@ -1071,12 +1098,12 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_write(struct ieee80211_vif *vif, | |||
1071 | data = iwl_dbgfs_is_match("send_range_req_ext=", buf); | 1098 | data = iwl_dbgfs_is_match("send_range_req_ext=", buf); |
1072 | if (data) { | 1099 | if (data) { |
1073 | ret = kstrtou32(data, 10, &value); | 1100 | ret = kstrtou32(data, 10, &value); |
1074 | if (ret == 0 && value) { | 1101 | if (ret == 0 && value) |
1075 | ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif); | 1102 | ret = iwl_mvm_tof_range_request_ext_cmd(mvm, vif); |
1076 | goto out; | 1103 | goto out; |
1077 | } | ||
1078 | } | 1104 | } |
1079 | 1105 | ||
1106 | ret = -EINVAL; | ||
1080 | out: | 1107 | out: |
1081 | mutex_unlock(&mvm->mutex); | 1108 | mutex_unlock(&mvm->mutex); |
1082 | return ret ?: count; | 1109 | return ret ?: count; |
@@ -1099,18 +1126,18 @@ static ssize_t iwl_dbgfs_tof_range_req_ext_read(struct file *file, | |||
1099 | mutex_lock(&mvm->mutex); | 1126 | mutex_lock(&mvm->mutex); |
1100 | 1127 | ||
1101 | pos += scnprintf(buf + pos, bufsz - pos, | 1128 | pos += scnprintf(buf + pos, bufsz - pos, |
1102 | "tsf_timer_offset_msec = %hx\n", | 1129 | "tsf_timer_offset_msec = %hd\n", |
1103 | cmd->tsf_timer_offset_msec); | 1130 | cmd->tsf_timer_offset_msec); |
1104 | pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhx\n", | 1131 | pos += scnprintf(buf + pos, bufsz - pos, "min_delta_ftm = %hhd\n", |
1105 | cmd->min_delta_ftm); | 1132 | cmd->min_delta_ftm); |
1106 | pos += scnprintf(buf + pos, bufsz - pos, | 1133 | pos += scnprintf(buf + pos, bufsz - pos, |
1107 | "ftm_format_and_bw20M = %hhx\n", | 1134 | "ftm_format_and_bw20M = %hhd\n", |
1108 | cmd->ftm_format_and_bw20M); | 1135 | cmd->ftm_format_and_bw20M); |
1109 | pos += scnprintf(buf + pos, bufsz - pos, | 1136 | pos += scnprintf(buf + pos, bufsz - pos, |
1110 | "ftm_format_and_bw40M = %hhx\n", | 1137 | "ftm_format_and_bw40M = %hhd\n", |
1111 | cmd->ftm_format_and_bw40M); | 1138 | cmd->ftm_format_and_bw40M); |
1112 | pos += scnprintf(buf + pos, bufsz - pos, | 1139 | pos += scnprintf(buf + pos, bufsz - pos, |
1113 | "ftm_format_and_bw80M = %hhx\n", | 1140 | "ftm_format_and_bw80M = %hhd\n", |
1114 | cmd->ftm_format_and_bw80M); | 1141 | cmd->ftm_format_and_bw80M); |
1115 | 1142 | ||
1116 | mutex_unlock(&mvm->mutex); | 1143 | mutex_unlock(&mvm->mutex); |
@@ -1123,8 +1150,8 @@ static ssize_t iwl_dbgfs_tof_range_abort_write(struct ieee80211_vif *vif, | |||
1123 | { | 1150 | { |
1124 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1151 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
1125 | struct iwl_mvm *mvm = mvmvif->mvm; | 1152 | struct iwl_mvm *mvm = mvmvif->mvm; |
1126 | int value, ret = 0; | 1153 | u32 value; |
1127 | int abort_id; | 1154 | int abort_id, ret = 0; |
1128 | char *data; | 1155 | char *data; |
1129 | 1156 | ||
1130 | mutex_lock(&mvm->mutex); | 1157 | mutex_lock(&mvm->mutex); |
@@ -1205,11 +1232,11 @@ static ssize_t iwl_dbgfs_tof_range_response_read(struct file *file, | |||
1205 | struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i]; | 1232 | struct iwl_tof_range_rsp_ap_entry_ntfy *ap = &cmd->ap[i]; |
1206 | 1233 | ||
1207 | pos += scnprintf(buf + pos, bufsz - pos, | 1234 | pos += scnprintf(buf + pos, bufsz - pos, |
1208 | "ap %.2d: bssid=%pM status=%hhx bw=%hhx" | 1235 | "ap %.2d: bssid=%pM status=%hhd bw=%hhd" |
1209 | " rtt=%x rtt_var=%x rtt_spread=%x" | 1236 | " rtt=%d rtt_var=%d rtt_spread=%d" |
1210 | " rssi=%hhx rssi_spread=%hhx" | 1237 | " rssi=%hhd rssi_spread=%hhd" |
1211 | " range=%x range_var=%x" | 1238 | " range=%d range_var=%d" |
1212 | " time_stamp=%x\n", | 1239 | " time_stamp=%d\n", |
1213 | i, ap->bssid, ap->measure_status, | 1240 | i, ap->bssid, ap->measure_status, |
1214 | ap->measure_bw, | 1241 | ap->measure_bw, |
1215 | ap->rtt, ap->rtt_variance, ap->rtt_spread, | 1242 | ap->rtt, ap->rtt_variance, ap->rtt_spread, |
@@ -1250,11 +1277,10 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, | |||
1250 | { | 1277 | { |
1251 | struct ieee80211_vif *vif = file->private_data; | 1278 | struct ieee80211_vif *vif = file->private_data; |
1252 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 1279 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
1253 | char buf[3]; | 1280 | char buf[2]; |
1254 | 1281 | ||
1255 | buf[0] = mvmvif->low_latency ? '1' : '0'; | 1282 | buf[0] = mvmvif->low_latency ? '1' : '0'; |
1256 | buf[1] = '\n'; | 1283 | buf[1] = '\n'; |
1257 | buf[2] = '\0'; | ||
1258 | return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); | 1284 | return simple_read_from_buffer(user_buf, count, ppos, buf, sizeof(buf)); |
1259 | } | 1285 | } |
1260 | 1286 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 7d69a556bcc8..05928fb4021d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -85,7 +85,7 @@ static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf, | |||
85 | IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk); | 85 | IWL_ERR(mvm, "FLUSHING queues: scd_q_msk = 0x%x\n", scd_q_msk); |
86 | 86 | ||
87 | mutex_lock(&mvm->mutex); | 87 | mutex_lock(&mvm->mutex); |
88 | ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, true) ? : count; | 88 | ret = iwl_mvm_flush_tx_path(mvm, scd_q_msk, 0) ? : count; |
89 | mutex_unlock(&mvm->mutex); | 89 | mutex_unlock(&mvm->mutex); |
90 | 90 | ||
91 | return ret; | 91 | return ret; |
@@ -1214,118 +1214,6 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, | |||
1214 | 1214 | ||
1215 | return ret; | 1215 | return ret; |
1216 | } | 1216 | } |
1217 | |||
1218 | #define MAX_NUM_ND_MATCHSETS 10 | ||
1219 | |||
1220 | static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf, | ||
1221 | size_t count, loff_t *ppos) | ||
1222 | { | ||
1223 | const char *seps = ",\n"; | ||
1224 | char *buf_ptr = buf; | ||
1225 | char *value_str = NULL; | ||
1226 | int ret, i; | ||
1227 | |||
1228 | /* TODO: don't free if write is being called several times in one go */ | ||
1229 | if (mvm->nd_config) { | ||
1230 | kfree(mvm->nd_config->match_sets); | ||
1231 | kfree(mvm->nd_config); | ||
1232 | mvm->nd_config = NULL; | ||
1233 | } | ||
1234 | |||
1235 | mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) + | ||
1236 | (11 * sizeof(struct ieee80211_channel *)), | ||
1237 | GFP_KERNEL); | ||
1238 | if (!mvm->nd_config) { | ||
1239 | ret = -ENOMEM; | ||
1240 | goto out_free; | ||
1241 | } | ||
1242 | |||
1243 | mvm->nd_config->n_channels = 11; | ||
1244 | mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20; | ||
1245 | mvm->nd_config->interval = 5; | ||
1246 | mvm->nd_config->min_rssi_thold = -80; | ||
1247 | for (i = 0; i < mvm->nd_config->n_channels; i++) | ||
1248 | mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i]; | ||
1249 | |||
1250 | mvm->nd_config->match_sets = | ||
1251 | kcalloc(MAX_NUM_ND_MATCHSETS, | ||
1252 | sizeof(*mvm->nd_config->match_sets), | ||
1253 | GFP_KERNEL); | ||
1254 | if (!mvm->nd_config->match_sets) { | ||
1255 | ret = -ENOMEM; | ||
1256 | goto out_free; | ||
1257 | } | ||
1258 | |||
1259 | while ((value_str = strsep(&buf_ptr, seps)) && | ||
1260 | strlen(value_str)) { | ||
1261 | struct cfg80211_match_set *set; | ||
1262 | |||
1263 | if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) { | ||
1264 | ret = -EINVAL; | ||
1265 | goto out_free; | ||
1266 | } | ||
1267 | |||
1268 | set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets]; | ||
1269 | set->ssid.ssid_len = strlen(value_str); | ||
1270 | |||
1271 | if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) { | ||
1272 | ret = -EINVAL; | ||
1273 | goto out_free; | ||
1274 | } | ||
1275 | |||
1276 | memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len); | ||
1277 | |||
1278 | mvm->nd_config->n_match_sets++; | ||
1279 | } | ||
1280 | |||
1281 | ret = count; | ||
1282 | |||
1283 | if (mvm->nd_config->n_match_sets) | ||
1284 | goto out; | ||
1285 | |||
1286 | out_free: | ||
1287 | if (mvm->nd_config) | ||
1288 | kfree(mvm->nd_config->match_sets); | ||
1289 | kfree(mvm->nd_config); | ||
1290 | mvm->nd_config = NULL; | ||
1291 | out: | ||
1292 | return ret; | ||
1293 | } | ||
1294 | |||
1295 | static ssize_t | ||
1296 | iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf, | ||
1297 | size_t count, loff_t *ppos) | ||
1298 | { | ||
1299 | struct iwl_mvm *mvm = file->private_data; | ||
1300 | size_t bufsz, ret; | ||
1301 | char *buf; | ||
1302 | int i, n_match_sets, pos = 0; | ||
1303 | |||
1304 | n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0; | ||
1305 | |||
1306 | bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1; | ||
1307 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1308 | if (!buf) | ||
1309 | return -ENOMEM; | ||
1310 | |||
1311 | for (i = 0; i < n_match_sets; i++) { | ||
1312 | if (pos + | ||
1313 | mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) { | ||
1314 | ret = -EIO; | ||
1315 | goto out; | ||
1316 | } | ||
1317 | |||
1318 | memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid, | ||
1319 | mvm->nd_config->match_sets[i].ssid.ssid_len); | ||
1320 | pos += mvm->nd_config->match_sets[i].ssid.ssid_len; | ||
1321 | buf[pos++] = '\n'; | ||
1322 | } | ||
1323 | |||
1324 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1325 | out: | ||
1326 | kfree(buf); | ||
1327 | return ret; | ||
1328 | } | ||
1329 | #endif | 1217 | #endif |
1330 | 1218 | ||
1331 | #define PRINT_MVM_REF(ref) do { \ | 1219 | #define PRINT_MVM_REF(ref) do { \ |
@@ -1473,11 +1361,25 @@ out: | |||
1473 | return count; | 1361 | return count; |
1474 | } | 1362 | } |
1475 | 1363 | ||
1364 | static ssize_t | ||
1365 | iwl_dbgfs_send_echo_cmd_write(struct iwl_mvm *mvm, char *buf, | ||
1366 | size_t count, loff_t *ppos) | ||
1367 | { | ||
1368 | int ret; | ||
1369 | |||
1370 | mutex_lock(&mvm->mutex); | ||
1371 | ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); | ||
1372 | mutex_unlock(&mvm->mutex); | ||
1373 | |||
1374 | return ret ?: count; | ||
1375 | } | ||
1376 | |||
1476 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); | 1377 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(prph_reg, 64); |
1477 | 1378 | ||
1478 | /* Device wide debugfs entries */ | 1379 | /* Device wide debugfs entries */ |
1479 | MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); | 1380 | MVM_DEBUGFS_WRITE_FILE_OPS(tx_flush, 16); |
1480 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); | 1381 | MVM_DEBUGFS_WRITE_FILE_OPS(sta_drain, 8); |
1382 | MVM_DEBUGFS_WRITE_FILE_OPS(send_echo_cmd, 8); | ||
1481 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); | 1383 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(sram, 64); |
1482 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); | 1384 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(set_nic_temperature, 64); |
1483 | MVM_DEBUGFS_READ_FILE_OPS(nic_temp); | 1385 | MVM_DEBUGFS_READ_FILE_OPS(nic_temp); |
@@ -1503,7 +1405,6 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); | |||
1503 | 1405 | ||
1504 | #ifdef CONFIG_PM_SLEEP | 1406 | #ifdef CONFIG_PM_SLEEP |
1505 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); | 1407 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); |
1506 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384); | ||
1507 | #endif | 1408 | #endif |
1508 | 1409 | ||
1509 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | 1410 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) |
@@ -1538,6 +1439,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1538 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1439 | MVM_DEBUGFS_ADD_FILE(d0i3_refs, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
1539 | MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | 1440 | MVM_DEBUGFS_ADD_FILE(fw_dbg_conf, mvm->debugfs_dir, S_IRUSR | S_IWUSR); |
1540 | MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); | 1441 | MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); |
1442 | MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); | ||
1541 | if (!debugfs_create_bool("enable_scan_iteration_notif", | 1443 | if (!debugfs_create_bool("enable_scan_iteration_notif", |
1542 | S_IRUSR | S_IWUSR, | 1444 | S_IRUSR | S_IWUSR, |
1543 | mvm->debugfs_dir, | 1445 | mvm->debugfs_dir, |
@@ -1572,7 +1474,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1572 | if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR, | 1474 | if (!debugfs_create_u32("last_netdetect_scans", S_IRUSR, |
1573 | mvm->debugfs_dir, &mvm->last_netdetect_scans)) | 1475 | mvm->debugfs_dir, &mvm->last_netdetect_scans)) |
1574 | goto err; | 1476 | goto err; |
1575 | MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | ||
1576 | #endif | 1477 | #endif |
1577 | 1478 | ||
1578 | if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, | 1479 | if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, |
@@ -1594,6 +1495,9 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1594 | if (!debugfs_create_blob("nvm_prod", S_IRUSR, | 1495 | if (!debugfs_create_blob("nvm_prod", S_IRUSR, |
1595 | mvm->debugfs_dir, &mvm->nvm_prod_blob)) | 1496 | mvm->debugfs_dir, &mvm->nvm_prod_blob)) |
1596 | goto err; | 1497 | goto err; |
1498 | if (!debugfs_create_blob("nvm_phy_sku", S_IRUSR, | ||
1499 | mvm->debugfs_dir, &mvm->nvm_phy_sku_blob)) | ||
1500 | goto err; | ||
1597 | 1501 | ||
1598 | /* | 1502 | /* |
1599 | * Create a symlink with mac80211. It will be removed when mac80211 | 1503 | * Create a symlink with mac80211. It will be removed when mac80211 |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h index 7005fa4be74a..c8f3e2536cbb 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h | |||
@@ -192,16 +192,10 @@ struct iwl_powertable_cmd { | |||
192 | /** | 192 | /** |
193 | * enum iwl_device_power_flags - masks for device power command flags | 193 | * enum iwl_device_power_flags - masks for device power command flags |
194 | * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off | 194 | * @DEVIC_POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off |
195 | * receiver and transmitter. '0' - does not allow. This flag should be | 195 | * receiver and transmitter. '0' - does not allow. |
196 | * always set to '1' unless one need to disable actual power down for debug | ||
197 | * purposes. | ||
198 | * @DEVICE_POWER_FLAGS_CAM_MSK: '1' CAM (Continuous Active Mode) is set, meaning | ||
199 | * that power management is disabled. '0' Power management is enabled, one | ||
200 | * of power schemes is applied. | ||
201 | */ | 196 | */ |
202 | enum iwl_device_power_flags { | 197 | enum iwl_device_power_flags { |
203 | DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), | 198 | DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK = BIT(0), |
204 | DEVICE_POWER_FLAGS_CAM_MSK = BIT(13), | ||
205 | }; | 199 | }; |
206 | 200 | ||
207 | /** | 201 | /** |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h new file mode 100644 index 000000000000..9b7e49d4620f --- /dev/null +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-rx.h | |||
@@ -0,0 +1,238 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | ||
9 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | ||
10 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of version 2 of the GNU General Public License as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
24 | * USA | ||
25 | * | ||
26 | * The full GNU General Public License is included in this distribution | ||
27 | * in the file called COPYING. | ||
28 | * | ||
29 | * Contact Information: | ||
30 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
31 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
32 | * | ||
33 | * BSD LICENSE | ||
34 | * | ||
35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | ||
36 | * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH | ||
37 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
38 | * All rights reserved. | ||
39 | * | ||
40 | * Redistribution and use in source and binary forms, with or without | ||
41 | * modification, are permitted provided that the following conditions | ||
42 | * are met: | ||
43 | * | ||
44 | * * Redistributions of source code must retain the above copyright | ||
45 | * notice, this list of conditions and the following disclaimer. | ||
46 | * * Redistributions in binary form must reproduce the above copyright | ||
47 | * notice, this list of conditions and the following disclaimer in | ||
48 | * the documentation and/or other materials provided with the | ||
49 | * distribution. | ||
50 | * * Neither the name Intel Corporation nor the names of its | ||
51 | * contributors may be used to endorse or promote products derived | ||
52 | * from this software without specific prior written permission. | ||
53 | * | ||
54 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
55 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
56 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
57 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
58 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
59 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
60 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
61 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
62 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
63 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
64 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
65 | * | ||
66 | *****************************************************************************/ | ||
67 | |||
68 | #ifndef __fw_api_rx_h__ | ||
69 | #define __fw_api_rx_h__ | ||
70 | |||
71 | #define IWL_RX_INFO_PHY_CNT 8 | ||
72 | #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 | ||
73 | #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff | ||
74 | #define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 | ||
75 | #define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 | ||
76 | #define IWL_RX_INFO_ENERGY_ANT_A_POS 0 | ||
77 | #define IWL_RX_INFO_ENERGY_ANT_B_POS 8 | ||
78 | #define IWL_RX_INFO_ENERGY_ANT_C_POS 16 | ||
79 | |||
80 | /** | ||
81 | * struct iwl_rx_phy_info - phy info | ||
82 | * (REPLY_RX_PHY_CMD = 0xc0) | ||
83 | * @non_cfg_phy_cnt: non configurable DSP phy data byte count | ||
84 | * @cfg_phy_cnt: configurable DSP phy data byte count | ||
85 | * @stat_id: configurable DSP phy data set ID | ||
86 | * @reserved1: | ||
87 | * @system_timestamp: GP2 at on air rise | ||
88 | * @timestamp: TSF at on air rise | ||
89 | * @beacon_time_stamp: beacon at on-air rise | ||
90 | * @phy_flags: general phy flags: band, modulation, ... | ||
91 | * @channel: channel number | ||
92 | * @non_cfg_phy_buf: for various implementations of non_cfg_phy | ||
93 | * @rate_n_flags: RATE_MCS_* | ||
94 | * @byte_count: frame's byte-count | ||
95 | * @frame_time: frame's time on the air, based on byte count and frame rate | ||
96 | * calculation | ||
97 | * @mac_active_msk: what MACs were active when the frame was received | ||
98 | * | ||
99 | * Before each Rx, the device sends this data. It contains PHY information | ||
100 | * about the reception of the packet. | ||
101 | */ | ||
102 | struct iwl_rx_phy_info { | ||
103 | u8 non_cfg_phy_cnt; | ||
104 | u8 cfg_phy_cnt; | ||
105 | u8 stat_id; | ||
106 | u8 reserved1; | ||
107 | __le32 system_timestamp; | ||
108 | __le64 timestamp; | ||
109 | __le32 beacon_time_stamp; | ||
110 | __le16 phy_flags; | ||
111 | __le16 channel; | ||
112 | __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; | ||
113 | __le32 rate_n_flags; | ||
114 | __le32 byte_count; | ||
115 | __le16 mac_active_msk; | ||
116 | __le16 frame_time; | ||
117 | } __packed; | ||
118 | |||
119 | /* | ||
120 | * TCP offload Rx assist info | ||
121 | * | ||
122 | * bits 0:3 - reserved | ||
123 | * bits 4:7 - MIC CRC length | ||
124 | * bits 8:12 - MAC header length | ||
125 | * bit 13 - Padding indication | ||
126 | * bit 14 - A-AMSDU indication | ||
127 | * bit 15 - Offload enabled | ||
128 | */ | ||
129 | enum iwl_csum_rx_assist_info { | ||
130 | CSUM_RXA_RESERVED_MASK = 0x000f, | ||
131 | CSUM_RXA_MICSIZE_MASK = 0x00f0, | ||
132 | CSUM_RXA_HEADERLEN_MASK = 0x1f00, | ||
133 | CSUM_RXA_PADD = BIT(13), | ||
134 | CSUM_RXA_AMSDU = BIT(14), | ||
135 | CSUM_RXA_ENA = BIT(15) | ||
136 | }; | ||
137 | |||
138 | /** | ||
139 | * struct iwl_rx_mpdu_res_start - phy info | ||
140 | * @assist: see CSUM_RX_ASSIST_ above | ||
141 | */ | ||
142 | struct iwl_rx_mpdu_res_start { | ||
143 | __le16 byte_count; | ||
144 | __le16 assist; | ||
145 | } __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */ | ||
146 | |||
147 | /** | ||
148 | * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags | ||
149 | * @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band | ||
150 | * @RX_RES_PHY_FLAGS_MOD_CCK: | ||
151 | * @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short | ||
152 | * @RX_RES_PHY_FLAGS_NARROW_BAND: | ||
153 | * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received | ||
154 | * @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU | ||
155 | * @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame | ||
156 | * @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble | ||
157 | * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame | ||
158 | */ | ||
159 | enum iwl_rx_phy_flags { | ||
160 | RX_RES_PHY_FLAGS_BAND_24 = BIT(0), | ||
161 | RX_RES_PHY_FLAGS_MOD_CCK = BIT(1), | ||
162 | RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2), | ||
163 | RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3), | ||
164 | RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4), | ||
165 | RX_RES_PHY_FLAGS_ANTENNA_POS = 4, | ||
166 | RX_RES_PHY_FLAGS_AGG = BIT(7), | ||
167 | RX_RES_PHY_FLAGS_OFDM_HT = BIT(8), | ||
168 | RX_RES_PHY_FLAGS_OFDM_GF = BIT(9), | ||
169 | RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10), | ||
170 | }; | ||
171 | |||
172 | /** | ||
173 | * enum iwl_mvm_rx_status - written by fw for each Rx packet | ||
174 | * @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine | ||
175 | * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow | ||
176 | * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: | ||
177 | * @RX_MPDU_RES_STATUS_KEY_VALID: | ||
178 | * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: | ||
179 | * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed | ||
180 | * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked | ||
181 | * in the driver. | ||
182 | * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine | ||
183 | * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or | ||
184 | * alg = CCM only. Checks replay attack for 11w frames. Relevant only if | ||
185 | * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. | ||
186 | * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted | ||
187 | * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP | ||
188 | * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM | ||
189 | * @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP | ||
190 | * @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC | ||
191 | * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted | ||
192 | * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm | ||
193 | * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted | ||
194 | * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP: | ||
195 | * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: | ||
196 | * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: | ||
197 | * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame | ||
198 | * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw | ||
199 | * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors | ||
200 | * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK: | ||
201 | * @RX_MPDU_RES_STATUS_STA_ID_MSK: | ||
202 | * @RX_MPDU_RES_STATUS_RRF_KILL: | ||
203 | * @RX_MPDU_RES_STATUS_FILTERING_MSK: | ||
204 | * @RX_MPDU_RES_STATUS2_FILTERING_MSK: | ||
205 | */ | ||
206 | enum iwl_mvm_rx_status { | ||
207 | RX_MPDU_RES_STATUS_CRC_OK = BIT(0), | ||
208 | RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), | ||
209 | RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), | ||
210 | RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), | ||
211 | RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), | ||
212 | RX_MPDU_RES_STATUS_ICV_OK = BIT(5), | ||
213 | RX_MPDU_RES_STATUS_MIC_OK = BIT(6), | ||
214 | RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), | ||
215 | RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7), | ||
216 | RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8), | ||
217 | RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), | ||
218 | RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), | ||
219 | RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), | ||
220 | RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), | ||
221 | RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), | ||
222 | RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), | ||
223 | RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), | ||
224 | RX_MPDU_RES_STATUS_DEC_DONE = BIT(11), | ||
225 | RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12), | ||
226 | RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13), | ||
227 | RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14), | ||
228 | RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15), | ||
229 | RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16), | ||
230 | RX_MPDU_RES_STATUS_CSUM_OK = BIT(17), | ||
231 | RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000), | ||
232 | RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), | ||
233 | RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), | ||
234 | RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), | ||
235 | RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), | ||
236 | }; | ||
237 | |||
238 | #endif /* __fw_api_rx_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h index 660cc1c93e19..3a657e4b60ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h | |||
@@ -101,6 +101,7 @@ struct iwl_ssid_ie { | |||
101 | 101 | ||
102 | #define IWL_FULL_SCAN_MULTIPLIER 5 | 102 | #define IWL_FULL_SCAN_MULTIPLIER 5 |
103 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 | 103 | #define IWL_FAST_SCHED_SCAN_ITERATIONS 3 |
104 | #define IWL_MAX_SCHED_SCAN_PLANS 2 | ||
104 | 105 | ||
105 | enum scan_framework_client { | 106 | enum scan_framework_client { |
106 | SCAN_CLIENT_SCHED_SCAN = BIT(0), | 107 | SCAN_CLIENT_SCHED_SCAN = BIT(0), |
@@ -359,7 +360,7 @@ struct iwl_scan_req_lmac { | |||
359 | /* SCAN_REQ_PERIODIC_PARAMS_API_S */ | 360 | /* SCAN_REQ_PERIODIC_PARAMS_API_S */ |
360 | __le32 iter_num; | 361 | __le32 iter_num; |
361 | __le32 delay; | 362 | __le32 delay; |
362 | struct iwl_scan_schedule_lmac schedule[2]; | 363 | struct iwl_scan_schedule_lmac schedule[IWL_MAX_SCHED_SCAN_PLANS]; |
363 | struct iwl_scan_channel_opt channel_opt[2]; | 364 | struct iwl_scan_channel_opt channel_opt[2]; |
364 | u8 data[]; | 365 | u8 data[]; |
365 | } __packed; | 366 | } __packed; |
@@ -582,7 +583,7 @@ struct iwl_scan_umac_schedule { | |||
582 | */ | 583 | */ |
583 | struct iwl_scan_req_umac_tail { | 584 | struct iwl_scan_req_umac_tail { |
584 | /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ | 585 | /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ |
585 | struct iwl_scan_umac_schedule schedule[2]; | 586 | struct iwl_scan_umac_schedule schedule[IWL_MAX_SCHED_SCAN_PLANS]; |
586 | __le16 delay; | 587 | __le16 delay; |
587 | __le16 reserved; | 588 | __le16 reserved; |
588 | /* SCAN_PROBE_PARAMS_API_S_VER_1 */ | 589 | /* SCAN_PROBE_PARAMS_API_S_VER_1 */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h index 709e28d8b1b0..0c321f63ee42 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-stats.h | |||
@@ -219,32 +219,6 @@ struct mvm_statistics_bt_activity { | |||
219 | __le32 lo_priority_rx_denied_cnt; | 219 | __le32 lo_priority_rx_denied_cnt; |
220 | } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ | 220 | } __packed; /* STATISTICS_BT_ACTIVITY_API_S_VER_1 */ |
221 | 221 | ||
222 | struct mvm_statistics_general_v5 { | ||
223 | __le32 radio_temperature; | ||
224 | __le32 radio_voltage; | ||
225 | struct mvm_statistics_dbg dbg; | ||
226 | __le32 sleep_time; | ||
227 | __le32 slots_out; | ||
228 | __le32 slots_idle; | ||
229 | __le32 ttl_timestamp; | ||
230 | struct mvm_statistics_div slow_div; | ||
231 | __le32 rx_enable_counter; | ||
232 | /* | ||
233 | * num_of_sos_states: | ||
234 | * count the number of times we have to re-tune | ||
235 | * in order to get out of bad PHY status | ||
236 | */ | ||
237 | __le32 num_of_sos_states; | ||
238 | __le32 beacon_filtered; | ||
239 | __le32 missed_beacons; | ||
240 | __s8 beacon_filter_average_energy; | ||
241 | __s8 beacon_filter_reason; | ||
242 | __s8 beacon_filter_current_energy; | ||
243 | __s8 beacon_filter_reserved; | ||
244 | __le32 beacon_filter_delta_time; | ||
245 | struct mvm_statistics_bt_activity bt_activity; | ||
246 | } __packed; /* STATISTICS_GENERAL_API_S_VER_5 */ | ||
247 | |||
248 | struct mvm_statistics_general_v8 { | 222 | struct mvm_statistics_general_v8 { |
249 | __le32 radio_temperature; | 223 | __le32 radio_temperature; |
250 | __le32 radio_voltage; | 224 | __le32 radio_voltage; |
@@ -263,10 +237,10 @@ struct mvm_statistics_general_v8 { | |||
263 | __le32 num_of_sos_states; | 237 | __le32 num_of_sos_states; |
264 | __le32 beacon_filtered; | 238 | __le32 beacon_filtered; |
265 | __le32 missed_beacons; | 239 | __le32 missed_beacons; |
266 | __s8 beacon_filter_average_energy; | 240 | u8 beacon_filter_average_energy; |
267 | __s8 beacon_filter_reason; | 241 | u8 beacon_filter_reason; |
268 | __s8 beacon_filter_current_energy; | 242 | u8 beacon_filter_current_energy; |
269 | __s8 beacon_filter_reserved; | 243 | u8 beacon_filter_reserved; |
270 | __le32 beacon_filter_delta_time; | 244 | __le32 beacon_filter_delta_time; |
271 | struct mvm_statistics_bt_activity bt_activity; | 245 | struct mvm_statistics_bt_activity bt_activity; |
272 | __le64 rx_time; | 246 | __le64 rx_time; |
@@ -293,13 +267,6 @@ struct mvm_statistics_rx { | |||
293 | * STATISTICS_CMD (0x9c), below. | 267 | * STATISTICS_CMD (0x9c), below. |
294 | */ | 268 | */ |
295 | 269 | ||
296 | struct iwl_notif_statistics_v8 { | ||
297 | __le32 flag; | ||
298 | struct mvm_statistics_rx rx; | ||
299 | struct mvm_statistics_tx tx; | ||
300 | struct mvm_statistics_general_v5 general; | ||
301 | } __packed; /* STATISTICS_NTFY_API_S_VER_8 */ | ||
302 | |||
303 | struct iwl_notif_statistics_v10 { | 270 | struct iwl_notif_statistics_v10 { |
304 | __le32 flag; | 271 | __le32 flag; |
305 | struct mvm_statistics_rx rx; | 272 | struct mvm_statistics_rx rx; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 4af7513adda2..181590fbd3b3 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -67,6 +67,7 @@ | |||
67 | #define __fw_api_h__ | 67 | #define __fw_api_h__ |
68 | 68 | ||
69 | #include "fw-api-rs.h" | 69 | #include "fw-api-rs.h" |
70 | #include "fw-api-rx.h" | ||
70 | #include "fw-api-tx.h" | 71 | #include "fw-api-tx.h" |
71 | #include "fw-api-sta.h" | 72 | #include "fw-api-sta.h" |
72 | #include "fw-api-mac.h" | 73 | #include "fw-api-mac.h" |
@@ -100,6 +101,7 @@ enum iwl_mvm_tx_fifo { | |||
100 | enum { | 101 | enum { |
101 | MVM_ALIVE = 0x1, | 102 | MVM_ALIVE = 0x1, |
102 | REPLY_ERROR = 0x2, | 103 | REPLY_ERROR = 0x2, |
104 | ECHO_CMD = 0x3, | ||
103 | 105 | ||
104 | INIT_COMPLETE_NOTIF = 0x4, | 106 | INIT_COMPLETE_NOTIF = 0x4, |
105 | 107 | ||
@@ -266,6 +268,16 @@ enum { | |||
266 | REPLY_MAX = 0xff, | 268 | REPLY_MAX = 0xff, |
267 | }; | 269 | }; |
268 | 270 | ||
271 | enum iwl_phy_ops_subcmd_ids { | ||
272 | CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0, | ||
273 | DTS_MEASUREMENT_NOTIF_WIDE = 0xFF, | ||
274 | }; | ||
275 | |||
276 | /* command groups */ | ||
277 | enum { | ||
278 | PHY_OPS_GROUP = 0x4, | ||
279 | }; | ||
280 | |||
269 | /** | 281 | /** |
270 | * struct iwl_cmd_response - generic response struct for most commands | 282 | * struct iwl_cmd_response - generic response struct for most commands |
271 | * @status: status of the command asked, changes for each one | 283 | * @status: status of the command asked, changes for each one |
@@ -1070,190 +1082,6 @@ struct iwl_hs20_roc_res { | |||
1070 | __le32 status; | 1082 | __le32 status; |
1071 | } __packed; /* HOT_SPOT_RSP_API_S_VER_1 */ | 1083 | } __packed; /* HOT_SPOT_RSP_API_S_VER_1 */ |
1072 | 1084 | ||
1073 | #define IWL_RX_INFO_PHY_CNT 8 | ||
1074 | #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1 | ||
1075 | #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff | ||
1076 | #define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00 | ||
1077 | #define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000 | ||
1078 | #define IWL_RX_INFO_ENERGY_ANT_A_POS 0 | ||
1079 | #define IWL_RX_INFO_ENERGY_ANT_B_POS 8 | ||
1080 | #define IWL_RX_INFO_ENERGY_ANT_C_POS 16 | ||
1081 | |||
1082 | #define IWL_RX_INFO_AGC_IDX 1 | ||
1083 | #define IWL_RX_INFO_RSSI_AB_IDX 2 | ||
1084 | #define IWL_OFDM_AGC_A_MSK 0x0000007f | ||
1085 | #define IWL_OFDM_AGC_A_POS 0 | ||
1086 | #define IWL_OFDM_AGC_B_MSK 0x00003f80 | ||
1087 | #define IWL_OFDM_AGC_B_POS 7 | ||
1088 | #define IWL_OFDM_AGC_CODE_MSK 0x3fe00000 | ||
1089 | #define IWL_OFDM_AGC_CODE_POS 20 | ||
1090 | #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff | ||
1091 | #define IWL_OFDM_RSSI_A_POS 0 | ||
1092 | #define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 | ||
1093 | #define IWL_OFDM_RSSI_ALLBAND_A_POS 8 | ||
1094 | #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 | ||
1095 | #define IWL_OFDM_RSSI_B_POS 16 | ||
1096 | #define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 | ||
1097 | #define IWL_OFDM_RSSI_ALLBAND_B_POS 24 | ||
1098 | |||
1099 | /** | ||
1100 | * struct iwl_rx_phy_info - phy info | ||
1101 | * (REPLY_RX_PHY_CMD = 0xc0) | ||
1102 | * @non_cfg_phy_cnt: non configurable DSP phy data byte count | ||
1103 | * @cfg_phy_cnt: configurable DSP phy data byte count | ||
1104 | * @stat_id: configurable DSP phy data set ID | ||
1105 | * @reserved1: | ||
1106 | * @system_timestamp: GP2 at on air rise | ||
1107 | * @timestamp: TSF at on air rise | ||
1108 | * @beacon_time_stamp: beacon at on-air rise | ||
1109 | * @phy_flags: general phy flags: band, modulation, ... | ||
1110 | * @channel: channel number | ||
1111 | * @non_cfg_phy_buf: for various implementations of non_cfg_phy | ||
1112 | * @rate_n_flags: RATE_MCS_* | ||
1113 | * @byte_count: frame's byte-count | ||
1114 | * @frame_time: frame's time on the air, based on byte count and frame rate | ||
1115 | * calculation | ||
1116 | * @mac_active_msk: what MACs were active when the frame was received | ||
1117 | * | ||
1118 | * Before each Rx, the device sends this data. It contains PHY information | ||
1119 | * about the reception of the packet. | ||
1120 | */ | ||
1121 | struct iwl_rx_phy_info { | ||
1122 | u8 non_cfg_phy_cnt; | ||
1123 | u8 cfg_phy_cnt; | ||
1124 | u8 stat_id; | ||
1125 | u8 reserved1; | ||
1126 | __le32 system_timestamp; | ||
1127 | __le64 timestamp; | ||
1128 | __le32 beacon_time_stamp; | ||
1129 | __le16 phy_flags; | ||
1130 | __le16 channel; | ||
1131 | __le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT]; | ||
1132 | __le32 rate_n_flags; | ||
1133 | __le32 byte_count; | ||
1134 | __le16 mac_active_msk; | ||
1135 | __le16 frame_time; | ||
1136 | } __packed; | ||
1137 | |||
1138 | /* | ||
1139 | * TCP offload Rx assist info | ||
1140 | * | ||
1141 | * bits 0:3 - reserved | ||
1142 | * bits 4:7 - MIC CRC length | ||
1143 | * bits 8:12 - MAC header length | ||
1144 | * bit 13 - Padding indication | ||
1145 | * bit 14 - A-AMSDU indication | ||
1146 | * bit 15 - Offload enabled | ||
1147 | */ | ||
1148 | enum iwl_csum_rx_assist_info { | ||
1149 | CSUM_RXA_RESERVED_MASK = 0x000f, | ||
1150 | CSUM_RXA_MICSIZE_MASK = 0x00f0, | ||
1151 | CSUM_RXA_HEADERLEN_MASK = 0x1f00, | ||
1152 | CSUM_RXA_PADD = BIT(13), | ||
1153 | CSUM_RXA_AMSDU = BIT(14), | ||
1154 | CSUM_RXA_ENA = BIT(15) | ||
1155 | }; | ||
1156 | |||
1157 | /** | ||
1158 | * struct iwl_rx_mpdu_res_start - phy info | ||
1159 | * @assist: see CSUM_RX_ASSIST_ above | ||
1160 | */ | ||
1161 | struct iwl_rx_mpdu_res_start { | ||
1162 | __le16 byte_count; | ||
1163 | __le16 assist; | ||
1164 | } __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */ | ||
1165 | |||
1166 | /** | ||
1167 | * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags | ||
1168 | * @RX_RES_PHY_FLAGS_BAND_24: true if the packet was received on 2.4 band | ||
1169 | * @RX_RES_PHY_FLAGS_MOD_CCK: | ||
1170 | * @RX_RES_PHY_FLAGS_SHORT_PREAMBLE: true if packet's preamble was short | ||
1171 | * @RX_RES_PHY_FLAGS_NARROW_BAND: | ||
1172 | * @RX_RES_PHY_FLAGS_ANTENNA: antenna on which the packet was received | ||
1173 | * @RX_RES_PHY_FLAGS_AGG: set if the packet was part of an A-MPDU | ||
1174 | * @RX_RES_PHY_FLAGS_OFDM_HT: The frame was an HT frame | ||
1175 | * @RX_RES_PHY_FLAGS_OFDM_GF: The frame used GF preamble | ||
1176 | * @RX_RES_PHY_FLAGS_OFDM_VHT: The frame was a VHT frame | ||
1177 | */ | ||
1178 | enum iwl_rx_phy_flags { | ||
1179 | RX_RES_PHY_FLAGS_BAND_24 = BIT(0), | ||
1180 | RX_RES_PHY_FLAGS_MOD_CCK = BIT(1), | ||
1181 | RX_RES_PHY_FLAGS_SHORT_PREAMBLE = BIT(2), | ||
1182 | RX_RES_PHY_FLAGS_NARROW_BAND = BIT(3), | ||
1183 | RX_RES_PHY_FLAGS_ANTENNA = (0x7 << 4), | ||
1184 | RX_RES_PHY_FLAGS_ANTENNA_POS = 4, | ||
1185 | RX_RES_PHY_FLAGS_AGG = BIT(7), | ||
1186 | RX_RES_PHY_FLAGS_OFDM_HT = BIT(8), | ||
1187 | RX_RES_PHY_FLAGS_OFDM_GF = BIT(9), | ||
1188 | RX_RES_PHY_FLAGS_OFDM_VHT = BIT(10), | ||
1189 | }; | ||
1190 | |||
1191 | /** | ||
1192 | * enum iwl_mvm_rx_status - written by fw for each Rx packet | ||
1193 | * @RX_MPDU_RES_STATUS_CRC_OK: CRC is fine | ||
1194 | * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow | ||
1195 | * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: | ||
1196 | * @RX_MPDU_RES_STATUS_KEY_VALID: | ||
1197 | * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: | ||
1198 | * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed | ||
1199 | * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked | ||
1200 | * in the driver. | ||
1201 | * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine | ||
1202 | * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR: valid for alg = CCM_CMAC or | ||
1203 | * alg = CCM only. Checks replay attack for 11w frames. Relevant only if | ||
1204 | * %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set. | ||
1205 | * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted | ||
1206 | * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP | ||
1207 | * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM | ||
1208 | * @RX_MPDU_RES_STATUS_SEC_TKIP_ENC: this frame is encrypted using TKIP | ||
1209 | * @RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC: this frame is encrypted using CCM_CMAC | ||
1210 | * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted | ||
1211 | * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm | ||
1212 | * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted | ||
1213 | * @RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP: | ||
1214 | * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: | ||
1215 | * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: | ||
1216 | * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame | ||
1217 | * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw | ||
1218 | * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors | ||
1219 | * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK: | ||
1220 | * @RX_MPDU_RES_STATUS_STA_ID_MSK: | ||
1221 | * @RX_MPDU_RES_STATUS_RRF_KILL: | ||
1222 | * @RX_MPDU_RES_STATUS_FILTERING_MSK: | ||
1223 | * @RX_MPDU_RES_STATUS2_FILTERING_MSK: | ||
1224 | */ | ||
1225 | enum iwl_mvm_rx_status { | ||
1226 | RX_MPDU_RES_STATUS_CRC_OK = BIT(0), | ||
1227 | RX_MPDU_RES_STATUS_OVERRUN_OK = BIT(1), | ||
1228 | RX_MPDU_RES_STATUS_SRC_STA_FOUND = BIT(2), | ||
1229 | RX_MPDU_RES_STATUS_KEY_VALID = BIT(3), | ||
1230 | RX_MPDU_RES_STATUS_KEY_PARAM_OK = BIT(4), | ||
1231 | RX_MPDU_RES_STATUS_ICV_OK = BIT(5), | ||
1232 | RX_MPDU_RES_STATUS_MIC_OK = BIT(6), | ||
1233 | RX_MPDU_RES_STATUS_TTAK_OK = BIT(7), | ||
1234 | RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR = BIT(7), | ||
1235 | RX_MPDU_RES_STATUS_SEC_NO_ENC = (0 << 8), | ||
1236 | RX_MPDU_RES_STATUS_SEC_WEP_ENC = (1 << 8), | ||
1237 | RX_MPDU_RES_STATUS_SEC_CCM_ENC = (2 << 8), | ||
1238 | RX_MPDU_RES_STATUS_SEC_TKIP_ENC = (3 << 8), | ||
1239 | RX_MPDU_RES_STATUS_SEC_EXT_ENC = (4 << 8), | ||
1240 | RX_MPDU_RES_STATUS_SEC_CCM_CMAC_ENC = (6 << 8), | ||
1241 | RX_MPDU_RES_STATUS_SEC_ENC_ERR = (7 << 8), | ||
1242 | RX_MPDU_RES_STATUS_SEC_ENC_MSK = (7 << 8), | ||
1243 | RX_MPDU_RES_STATUS_DEC_DONE = BIT(11), | ||
1244 | RX_MPDU_RES_STATUS_PROTECT_FRAME_BIT_CMP = BIT(12), | ||
1245 | RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13), | ||
1246 | RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14), | ||
1247 | RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15), | ||
1248 | RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16), | ||
1249 | RX_MPDU_RES_STATUS_CSUM_OK = BIT(17), | ||
1250 | RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000), | ||
1251 | RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), | ||
1252 | RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), | ||
1253 | RX_MPDU_RES_STATUS_FILTERING_MSK = (0xc00000), | ||
1254 | RX_MPDU_RES_STATUS2_FILTERING_MSK = (0xc0000000), | ||
1255 | }; | ||
1256 | |||
1257 | /** | 1085 | /** |
1258 | * struct iwl_radio_version_notif - information on the radio version | 1086 | * struct iwl_radio_version_notif - information on the radio version |
1259 | * ( RADIO_VERSION_NOTIFICATION = 0x68 ) | 1087 | * ( RADIO_VERSION_NOTIFICATION = 0x68 ) |
@@ -1696,6 +1524,69 @@ struct iwl_dts_measurement_cmd { | |||
1696 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */ | 1524 | } __packed; /* TEMPERATURE_MEASUREMENT_TRIGGER_CMD_S */ |
1697 | 1525 | ||
1698 | /** | 1526 | /** |
1527 | * enum iwl_dts_control_measurement_mode - DTS measurement type | ||
1528 | * @DTS_AUTOMATIC: Automatic mode (full SW control). Provide temperature read | ||
1529 | * back (latest value. Not waiting for new value). Use automatic | ||
1530 | * SW DTS configuration. | ||
1531 | * @DTS_REQUEST_READ: Request DTS read. Configure DTS with manual settings, | ||
1532 | * trigger DTS reading and provide read back temperature read | ||
1533 | * when available. | ||
1534 | * @DTS_OVER_WRITE: over-write the DTS temperatures in the SW until next read | ||
1535 | * @DTS_DIRECT_WITHOUT_MEASURE: DTS returns its latest temperature result, | ||
1536 | * without measurement trigger. | ||
1537 | */ | ||
1538 | enum iwl_dts_control_measurement_mode { | ||
1539 | DTS_AUTOMATIC = 0, | ||
1540 | DTS_REQUEST_READ = 1, | ||
1541 | DTS_OVER_WRITE = 2, | ||
1542 | DTS_DIRECT_WITHOUT_MEASURE = 3, | ||
1543 | }; | ||
1544 | |||
1545 | /** | ||
1546 | * enum iwl_dts_used - DTS to use or used for measurement in the DTS request | ||
1547 | * @DTS_USE_TOP: Top | ||
1548 | * @DTS_USE_CHAIN_A: chain A | ||
1549 | * @DTS_USE_CHAIN_B: chain B | ||
1550 | * @DTS_USE_CHAIN_C: chain C | ||
1551 | * @XTAL_TEMPERATURE - read temperature from xtal | ||
1552 | */ | ||
1553 | enum iwl_dts_used { | ||
1554 | DTS_USE_TOP = 0, | ||
1555 | DTS_USE_CHAIN_A = 1, | ||
1556 | DTS_USE_CHAIN_B = 2, | ||
1557 | DTS_USE_CHAIN_C = 3, | ||
1558 | XTAL_TEMPERATURE = 4, | ||
1559 | }; | ||
1560 | |||
1561 | /** | ||
1562 | * enum iwl_dts_bit_mode - bit-mode to use in DTS request read mode | ||
1563 | * @DTS_BIT6_MODE: bit 6 mode | ||
1564 | * @DTS_BIT8_MODE: bit 8 mode | ||
1565 | */ | ||
1566 | enum iwl_dts_bit_mode { | ||
1567 | DTS_BIT6_MODE = 0, | ||
1568 | DTS_BIT8_MODE = 1, | ||
1569 | }; | ||
1570 | |||
1571 | /** | ||
1572 | * iwl_ext_dts_measurement_cmd - request extended DTS temperature measurements | ||
1573 | * @control_mode: see &enum iwl_dts_control_measurement_mode | ||
1574 | * @temperature: used when over write DTS mode is selected | ||
1575 | * @sensor: set temperature sensor to use. See &enum iwl_dts_used | ||
1576 | * @avg_factor: average factor to DTS in request DTS read mode | ||
1577 | * @bit_mode: value defines the DTS bit mode to use. See &enum iwl_dts_bit_mode | ||
1578 | * @step_duration: step duration for the DTS | ||
1579 | */ | ||
1580 | struct iwl_ext_dts_measurement_cmd { | ||
1581 | __le32 control_mode; | ||
1582 | __le32 temperature; | ||
1583 | __le32 sensor; | ||
1584 | __le32 avg_factor; | ||
1585 | __le32 bit_mode; | ||
1586 | __le32 step_duration; | ||
1587 | } __packed; /* XVT_FW_DTS_CONTROL_MEASUREMENT_REQUEST_API_S */ | ||
1588 | |||
1589 | /** | ||
1699 | * iwl_dts_measurement_notif - notification received with the measurements | 1590 | * iwl_dts_measurement_notif - notification received with the measurements |
1700 | * | 1591 | * |
1701 | * @temp: the measured temperature | 1592 | * @temp: the measured temperature |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 4a0ce83315bd..d906fa13ba97 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -616,12 +616,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
616 | * will be empty. | 616 | * will be empty. |
617 | */ | 617 | */ |
618 | 618 | ||
619 | for (i = 0; i < IWL_MAX_HW_QUEUES; i++) { | 619 | memset(&mvm->queue_info, 0, sizeof(mvm->queue_info)); |
620 | if (i < mvm->first_agg_queue && i != IWL_MVM_CMD_QUEUE) | 620 | mvm->queue_info[IWL_MVM_CMD_QUEUE].hw_queue_refcount = 1; |
621 | mvm->queue_to_mac80211[i] = i; | ||
622 | else | ||
623 | mvm->queue_to_mac80211[i] = IWL_INVALID_MAC80211_QUEUE; | ||
624 | } | ||
625 | 621 | ||
626 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) | 622 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) |
627 | atomic_set(&mvm->mac80211_queue_stop_count[i], 0); | 623 | atomic_set(&mvm->mac80211_queue_stop_count[i], 0); |
@@ -703,7 +699,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
703 | * abort after reading the nvm in case RF Kill is on, we will complete | 699 | * abort after reading the nvm in case RF Kill is on, we will complete |
704 | * the init seq later when RF kill will switch to off | 700 | * the init seq later when RF kill will switch to off |
705 | */ | 701 | */ |
706 | if (iwl_mvm_is_radio_killed(mvm)) { | 702 | if (iwl_mvm_is_radio_hw_killed(mvm)) { |
707 | IWL_DEBUG_RF_KILL(mvm, | 703 | IWL_DEBUG_RF_KILL(mvm, |
708 | "jump over all phy activities due to RF kill\n"); | 704 | "jump over all phy activities due to RF kill\n"); |
709 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); | 705 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); |
@@ -736,7 +732,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
736 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, | 732 | ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait, |
737 | MVM_UCODE_CALIB_TIMEOUT); | 733 | MVM_UCODE_CALIB_TIMEOUT); |
738 | 734 | ||
739 | if (ret && iwl_mvm_is_radio_killed(mvm)) { | 735 | if (ret && iwl_mvm_is_radio_hw_killed(mvm)) { |
740 | IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n"); | 736 | IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n"); |
741 | ret = 1; | 737 | ret = 1; |
742 | } | 738 | } |
@@ -940,19 +936,6 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) | |||
940 | return ret; | 936 | return ret; |
941 | } | 937 | } |
942 | 938 | ||
943 | static int iwl_mvm_config_ltr_v1(struct iwl_mvm *mvm) | ||
944 | { | ||
945 | struct iwl_ltr_config_cmd_v1 cmd_v1 = { | ||
946 | .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE), | ||
947 | }; | ||
948 | |||
949 | if (!mvm->trans->ltr_enabled) | ||
950 | return 0; | ||
951 | |||
952 | return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, | ||
953 | sizeof(cmd_v1), &cmd_v1); | ||
954 | } | ||
955 | |||
956 | static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) | 939 | static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) |
957 | { | 940 | { |
958 | struct iwl_ltr_config_cmd cmd = { | 941 | struct iwl_ltr_config_cmd cmd = { |
@@ -962,9 +945,6 @@ static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) | |||
962 | if (!mvm->trans->ltr_enabled) | 945 | if (!mvm->trans->ltr_enabled) |
963 | return 0; | 946 | return 0; |
964 | 947 | ||
965 | if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_HDC_PHASE_0)) | ||
966 | return iwl_mvm_config_ltr_v1(mvm); | ||
967 | |||
968 | return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, | 948 | return iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0, |
969 | sizeof(cmd), &cmd); | 949 | sizeof(cmd), &cmd); |
970 | } | 950 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 3424315dd876..ad7ad720d2e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,6 +34,7 @@ | |||
33 | * | 34 | * |
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 36 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
36 | * All rights reserved. | 38 | * All rights reserved. |
37 | * | 39 | * |
38 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -484,16 +486,18 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
484 | switch (vif->type) { | 486 | switch (vif->type) { |
485 | case NL80211_IFTYPE_P2P_DEVICE: | 487 | case NL80211_IFTYPE_P2P_DEVICE: |
486 | iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, | 488 | iwl_mvm_enable_ac_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, |
487 | IWL_MVM_TX_FIFO_VO, wdg_timeout); | 489 | IWL_MVM_OFFCHANNEL_QUEUE, |
490 | IWL_MVM_TX_FIFO_VO, 0, wdg_timeout); | ||
488 | break; | 491 | break; |
489 | case NL80211_IFTYPE_AP: | 492 | case NL80211_IFTYPE_AP: |
490 | iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, | 493 | iwl_mvm_enable_ac_txq(mvm, vif->cab_queue, vif->cab_queue, |
491 | IWL_MVM_TX_FIFO_MCAST, wdg_timeout); | 494 | IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); |
492 | /* fall through */ | 495 | /* fall through */ |
493 | default: | 496 | default: |
494 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 497 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
495 | iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], | 498 | iwl_mvm_enable_ac_txq(mvm, vif->hw_queue[ac], |
496 | iwl_mvm_ac_to_tx_fifo[ac], | 499 | vif->hw_queue[ac], |
500 | iwl_mvm_ac_to_tx_fifo[ac], 0, | ||
497 | wdg_timeout); | 501 | wdg_timeout); |
498 | break; | 502 | break; |
499 | } | 503 | } |
@@ -509,14 +513,19 @@ void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
509 | 513 | ||
510 | switch (vif->type) { | 514 | switch (vif->type) { |
511 | case NL80211_IFTYPE_P2P_DEVICE: | 515 | case NL80211_IFTYPE_P2P_DEVICE: |
512 | iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, 0); | 516 | iwl_mvm_disable_txq(mvm, IWL_MVM_OFFCHANNEL_QUEUE, |
517 | IWL_MVM_OFFCHANNEL_QUEUE, IWL_MAX_TID_COUNT, | ||
518 | 0); | ||
513 | break; | 519 | break; |
514 | case NL80211_IFTYPE_AP: | 520 | case NL80211_IFTYPE_AP: |
515 | iwl_mvm_disable_txq(mvm, vif->cab_queue, 0); | 521 | iwl_mvm_disable_txq(mvm, vif->cab_queue, vif->cab_queue, |
522 | IWL_MAX_TID_COUNT, 0); | ||
516 | /* fall through */ | 523 | /* fall through */ |
517 | default: | 524 | default: |
518 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 525 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
519 | iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], 0); | 526 | iwl_mvm_disable_txq(mvm, vif->hw_queue[ac], |
527 | vif->hw_queue[ac], | ||
528 | IWL_MAX_TID_COUNT, 0); | ||
520 | } | 529 | } |
521 | } | 530 | } |
522 | 531 | ||
@@ -834,6 +843,9 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, | |||
834 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); | 843 | ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval); |
835 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); | 844 | ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid); |
836 | 845 | ||
846 | if (vif->probe_req_reg && vif->bss_conf.assoc && vif->p2p) | ||
847 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); | ||
848 | |||
837 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); | 849 | return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd); |
838 | } | 850 | } |
839 | 851 | ||
@@ -1128,6 +1140,7 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, | |||
1128 | struct ieee80211_vif *vif, | 1140 | struct ieee80211_vif *vif, |
1129 | u32 action) | 1141 | u32 action) |
1130 | { | 1142 | { |
1143 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
1131 | struct iwl_mac_ctx_cmd cmd = {}; | 1144 | struct iwl_mac_ctx_cmd cmd = {}; |
1132 | 1145 | ||
1133 | WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p); | 1146 | WARN_ON(vif->type != NL80211_IFTYPE_AP || vif->p2p); |
@@ -1137,10 +1150,16 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm, | |||
1137 | 1150 | ||
1138 | /* | 1151 | /* |
1139 | * pass probe requests and beacons from other APs (needed | 1152 | * pass probe requests and beacons from other APs (needed |
1140 | * for ht protection) | 1153 | * for ht protection); when there're no any associated station |
1154 | * don't ask FW to pass beacons to prevent unnecessary wake-ups. | ||
1141 | */ | 1155 | */ |
1142 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST | | 1156 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST); |
1143 | MAC_FILTER_IN_BEACON); | 1157 | if (mvmvif->ap_assoc_sta_count) { |
1158 | cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); | ||
1159 | IWL_DEBUG_HC(mvm, "Asking FW to pass beacons\n"); | ||
1160 | } else { | ||
1161 | IWL_DEBUG_HC(mvm, "No need to receive beacons\n"); | ||
1162 | } | ||
1144 | 1163 | ||
1145 | /* Fill the data specific for ap mode */ | 1164 | /* Fill the data specific for ap mode */ |
1146 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, | 1165 | iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index aa8c2b7f23c7..1fb684693040 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -572,6 +572,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) | |||
572 | /* we create the 802.11 header and zero length SSID IE. */ | 572 | /* we create the 802.11 header and zero length SSID IE. */ |
573 | hw->wiphy->max_sched_scan_ie_len = | 573 | hw->wiphy->max_sched_scan_ie_len = |
574 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; | 574 | SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; |
575 | hw->wiphy->max_sched_scan_plans = IWL_MAX_SCHED_SCAN_PLANS; | ||
576 | hw->wiphy->max_sched_scan_plan_interval = U16_MAX; | ||
577 | |||
578 | /* | ||
579 | * the firmware uses u8 for num of iterations, but 0xff is saved for | ||
580 | * infinite loop, so the maximum number of iterations is actually 254. | ||
581 | */ | ||
582 | hw->wiphy->max_sched_scan_plan_iterations = 254; | ||
575 | 583 | ||
576 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | | 584 | hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | |
577 | NL80211_FEATURE_LOW_PRIORITY_SCAN | | 585 | NL80211_FEATURE_LOW_PRIORITY_SCAN | |
@@ -820,7 +828,7 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw, | |||
820 | struct ieee80211_vif *vif, | 828 | struct ieee80211_vif *vif, |
821 | enum ieee80211_ampdu_mlme_action action, | 829 | enum ieee80211_ampdu_mlme_action action, |
822 | struct ieee80211_sta *sta, u16 tid, | 830 | struct ieee80211_sta *sta, u16 tid, |
823 | u16 *ssn, u8 buf_size) | 831 | u16 *ssn, u8 buf_size, bool amsdu) |
824 | { | 832 | { |
825 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 833 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
826 | int ret; | 834 | int ret; |
@@ -1129,6 +1137,12 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
1129 | 1137 | ||
1130 | lockdep_assert_held(&mvm->mutex); | 1138 | lockdep_assert_held(&mvm->mutex); |
1131 | 1139 | ||
1140 | /* there's no point in fw dump if the bus is dead */ | ||
1141 | if (test_bit(STATUS_TRANS_DEAD, &mvm->trans->status)) { | ||
1142 | IWL_ERR(mvm, "Skip fw error dump since bus is dead\n"); | ||
1143 | return; | ||
1144 | } | ||
1145 | |||
1132 | if (mvm->fw_dump_trig && | 1146 | if (mvm->fw_dump_trig && |
1133 | mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) | 1147 | mvm->fw_dump_trig->mode & IWL_FW_DBG_TRIGGER_MONITOR_ONLY) |
1134 | monitor_dump_only = true; | 1148 | monitor_dump_only = true; |
@@ -1192,6 +1206,13 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
1192 | if (sram2_len) | 1206 | if (sram2_len) |
1193 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; | 1207 | file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len; |
1194 | 1208 | ||
1209 | /* Make room for fw's virtual image pages, if it exists */ | ||
1210 | if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) | ||
1211 | file_len += mvm->num_of_paging_blk * | ||
1212 | (sizeof(*dump_data) + | ||
1213 | sizeof(struct iwl_fw_error_dump_paging) + | ||
1214 | PAGING_BLOCK_SIZE); | ||
1215 | |||
1195 | /* If we only want a monitor dump, reset the file length */ | 1216 | /* If we only want a monitor dump, reset the file length */ |
1196 | if (monitor_dump_only) { | 1217 | if (monitor_dump_only) { |
1197 | file_len = sizeof(*dump_file) + sizeof(*dump_data) + | 1218 | file_len = sizeof(*dump_file) + sizeof(*dump_data) + |
@@ -1302,6 +1323,26 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
1302 | dump_mem->data, IWL8260_ICCM_LEN); | 1323 | dump_mem->data, IWL8260_ICCM_LEN); |
1303 | } | 1324 | } |
1304 | 1325 | ||
1326 | /* Dump fw's virtual image */ | ||
1327 | if (mvm->fw->img[mvm->cur_ucode].paging_mem_size) { | ||
1328 | u32 i; | ||
1329 | |||
1330 | for (i = 1; i < mvm->num_of_paging_blk + 1; i++) { | ||
1331 | struct iwl_fw_error_dump_paging *paging; | ||
1332 | struct page *pages = | ||
1333 | mvm->fw_paging_db[i].fw_paging_block; | ||
1334 | |||
1335 | dump_data = iwl_fw_error_next_data(dump_data); | ||
1336 | dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PAGING); | ||
1337 | dump_data->len = cpu_to_le32(sizeof(*paging) + | ||
1338 | PAGING_BLOCK_SIZE); | ||
1339 | paging = (void *)dump_data->data; | ||
1340 | paging->index = cpu_to_le32(i); | ||
1341 | memcpy(paging->data, page_address(pages), | ||
1342 | PAGING_BLOCK_SIZE); | ||
1343 | } | ||
1344 | } | ||
1345 | |||
1305 | dump_trans_data: | 1346 | dump_trans_data: |
1306 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans, | 1347 | fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans, |
1307 | mvm->fw_dump_trig); | 1348 | mvm->fw_dump_trig); |
@@ -1577,20 +1618,6 @@ static struct iwl_mvm_phy_ctxt *iwl_mvm_get_free_phy_ctxt(struct iwl_mvm *mvm) | |||
1577 | return NULL; | 1618 | return NULL; |
1578 | } | 1619 | } |
1579 | 1620 | ||
1580 | static int iwl_mvm_set_tx_power_old(struct iwl_mvm *mvm, | ||
1581 | struct ieee80211_vif *vif, s8 tx_power) | ||
1582 | { | ||
1583 | /* FW is in charge of regulatory enforcement */ | ||
1584 | struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = { | ||
1585 | .mac_context_id = iwl_mvm_vif_from_mac80211(vif)->id, | ||
1586 | .pwr_restriction = cpu_to_le16(tx_power), | ||
1587 | }; | ||
1588 | |||
1589 | return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, | ||
1590 | sizeof(reduce_txpwr_cmd), | ||
1591 | &reduce_txpwr_cmd); | ||
1592 | } | ||
1593 | |||
1594 | static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 1621 | static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
1595 | s16 tx_power) | 1622 | s16 tx_power) |
1596 | { | 1623 | { |
@@ -1602,9 +1629,6 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1602 | }; | 1629 | }; |
1603 | int len = sizeof(cmd); | 1630 | int len = sizeof(cmd); |
1604 | 1631 | ||
1605 | if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_TX_POWER_DEV)) | ||
1606 | return iwl_mvm_set_tx_power_old(mvm, vif, tx_power); | ||
1607 | |||
1608 | if (tx_power == IWL_DEFAULT_MAX_TX_POWER) | 1632 | if (tx_power == IWL_DEFAULT_MAX_TX_POWER) |
1609 | cmd.v2.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER); | 1633 | cmd.v2.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER); |
1610 | 1634 | ||
@@ -1771,7 +1795,7 @@ static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, | |||
1771 | * Flush them here. | 1795 | * Flush them here. |
1772 | */ | 1796 | */ |
1773 | mutex_lock(&mvm->mutex); | 1797 | mutex_lock(&mvm->mutex); |
1774 | iwl_mvm_flush_tx_path(mvm, tfd_msk, true); | 1798 | iwl_mvm_flush_tx_path(mvm, tfd_msk, 0); |
1775 | mutex_unlock(&mvm->mutex); | 1799 | mutex_unlock(&mvm->mutex); |
1776 | 1800 | ||
1777 | /* | 1801 | /* |
@@ -1972,6 +1996,27 @@ out: | |||
1972 | *total_flags = 0; | 1996 | *total_flags = 0; |
1973 | } | 1997 | } |
1974 | 1998 | ||
1999 | static void iwl_mvm_config_iface_filter(struct ieee80211_hw *hw, | ||
2000 | struct ieee80211_vif *vif, | ||
2001 | unsigned int filter_flags, | ||
2002 | unsigned int changed_flags) | ||
2003 | { | ||
2004 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
2005 | |||
2006 | /* We support only filter for probe requests */ | ||
2007 | if (!(changed_flags & FIF_PROBE_REQ)) | ||
2008 | return; | ||
2009 | |||
2010 | /* Supported only for p2p client interfaces */ | ||
2011 | if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc || | ||
2012 | !vif->p2p) | ||
2013 | return; | ||
2014 | |||
2015 | mutex_lock(&mvm->mutex); | ||
2016 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | ||
2017 | mutex_unlock(&mvm->mutex); | ||
2018 | } | ||
2019 | |||
1975 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 2020 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
1976 | struct iwl_bcast_iter_data { | 2021 | struct iwl_bcast_iter_data { |
1977 | struct iwl_mvm *mvm; | 2022 | struct iwl_mvm *mvm; |
@@ -2319,6 +2364,8 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, | |||
2319 | if (vif->type == NL80211_IFTYPE_AP) | 2364 | if (vif->type == NL80211_IFTYPE_AP) |
2320 | iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); | 2365 | iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif); |
2321 | 2366 | ||
2367 | mvmvif->ap_assoc_sta_count = 0; | ||
2368 | |||
2322 | /* Add the mac context */ | 2369 | /* Add the mac context */ |
2323 | ret = iwl_mvm_mac_ctxt_add(mvm, vif); | 2370 | ret = iwl_mvm_mac_ctxt_add(mvm, vif); |
2324 | if (ret) | 2371 | if (ret) |
@@ -2388,6 +2435,7 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw, | |||
2388 | iwl_mvm_remove_time_event(mvm, mvmvif, | 2435 | iwl_mvm_remove_time_event(mvm, mvmvif, |
2389 | &mvmvif->time_event_data); | 2436 | &mvmvif->time_event_data); |
2390 | RCU_INIT_POINTER(mvm->csa_vif, NULL); | 2437 | RCU_INIT_POINTER(mvm->csa_vif, NULL); |
2438 | mvmvif->csa_countdown = false; | ||
2391 | } | 2439 | } |
2392 | 2440 | ||
2393 | if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) { | 2441 | if (rcu_access_pointer(mvm->csa_tx_blocked_vif) == vif) { |
@@ -2613,6 +2661,7 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | |||
2613 | struct ieee80211_sta *sta) | 2661 | struct ieee80211_sta *sta) |
2614 | { | 2662 | { |
2615 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 2663 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
2664 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
2616 | struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); | 2665 | struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); |
2617 | 2666 | ||
2618 | /* | 2667 | /* |
@@ -2627,6 +2676,12 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw, | |||
2627 | if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id])) | 2676 | if (sta == rcu_access_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id])) |
2628 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], | 2677 | rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], |
2629 | ERR_PTR(-ENOENT)); | 2678 | ERR_PTR(-ENOENT)); |
2679 | |||
2680 | if (mvm_sta->vif->type == NL80211_IFTYPE_AP) { | ||
2681 | mvmvif->ap_assoc_sta_count--; | ||
2682 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | ||
2683 | } | ||
2684 | |||
2630 | mutex_unlock(&mvm->mutex); | 2685 | mutex_unlock(&mvm->mutex); |
2631 | } | 2686 | } |
2632 | 2687 | ||
@@ -3905,7 +3960,7 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, | |||
3905 | } | 3960 | } |
3906 | 3961 | ||
3907 | if (drop) { | 3962 | if (drop) { |
3908 | if (iwl_mvm_flush_tx_path(mvm, msk, true)) | 3963 | if (iwl_mvm_flush_tx_path(mvm, msk, 0)) |
3909 | IWL_ERR(mvm, "flush request fail\n"); | 3964 | IWL_ERR(mvm, "flush request fail\n"); |
3910 | mutex_unlock(&mvm->mutex); | 3965 | mutex_unlock(&mvm->mutex); |
3911 | } else { | 3966 | } else { |
@@ -4142,6 +4197,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
4142 | .config = iwl_mvm_mac_config, | 4197 | .config = iwl_mvm_mac_config, |
4143 | .prepare_multicast = iwl_mvm_prepare_multicast, | 4198 | .prepare_multicast = iwl_mvm_prepare_multicast, |
4144 | .configure_filter = iwl_mvm_configure_filter, | 4199 | .configure_filter = iwl_mvm_configure_filter, |
4200 | .config_iface_filter = iwl_mvm_config_iface_filter, | ||
4145 | .bss_info_changed = iwl_mvm_bss_info_changed, | 4201 | .bss_info_changed = iwl_mvm_bss_info_changed, |
4146 | .hw_scan = iwl_mvm_mac_hw_scan, | 4202 | .hw_scan = iwl_mvm_mac_hw_scan, |
4147 | .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, | 4203 | .cancel_hw_scan = iwl_mvm_mac_cancel_hw_scan, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 72e8a03a5293..4bde2d027dcd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -82,7 +82,6 @@ | |||
82 | #include "constants.h" | 82 | #include "constants.h" |
83 | #include "tof.h" | 83 | #include "tof.h" |
84 | 84 | ||
85 | #define IWL_INVALID_MAC80211_QUEUE 0xff | ||
86 | #define IWL_MVM_MAX_ADDRESSES 5 | 85 | #define IWL_MVM_MAX_ADDRESSES 5 |
87 | /* RSSI offset for WkP */ | 86 | /* RSSI offset for WkP */ |
88 | #define IWL_RSSI_OFFSET 50 | 87 | #define IWL_RSSI_OFFSET 50 |
@@ -323,11 +322,11 @@ enum iwl_bt_force_ant_mode { | |||
323 | struct iwl_mvm_vif_bf_data { | 322 | struct iwl_mvm_vif_bf_data { |
324 | bool bf_enabled; | 323 | bool bf_enabled; |
325 | bool ba_enabled; | 324 | bool ba_enabled; |
326 | s8 ave_beacon_signal; | 325 | int ave_beacon_signal; |
327 | s8 last_cqm_event; | 326 | int last_cqm_event; |
328 | s8 bt_coex_min_thold; | 327 | int bt_coex_min_thold; |
329 | s8 bt_coex_max_thold; | 328 | int bt_coex_max_thold; |
330 | s8 last_bt_coex_event; | 329 | int last_bt_coex_event; |
331 | }; | 330 | }; |
332 | 331 | ||
333 | /** | 332 | /** |
@@ -338,6 +337,8 @@ struct iwl_mvm_vif_bf_data { | |||
338 | * @bssid: BSSID for this (client) interface | 337 | * @bssid: BSSID for this (client) interface |
339 | * @associated: indicates that we're currently associated, used only for | 338 | * @associated: indicates that we're currently associated, used only for |
340 | * managing the firmware state in iwl_mvm_bss_info_changed_station() | 339 | * managing the firmware state in iwl_mvm_bss_info_changed_station() |
340 | * @ap_assoc_sta_count: count of stations associated to us - valid only | ||
341 | * if VIF type is AP | ||
341 | * @uploaded: indicates the MAC context has been added to the device | 342 | * @uploaded: indicates the MAC context has been added to the device |
342 | * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface | 343 | * @ap_ibss_active: indicates that AP/IBSS is configured and that the interface |
343 | * should get quota etc. | 344 | * should get quota etc. |
@@ -367,6 +368,7 @@ struct iwl_mvm_vif { | |||
367 | 368 | ||
368 | u8 bssid[ETH_ALEN]; | 369 | u8 bssid[ETH_ALEN]; |
369 | bool associated; | 370 | bool associated; |
371 | u8 ap_assoc_sta_count; | ||
370 | 372 | ||
371 | bool uploaded; | 373 | bool uploaded; |
372 | bool ap_ibss_active; | 374 | bool ap_ibss_active; |
@@ -602,7 +604,14 @@ struct iwl_mvm { | |||
602 | u64 on_time_scan; | 604 | u64 on_time_scan; |
603 | } radio_stats, accu_radio_stats; | 605 | } radio_stats, accu_radio_stats; |
604 | 606 | ||
605 | u8 queue_to_mac80211[IWL_MAX_HW_QUEUES]; | 607 | struct { |
608 | /* Map to HW queue */ | ||
609 | u32 hw_queue_to_mac80211; | ||
610 | u8 hw_queue_refcount; | ||
611 | bool setup_reserved; | ||
612 | u16 tid_bitmap; /* Bitmap of the TIDs mapped to this queue */ | ||
613 | } queue_info[IWL_MAX_HW_QUEUES]; | ||
614 | spinlock_t queue_info_lock; /* For syncing queue mgmt operations */ | ||
606 | atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES]; | 615 | atomic_t mac80211_queue_stop_count[IEEE80211_MAX_QUEUES]; |
607 | 616 | ||
608 | const char *nvm_file_name; | 617 | const char *nvm_file_name; |
@@ -679,6 +688,7 @@ struct iwl_mvm { | |||
679 | struct debugfs_blob_wrapper nvm_sw_blob; | 688 | struct debugfs_blob_wrapper nvm_sw_blob; |
680 | struct debugfs_blob_wrapper nvm_calib_blob; | 689 | struct debugfs_blob_wrapper nvm_calib_blob; |
681 | struct debugfs_blob_wrapper nvm_prod_blob; | 690 | struct debugfs_blob_wrapper nvm_prod_blob; |
691 | struct debugfs_blob_wrapper nvm_phy_sku_blob; | ||
682 | 692 | ||
683 | struct iwl_mvm_frame_stats drv_rx_stats; | 693 | struct iwl_mvm_frame_stats drv_rx_stats; |
684 | spinlock_t drv_stats_lock; | 694 | spinlock_t drv_stats_lock; |
@@ -860,6 +870,11 @@ static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm) | |||
860 | test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); | 870 | test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status); |
861 | } | 871 | } |
862 | 872 | ||
873 | static inline bool iwl_mvm_is_radio_hw_killed(struct iwl_mvm *mvm) | ||
874 | { | ||
875 | return test_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); | ||
876 | } | ||
877 | |||
863 | /* Must be called with rcu_read_lock() held and it can only be | 878 | /* Must be called with rcu_read_lock() held and it can only be |
864 | * released when mvmsta is not needed anymore. | 879 | * released when mvmsta is not needed anymore. |
865 | */ | 880 | */ |
@@ -907,6 +922,12 @@ static inline bool iwl_mvm_is_d0i3_supported(struct iwl_mvm *mvm) | |||
907 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); | 922 | IWL_UCODE_TLV_CAPA_D0I3_SUPPORT); |
908 | } | 923 | } |
909 | 924 | ||
925 | static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm) | ||
926 | { | ||
927 | return fw_has_capa(&mvm->fw->ucode_capa, | ||
928 | IWL_UCODE_TLV_CAPA_DQA_SUPPORT); | ||
929 | } | ||
930 | |||
910 | static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) | 931 | static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) |
911 | { | 932 | { |
912 | bool nvm_lar = mvm->nvm_data->lar_enabled; | 933 | bool nvm_lar = mvm->nvm_data->lar_enabled; |
@@ -934,11 +955,6 @@ static inline bool iwl_mvm_is_wifi_mcc_supported(struct iwl_mvm *mvm) | |||
934 | IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC); | 955 | IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC); |
935 | } | 956 | } |
936 | 957 | ||
937 | static inline bool iwl_mvm_is_scd_cfg_supported(struct iwl_mvm *mvm) | ||
938 | { | ||
939 | return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SCD_CFG); | ||
940 | } | ||
941 | |||
942 | static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm) | 958 | static inline bool iwl_mvm_bt_is_plcr_supported(struct iwl_mvm *mvm) |
943 | { | 959 | { |
944 | return fw_has_capa(&mvm->fw->ucode_capa, | 960 | return fw_has_capa(&mvm->fw->ucode_capa, |
@@ -959,6 +975,12 @@ static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm) | |||
959 | IWL_UCODE_TLV_CAPA_CSUM_SUPPORT); | 975 | IWL_UCODE_TLV_CAPA_CSUM_SUPPORT); |
960 | } | 976 | } |
961 | 977 | ||
978 | static inline bool iwl_mvm_has_new_rx_api(struct iwl_mvm *mvm) | ||
979 | { | ||
980 | /* firmware flag isn't defined yet */ | ||
981 | return false; | ||
982 | } | ||
983 | |||
962 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; | 984 | extern const u8 iwl_mvm_ac_to_tx_fifo[]; |
963 | 985 | ||
964 | struct iwl_rate_info { | 986 | struct iwl_rate_info { |
@@ -1014,7 +1036,7 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status); | |||
1014 | #else | 1036 | #else |
1015 | static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } | 1037 | static inline const char *iwl_mvm_get_tx_fail_reason(u32 status) { return ""; } |
1016 | #endif | 1038 | #endif |
1017 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync); | 1039 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags); |
1018 | void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); | 1040 | void iwl_mvm_async_handlers_purge(struct iwl_mvm *mvm); |
1019 | 1041 | ||
1020 | static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info, | 1042 | static inline void iwl_mvm_set_tx_cmd_ccmp(struct ieee80211_tx_info *info, |
@@ -1131,7 +1153,6 @@ void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm, | |||
1131 | struct ieee80211_vif *vif); | 1153 | struct ieee80211_vif *vif); |
1132 | unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, | 1154 | unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm, |
1133 | struct ieee80211_vif *exclude_vif); | 1155 | struct ieee80211_vif *exclude_vif); |
1134 | |||
1135 | /* Bindings */ | 1156 | /* Bindings */ |
1136 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 1157 | int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
1137 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 1158 | int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
@@ -1344,14 +1365,20 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) | |||
1344 | } | 1365 | } |
1345 | 1366 | ||
1346 | /* hw scheduler queue config */ | 1367 | /* hw scheduler queue config */ |
1347 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 1368 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, |
1348 | const struct iwl_trans_txq_scd_cfg *cfg, | 1369 | u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, |
1349 | unsigned int wdg_timeout); | 1370 | unsigned int wdg_timeout); |
1350 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags); | 1371 | /* |
1372 | * Disable a TXQ. | ||
1373 | * Note that in non-DQA mode the %mac80211_queue and %tid params are ignored. | ||
1374 | */ | ||
1375 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, | ||
1376 | u8 tid, u8 flags); | ||
1377 | int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq); | ||
1351 | 1378 | ||
1352 | static inline | 1379 | static inline |
1353 | void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, | 1380 | void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, |
1354 | u8 fifo, unsigned int wdg_timeout) | 1381 | u8 fifo, u16 ssn, unsigned int wdg_timeout) |
1355 | { | 1382 | { |
1356 | struct iwl_trans_txq_scd_cfg cfg = { | 1383 | struct iwl_trans_txq_scd_cfg cfg = { |
1357 | .fifo = fifo, | 1384 | .fifo = fifo, |
@@ -1360,13 +1387,13 @@ void iwl_mvm_enable_ac_txq(struct iwl_mvm *mvm, int queue, | |||
1360 | .frame_limit = IWL_FRAME_LIMIT, | 1387 | .frame_limit = IWL_FRAME_LIMIT, |
1361 | }; | 1388 | }; |
1362 | 1389 | ||
1363 | iwl_mvm_enable_txq(mvm, queue, 0, &cfg, wdg_timeout); | 1390 | iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); |
1364 | } | 1391 | } |
1365 | 1392 | ||
1366 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | 1393 | static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, |
1367 | int fifo, int sta_id, int tid, | 1394 | int mac80211_queue, int fifo, |
1368 | int frame_limit, u16 ssn, | 1395 | int sta_id, int tid, int frame_limit, |
1369 | unsigned int wdg_timeout) | 1396 | u16 ssn, unsigned int wdg_timeout) |
1370 | { | 1397 | { |
1371 | struct iwl_trans_txq_scd_cfg cfg = { | 1398 | struct iwl_trans_txq_scd_cfg cfg = { |
1372 | .fifo = fifo, | 1399 | .fifo = fifo, |
@@ -1376,7 +1403,7 @@ static inline void iwl_mvm_enable_agg_txq(struct iwl_mvm *mvm, int queue, | |||
1376 | .aggregate = true, | 1403 | .aggregate = true, |
1377 | }; | 1404 | }; |
1378 | 1405 | ||
1379 | iwl_mvm_enable_txq(mvm, queue, ssn, &cfg, wdg_timeout); | 1406 | iwl_mvm_enable_txq(mvm, queue, mac80211_queue, ssn, &cfg, wdg_timeout); |
1380 | } | 1407 | } |
1381 | 1408 | ||
1382 | /* Thermal management and CT-kill */ | 1409 | /* Thermal management and CT-kill */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 328187da7541..2ee0f6fe56a1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c | |||
@@ -316,7 +316,8 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) | |||
316 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, | 316 | return iwl_parse_nvm_data(mvm->trans->dev, mvm->cfg, hw, sw, calib, |
317 | regulatory, mac_override, phy_sku, | 317 | regulatory, mac_override, phy_sku, |
318 | mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, | 318 | mvm->fw->valid_tx_ant, mvm->fw->valid_rx_ant, |
319 | lar_enabled, mac_addr0, mac_addr1); | 319 | lar_enabled, mac_addr0, mac_addr1, |
320 | mvm->trans->hw_id); | ||
320 | } | 321 | } |
321 | 322 | ||
322 | #define MAX_NVM_FILE_LEN 16384 | 323 | #define MAX_NVM_FILE_LEN 16384 |
@@ -482,6 +483,7 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) | |||
482 | ret = -ENOMEM; | 483 | ret = -ENOMEM; |
483 | break; | 484 | break; |
484 | } | 485 | } |
486 | kfree(mvm->nvm_sections[section_id].data); | ||
485 | mvm->nvm_sections[section_id].data = temp; | 487 | mvm->nvm_sections[section_id].data = temp; |
486 | mvm->nvm_sections[section_id].length = section_size; | 488 | mvm->nvm_sections[section_id].length = section_size; |
487 | 489 | ||
@@ -563,6 +565,10 @@ int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic) | |||
563 | mvm->nvm_prod_blob.data = temp; | 565 | mvm->nvm_prod_blob.data = temp; |
564 | mvm->nvm_prod_blob.size = ret; | 566 | mvm->nvm_prod_blob.size = ret; |
565 | break; | 567 | break; |
568 | case NVM_SECTION_TYPE_PHY_SKU: | ||
569 | mvm->nvm_phy_sku_blob.data = temp; | ||
570 | mvm->nvm_phy_sku_blob.size = ret; | ||
571 | break; | ||
566 | default: | 572 | default: |
567 | if (section == mvm->cfg->nvm_hw_section_num) { | 573 | if (section == mvm->cfg->nvm_hw_section_num) { |
568 | mvm->nvm_hw_blob.data = temp; | 574 | mvm->nvm_hw_blob.data = temp; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index a37de3f410a0..13c97f665ba8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -89,6 +89,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); | |||
89 | MODULE_LICENSE("GPL"); | 89 | MODULE_LICENSE("GPL"); |
90 | 90 | ||
91 | static const struct iwl_op_mode_ops iwl_mvm_ops; | 91 | static const struct iwl_op_mode_ops iwl_mvm_ops; |
92 | static const struct iwl_op_mode_ops iwl_mvm_ops_mq; | ||
92 | 93 | ||
93 | struct iwl_mvm_mod_params iwlmvm_mod_params = { | 94 | struct iwl_mvm_mod_params iwlmvm_mod_params = { |
94 | .power_scheme = IWL_POWER_SCHEME_BPS, | 95 | .power_scheme = IWL_POWER_SCHEME_BPS, |
@@ -222,7 +223,6 @@ struct iwl_rx_handlers { | |||
222 | * called from a worker with mvm->mutex held. | 223 | * called from a worker with mvm->mutex held. |
223 | */ | 224 | */ |
224 | static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | 225 | static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { |
225 | RX_HANDLER(REPLY_RX_PHY_CMD, iwl_mvm_rx_rx_phy_cmd, false), | ||
226 | RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false), | 226 | RX_HANDLER(TX_CMD, iwl_mvm_rx_tx_cmd, false), |
227 | RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), | 227 | RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false), |
228 | 228 | ||
@@ -257,6 +257,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
257 | RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION, | 257 | RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION, |
258 | iwl_mvm_power_uapsd_misbehaving_ap_notif, false), | 258 | iwl_mvm_power_uapsd_misbehaving_ap_notif, false), |
259 | RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true), | 259 | RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true), |
260 | RX_HANDLER_GRP(PHY_OPS_GROUP, DTS_MEASUREMENT_NOTIF_WIDE, | ||
261 | iwl_mvm_temp_notif, true), | ||
260 | 262 | ||
261 | RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, | 263 | RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif, |
262 | true), | 264 | true), |
@@ -271,6 +273,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = { | |||
271 | static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = { | 273 | static const char *const iwl_mvm_cmd_strings[REPLY_MAX + 1] = { |
272 | CMD(MVM_ALIVE), | 274 | CMD(MVM_ALIVE), |
273 | CMD(REPLY_ERROR), | 275 | CMD(REPLY_ERROR), |
276 | CMD(ECHO_CMD), | ||
274 | CMD(INIT_COMPLETE_NOTIF), | 277 | CMD(INIT_COMPLETE_NOTIF), |
275 | CMD(PHY_CONTEXT_CMD), | 278 | CMD(PHY_CONTEXT_CMD), |
276 | CMD(MGMT_MCAST_KEY), | 279 | CMD(MGMT_MCAST_KEY), |
@@ -422,7 +425,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
422 | hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; | 425 | hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; |
423 | 426 | ||
424 | op_mode = hw->priv; | 427 | op_mode = hw->priv; |
425 | op_mode->ops = &iwl_mvm_ops; | ||
426 | 428 | ||
427 | mvm = IWL_OP_MODE_GET_MVM(op_mode); | 429 | mvm = IWL_OP_MODE_GET_MVM(op_mode); |
428 | mvm->dev = trans->dev; | 430 | mvm->dev = trans->dev; |
@@ -431,6 +433,15 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
431 | mvm->fw = fw; | 433 | mvm->fw = fw; |
432 | mvm->hw = hw; | 434 | mvm->hw = hw; |
433 | 435 | ||
436 | if (iwl_mvm_has_new_rx_api(mvm)) { | ||
437 | op_mode->ops = &iwl_mvm_ops_mq; | ||
438 | } else { | ||
439 | op_mode->ops = &iwl_mvm_ops; | ||
440 | |||
441 | if (WARN_ON(trans->num_rx_queues > 1)) | ||
442 | goto out_free; | ||
443 | } | ||
444 | |||
434 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; | 445 | mvm->restart_fw = iwlwifi_mod_params.restart_fw ? -1 : 0; |
435 | 446 | ||
436 | mvm->aux_queue = 15; | 447 | mvm->aux_queue = 15; |
@@ -451,6 +462,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
451 | INIT_LIST_HEAD(&mvm->aux_roc_te_list); | 462 | INIT_LIST_HEAD(&mvm->aux_roc_te_list); |
452 | INIT_LIST_HEAD(&mvm->async_handlers_list); | 463 | INIT_LIST_HEAD(&mvm->async_handlers_list); |
453 | spin_lock_init(&mvm->time_event_lock); | 464 | spin_lock_init(&mvm->time_event_lock); |
465 | spin_lock_init(&mvm->queue_info_lock); | ||
454 | 466 | ||
455 | INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); | 467 | INIT_WORK(&mvm->async_handlers_wk, iwl_mvm_async_handlers_wk); |
456 | INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); | 468 | INIT_WORK(&mvm->roc_done_wk, iwl_mvm_roc_done_wk); |
@@ -590,6 +602,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
590 | ieee80211_unregister_hw(mvm->hw); | 602 | ieee80211_unregister_hw(mvm->hw); |
591 | iwl_mvm_leds_exit(mvm); | 603 | iwl_mvm_leds_exit(mvm); |
592 | out_free: | 604 | out_free: |
605 | flush_delayed_work(&mvm->fw_dump_wk); | ||
593 | iwl_phy_db_free(mvm->phy_db); | 606 | iwl_phy_db_free(mvm->phy_db); |
594 | kfree(mvm->scan_cmd); | 607 | kfree(mvm->scan_cmd); |
595 | if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name) | 608 | if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name) |
@@ -617,6 +630,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
617 | kfree(mvm->d3_resume_sram); | 630 | kfree(mvm->d3_resume_sram); |
618 | if (mvm->nd_config) { | 631 | if (mvm->nd_config) { |
619 | kfree(mvm->nd_config->match_sets); | 632 | kfree(mvm->nd_config->match_sets); |
633 | kfree(mvm->nd_config->scan_plans); | ||
620 | kfree(mvm->nd_config); | 634 | kfree(mvm->nd_config); |
621 | mvm->nd_config = NULL; | 635 | mvm->nd_config = NULL; |
622 | } | 636 | } |
@@ -716,18 +730,11 @@ static inline void iwl_mvm_rx_check_trigger(struct iwl_mvm *mvm, | |||
716 | } | 730 | } |
717 | } | 731 | } |
718 | 732 | ||
719 | static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, | 733 | static void iwl_mvm_rx_common(struct iwl_mvm *mvm, |
720 | struct napi_struct *napi, | 734 | struct iwl_rx_cmd_buffer *rxb, |
721 | struct iwl_rx_cmd_buffer *rxb) | 735 | struct iwl_rx_packet *pkt) |
722 | { | 736 | { |
723 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 737 | int i; |
724 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
725 | u8 i; | ||
726 | |||
727 | if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) { | ||
728 | iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); | ||
729 | return; | ||
730 | } | ||
731 | 738 | ||
732 | iwl_mvm_rx_check_trigger(mvm, pkt); | 739 | iwl_mvm_rx_check_trigger(mvm, pkt); |
733 | 740 | ||
@@ -767,40 +774,84 @@ static void iwl_mvm_rx_dispatch(struct iwl_op_mode *op_mode, | |||
767 | } | 774 | } |
768 | } | 775 | } |
769 | 776 | ||
777 | static void iwl_mvm_rx(struct iwl_op_mode *op_mode, | ||
778 | struct napi_struct *napi, | ||
779 | struct iwl_rx_cmd_buffer *rxb) | ||
780 | { | ||
781 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
782 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
783 | |||
784 | if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) | ||
785 | iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); | ||
786 | else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) | ||
787 | iwl_mvm_rx_rx_phy_cmd(mvm, rxb); | ||
788 | else | ||
789 | iwl_mvm_rx_common(mvm, rxb, pkt); | ||
790 | } | ||
791 | |||
792 | static void iwl_mvm_rx_mq(struct iwl_op_mode *op_mode, | ||
793 | struct napi_struct *napi, | ||
794 | struct iwl_rx_cmd_buffer *rxb) | ||
795 | { | ||
796 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
797 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
798 | |||
799 | if (likely(pkt->hdr.cmd == REPLY_RX_MPDU_CMD)) | ||
800 | iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); | ||
801 | else if (pkt->hdr.cmd == REPLY_RX_PHY_CMD) | ||
802 | iwl_mvm_rx_rx_phy_cmd(mvm, rxb); | ||
803 | else | ||
804 | iwl_mvm_rx_common(mvm, rxb, pkt); | ||
805 | } | ||
806 | |||
770 | static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) | 807 | static void iwl_mvm_stop_sw_queue(struct iwl_op_mode *op_mode, int queue) |
771 | { | 808 | { |
772 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 809 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
773 | int mq = mvm->queue_to_mac80211[queue]; | 810 | unsigned long mq; |
811 | int q; | ||
774 | 812 | ||
775 | if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE)) | 813 | spin_lock_bh(&mvm->queue_info_lock); |
776 | return; | 814 | mq = mvm->queue_info[queue].hw_queue_to_mac80211; |
815 | spin_unlock_bh(&mvm->queue_info_lock); | ||
777 | 816 | ||
778 | if (atomic_inc_return(&mvm->mac80211_queue_stop_count[mq]) > 1) { | 817 | if (WARN_ON_ONCE(!mq)) |
779 | IWL_DEBUG_TX_QUEUES(mvm, | ||
780 | "queue %d (mac80211 %d) already stopped\n", | ||
781 | queue, mq); | ||
782 | return; | 818 | return; |
783 | } | ||
784 | 819 | ||
785 | ieee80211_stop_queue(mvm->hw, mq); | 820 | for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { |
821 | if (atomic_inc_return(&mvm->mac80211_queue_stop_count[q]) > 1) { | ||
822 | IWL_DEBUG_TX_QUEUES(mvm, | ||
823 | "queue %d (mac80211 %d) already stopped\n", | ||
824 | queue, q); | ||
825 | continue; | ||
826 | } | ||
827 | |||
828 | ieee80211_stop_queue(mvm->hw, q); | ||
829 | } | ||
786 | } | 830 | } |
787 | 831 | ||
788 | static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) | 832 | static void iwl_mvm_wake_sw_queue(struct iwl_op_mode *op_mode, int queue) |
789 | { | 833 | { |
790 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 834 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
791 | int mq = mvm->queue_to_mac80211[queue]; | 835 | unsigned long mq; |
836 | int q; | ||
792 | 837 | ||
793 | if (WARN_ON_ONCE(mq == IWL_INVALID_MAC80211_QUEUE)) | 838 | spin_lock_bh(&mvm->queue_info_lock); |
794 | return; | 839 | mq = mvm->queue_info[queue].hw_queue_to_mac80211; |
840 | spin_unlock_bh(&mvm->queue_info_lock); | ||
795 | 841 | ||
796 | if (atomic_dec_return(&mvm->mac80211_queue_stop_count[mq]) > 0) { | 842 | if (WARN_ON_ONCE(!mq)) |
797 | IWL_DEBUG_TX_QUEUES(mvm, | ||
798 | "queue %d (mac80211 %d) still stopped\n", | ||
799 | queue, mq); | ||
800 | return; | 843 | return; |
801 | } | ||
802 | 844 | ||
803 | ieee80211_wake_queue(mvm->hw, mq); | 845 | for_each_set_bit(q, &mq, IEEE80211_MAX_QUEUES) { |
846 | if (atomic_dec_return(&mvm->mac80211_queue_stop_count[q]) > 0) { | ||
847 | IWL_DEBUG_TX_QUEUES(mvm, | ||
848 | "queue %d (mac80211 %d) still stopped\n", | ||
849 | queue, q); | ||
850 | continue; | ||
851 | } | ||
852 | |||
853 | ieee80211_wake_queue(mvm->hw, q); | ||
854 | } | ||
804 | } | 855 | } |
805 | 856 | ||
806 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) | 857 | void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) |
@@ -1145,12 +1196,17 @@ int iwl_mvm_enter_d0i3(struct iwl_op_mode *op_mode) | |||
1145 | /* make sure we have no running tx while configuring the seqno */ | 1196 | /* make sure we have no running tx while configuring the seqno */ |
1146 | synchronize_net(); | 1197 | synchronize_net(); |
1147 | 1198 | ||
1148 | iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, &d0i3_iter_data); | 1199 | /* configure wowlan configuration only if needed */ |
1149 | ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, | 1200 | if (mvm->d0i3_ap_sta_id != IWL_MVM_STATION_COUNT) { |
1150 | sizeof(wowlan_config_cmd), | 1201 | iwl_mvm_set_wowlan_data(mvm, &wowlan_config_cmd, |
1151 | &wowlan_config_cmd); | 1202 | &d0i3_iter_data); |
1152 | if (ret) | 1203 | |
1153 | return ret; | 1204 | ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, flags, |
1205 | sizeof(wowlan_config_cmd), | ||
1206 | &wowlan_config_cmd); | ||
1207 | if (ret) | ||
1208 | return ret; | ||
1209 | } | ||
1154 | 1210 | ||
1155 | return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, | 1211 | return iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, |
1156 | flags | CMD_MAKE_TRANS_IDLE, | 1212 | flags | CMD_MAKE_TRANS_IDLE, |
@@ -1257,7 +1313,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
1257 | }; | 1313 | }; |
1258 | struct iwl_wowlan_status *status; | 1314 | struct iwl_wowlan_status *status; |
1259 | int ret; | 1315 | int ret; |
1260 | u32 handled_reasons, wakeup_reasons; | 1316 | u32 handled_reasons, wakeup_reasons = 0; |
1261 | __le16 *qos_seq = NULL; | 1317 | __le16 *qos_seq = NULL; |
1262 | 1318 | ||
1263 | mutex_lock(&mvm->mutex); | 1319 | mutex_lock(&mvm->mutex); |
@@ -1289,6 +1345,9 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk) | |||
1289 | out: | 1345 | out: |
1290 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); | 1346 | iwl_mvm_d0i3_enable_tx(mvm, qos_seq); |
1291 | 1347 | ||
1348 | IWL_DEBUG_INFO(mvm, "d0i3 exit completed (wakeup reasons: 0x%x)\n", | ||
1349 | wakeup_reasons); | ||
1350 | |||
1292 | /* qos_seq might point inside resp_pkt, so free it only now */ | 1351 | /* qos_seq might point inside resp_pkt, so free it only now */ |
1293 | if (get_status_cmd.resp_pkt) | 1352 | if (get_status_cmd.resp_pkt) |
1294 | iwl_free_resp(&get_status_cmd); | 1353 | iwl_free_resp(&get_status_cmd); |
@@ -1338,17 +1397,38 @@ int iwl_mvm_exit_d0i3(struct iwl_op_mode *op_mode) | |||
1338 | return _iwl_mvm_exit_d0i3(mvm); | 1397 | return _iwl_mvm_exit_d0i3(mvm); |
1339 | } | 1398 | } |
1340 | 1399 | ||
1400 | #define IWL_MVM_COMMON_OPS \ | ||
1401 | /* these could be differentiated */ \ | ||
1402 | .queue_full = iwl_mvm_stop_sw_queue, \ | ||
1403 | .queue_not_full = iwl_mvm_wake_sw_queue, \ | ||
1404 | .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, \ | ||
1405 | .free_skb = iwl_mvm_free_skb, \ | ||
1406 | .nic_error = iwl_mvm_nic_error, \ | ||
1407 | .cmd_queue_full = iwl_mvm_cmd_queue_full, \ | ||
1408 | .nic_config = iwl_mvm_nic_config, \ | ||
1409 | .enter_d0i3 = iwl_mvm_enter_d0i3, \ | ||
1410 | .exit_d0i3 = iwl_mvm_exit_d0i3, \ | ||
1411 | /* as we only register one, these MUST be common! */ \ | ||
1412 | .start = iwl_op_mode_mvm_start, \ | ||
1413 | .stop = iwl_op_mode_mvm_stop | ||
1414 | |||
1341 | static const struct iwl_op_mode_ops iwl_mvm_ops = { | 1415 | static const struct iwl_op_mode_ops iwl_mvm_ops = { |
1342 | .start = iwl_op_mode_mvm_start, | 1416 | IWL_MVM_COMMON_OPS, |
1343 | .stop = iwl_op_mode_mvm_stop, | 1417 | .rx = iwl_mvm_rx, |
1344 | .rx = iwl_mvm_rx_dispatch, | 1418 | }; |
1345 | .queue_full = iwl_mvm_stop_sw_queue, | 1419 | |
1346 | .queue_not_full = iwl_mvm_wake_sw_queue, | 1420 | static void iwl_mvm_rx_mq_rss(struct iwl_op_mode *op_mode, |
1347 | .hw_rf_kill = iwl_mvm_set_hw_rfkill_state, | 1421 | struct napi_struct *napi, |
1348 | .free_skb = iwl_mvm_free_skb, | 1422 | struct iwl_rx_cmd_buffer *rxb, |
1349 | .nic_error = iwl_mvm_nic_error, | 1423 | unsigned int queue) |
1350 | .cmd_queue_full = iwl_mvm_cmd_queue_full, | 1424 | { |
1351 | .nic_config = iwl_mvm_nic_config, | 1425 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
1352 | .enter_d0i3 = iwl_mvm_enter_d0i3, | 1426 | |
1353 | .exit_d0i3 = iwl_mvm_exit_d0i3, | 1427 | iwl_mvm_rx_rx_mpdu(mvm, napi, rxb); |
1428 | } | ||
1429 | |||
1430 | static const struct iwl_op_mode_ops iwl_mvm_ops_mq = { | ||
1431 | IWL_MVM_COMMON_OPS, | ||
1432 | .rx = iwl_mvm_rx_mq, | ||
1433 | .rx_rss = iwl_mvm_rx_mq_rss, | ||
1354 | }; | 1434 | }; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 4645877882a6..bed9696ee410 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
10 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -33,6 +34,7 @@ | |||
33 | * | 34 | * |
34 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 35 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
35 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 36 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
37 | * Copyright(c) 2015 Intel Deutschland GmbH | ||
36 | * All rights reserved. | 38 | * All rights reserved. |
37 | * | 39 | * |
38 | * Redistribution and use in source and binary forms, with or without | 40 | * Redistribution and use in source and binary forms, with or without |
@@ -306,13 +308,51 @@ static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif) | |||
306 | return radar_detect; | 308 | return radar_detect; |
307 | } | 309 | } |
308 | 310 | ||
311 | static void iwl_mvm_power_config_skip_dtim(struct iwl_mvm *mvm, | ||
312 | struct ieee80211_vif *vif, | ||
313 | struct iwl_mac_power_cmd *cmd, | ||
314 | bool host_awake) | ||
315 | { | ||
316 | int dtimper = vif->bss_conf.dtim_period ?: 1; | ||
317 | int skip; | ||
318 | |||
319 | /* disable, in case we're supposed to override */ | ||
320 | cmd->skip_dtim_periods = 0; | ||
321 | cmd->flags &= ~cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
322 | |||
323 | if (iwl_mvm_power_is_radar(vif)) | ||
324 | return; | ||
325 | |||
326 | if (dtimper >= 10) | ||
327 | return; | ||
328 | |||
329 | /* TODO: check that multicast wake lock is off */ | ||
330 | |||
331 | if (host_awake) { | ||
332 | if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_LP) | ||
333 | return; | ||
334 | skip = 2; | ||
335 | } else { | ||
336 | int dtimper_tu = dtimper * vif->bss_conf.beacon_int; | ||
337 | |||
338 | if (WARN_ON(!dtimper_tu)) | ||
339 | return; | ||
340 | /* configure skip over dtim up to 306TU - 314 msec */ | ||
341 | skip = max_t(u8, 1, 306 / dtimper_tu); | ||
342 | } | ||
343 | |||
344 | /* the firmware really expects "look at every X DTIMs", so add 1 */ | ||
345 | cmd->skip_dtim_periods = 1 + skip; | ||
346 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
347 | } | ||
348 | |||
309 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | 349 | static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, |
310 | struct ieee80211_vif *vif, | 350 | struct ieee80211_vif *vif, |
311 | struct iwl_mac_power_cmd *cmd) | 351 | struct iwl_mac_power_cmd *cmd, |
352 | bool host_awake) | ||
312 | { | 353 | { |
313 | int dtimper, bi; | 354 | int dtimper, bi; |
314 | int keep_alive; | 355 | int keep_alive; |
315 | bool radar_detect = false; | ||
316 | struct iwl_mvm_vif *mvmvif __maybe_unused = | 356 | struct iwl_mvm_vif *mvmvif __maybe_unused = |
317 | iwl_mvm_vif_from_mac80211(vif); | 357 | iwl_mvm_vif_from_mac80211(vif); |
318 | 358 | ||
@@ -337,8 +377,13 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
337 | 377 | ||
338 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); | 378 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_SAVE_ENA_MSK); |
339 | 379 | ||
340 | if (!vif->bss_conf.ps || !mvmvif->pm_enabled || | 380 | if (!vif->bss_conf.ps || !mvmvif->pm_enabled) |
341 | (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p)) | 381 | return; |
382 | |||
383 | if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && | ||
384 | (!fw_has_capa(&mvm->fw->ucode_capa, | ||
385 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS) || | ||
386 | !IWL_MVM_P2P_LOWLATENCY_PS_ENABLE)) | ||
342 | return; | 387 | return; |
343 | 388 | ||
344 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); | 389 | cmd->flags |= cpu_to_le16(POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK); |
@@ -350,27 +395,25 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, | |||
350 | cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; | 395 | cmd->lprx_rssi_threshold = POWER_LPRX_RSSI_THRESHOLD; |
351 | } | 396 | } |
352 | 397 | ||
353 | /* Check if radar detection is required on current channel */ | 398 | iwl_mvm_power_config_skip_dtim(mvm, vif, cmd, host_awake); |
354 | radar_detect = iwl_mvm_power_is_radar(vif); | ||
355 | 399 | ||
356 | /* Check skip over DTIM conditions */ | 400 | if (!host_awake) { |
357 | if (!radar_detect && (dtimper < 10) && | ||
358 | (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP || | ||
359 | mvm->cur_ucode == IWL_UCODE_WOWLAN)) { | ||
360 | cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
361 | cmd->skip_dtim_periods = 3; | ||
362 | } | ||
363 | |||
364 | if (mvm->cur_ucode != IWL_UCODE_WOWLAN) { | ||
365 | cmd->rx_data_timeout = | 401 | cmd->rx_data_timeout = |
366 | cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); | 402 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); |
367 | cmd->tx_data_timeout = | 403 | cmd->tx_data_timeout = |
368 | cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); | 404 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); |
405 | } else if (iwl_mvm_vif_low_latency(mvmvif) && vif->p2p && | ||
406 | fw_has_capa(&mvm->fw->ucode_capa, | ||
407 | IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS)) { | ||
408 | cmd->tx_data_timeout = | ||
409 | cpu_to_le32(IWL_MVM_SHORT_PS_TX_DATA_TIMEOUT); | ||
410 | cmd->rx_data_timeout = | ||
411 | cpu_to_le32(IWL_MVM_SHORT_PS_RX_DATA_TIMEOUT); | ||
369 | } else { | 412 | } else { |
370 | cmd->rx_data_timeout = | 413 | cmd->rx_data_timeout = |
371 | cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT); | 414 | cpu_to_le32(IWL_MVM_DEFAULT_PS_RX_DATA_TIMEOUT); |
372 | cmd->tx_data_timeout = | 415 | cmd->tx_data_timeout = |
373 | cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT); | 416 | cpu_to_le32(IWL_MVM_DEFAULT_PS_TX_DATA_TIMEOUT); |
374 | } | 417 | } |
375 | 418 | ||
376 | if (iwl_mvm_power_allow_uapsd(mvm, vif)) | 419 | if (iwl_mvm_power_allow_uapsd(mvm, vif)) |
@@ -427,7 +470,8 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, | |||
427 | { | 470 | { |
428 | struct iwl_mac_power_cmd cmd = {}; | 471 | struct iwl_mac_power_cmd cmd = {}; |
429 | 472 | ||
430 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 473 | iwl_mvm_power_build_cmd(mvm, vif, &cmd, |
474 | mvm->cur_ucode != IWL_UCODE_WOWLAN); | ||
431 | iwl_mvm_power_log(mvm, &cmd); | 475 | iwl_mvm_power_log(mvm, &cmd); |
432 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 476 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
433 | memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); | 477 | memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd)); |
@@ -440,14 +484,14 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm, | |||
440 | int iwl_mvm_power_update_device(struct iwl_mvm *mvm) | 484 | int iwl_mvm_power_update_device(struct iwl_mvm *mvm) |
441 | { | 485 | { |
442 | struct iwl_device_power_cmd cmd = { | 486 | struct iwl_device_power_cmd cmd = { |
443 | .flags = cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK), | 487 | .flags = 0, |
444 | }; | 488 | }; |
445 | 489 | ||
446 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) | 490 | if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) |
447 | mvm->ps_disabled = true; | 491 | mvm->ps_disabled = true; |
448 | 492 | ||
449 | if (mvm->ps_disabled) | 493 | if (!mvm->ps_disabled) |
450 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_CAM_MSK); | 494 | cmd.flags |= cpu_to_le16(DEVICE_POWER_FLAGS_POWER_SAVE_ENA_MSK); |
451 | 495 | ||
452 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 496 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
453 | if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 : | 497 | if ((mvm->cur_ucode == IWL_UCODE_WOWLAN) ? mvm->disable_power_off_d3 : |
@@ -963,25 +1007,8 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, | |||
963 | if (!vif->bss_conf.assoc) | 1007 | if (!vif->bss_conf.assoc) |
964 | return 0; | 1008 | return 0; |
965 | 1009 | ||
966 | iwl_mvm_power_build_cmd(mvm, vif, &cmd); | 1010 | iwl_mvm_power_build_cmd(mvm, vif, &cmd, !enable); |
967 | if (enable) { | ||
968 | /* configure skip over dtim up to 306TU - 314 msec */ | ||
969 | int dtimper = vif->bss_conf.dtim_period ?: 1; | ||
970 | int dtimper_tu = dtimper * vif->bss_conf.beacon_int; | ||
971 | bool radar_detect = iwl_mvm_power_is_radar(vif); | ||
972 | 1011 | ||
973 | if (WARN_ON(!dtimper_tu)) | ||
974 | return 0; | ||
975 | |||
976 | /* Check skip over DTIM conditions */ | ||
977 | /* TODO: check that multicast wake lock is off */ | ||
978 | if (!radar_detect && (dtimper < 10)) { | ||
979 | cmd.skip_dtim_periods = 306 / dtimper_tu; | ||
980 | if (cmd.skip_dtim_periods) | ||
981 | cmd.flags |= cpu_to_le16( | ||
982 | POWER_FLAGS_SKIP_OVER_DTIM_MSK); | ||
983 | } | ||
984 | } | ||
985 | iwl_mvm_power_log(mvm, &cmd); | 1012 | iwl_mvm_power_log(mvm, &cmd); |
986 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1013 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
987 | memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); | 1014 | memcpy(&mvmvif->mac_pwr_cmd, &cmd, sizeof(cmd)); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 5ae9c8aa868f..d1ad10391b47 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -177,9 +177,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
177 | 177 | ||
178 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 178 | mvmsta = iwl_mvm_sta_from_mac80211(sta); |
179 | mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); | 179 | mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif); |
180 | if (IWL_MVM_RS_DISABLE_P2P_MIMO && | ||
181 | iwl_mvm_vif_low_latency(mvmvif) && mvmsta->vif->p2p) | ||
182 | return false; | ||
183 | 180 | ||
184 | if (mvm->nvm_data->sku_cap_mimo_disabled) | 181 | if (mvm->nvm_data->sku_cap_mimo_disabled) |
185 | return false; | 182 | return false; |
@@ -524,14 +521,56 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) | |||
524 | return lq_types[type]; | 521 | return lq_types[type]; |
525 | } | 522 | } |
526 | 523 | ||
524 | static char *rs_pretty_rate(const struct rs_rate *rate) | ||
525 | { | ||
526 | static char buf[40]; | ||
527 | static const char * const legacy_rates[] = { | ||
528 | [IWL_RATE_1M_INDEX] = "1M", | ||
529 | [IWL_RATE_2M_INDEX] = "2M", | ||
530 | [IWL_RATE_5M_INDEX] = "5.5M", | ||
531 | [IWL_RATE_11M_INDEX] = "11M", | ||
532 | [IWL_RATE_6M_INDEX] = "6M", | ||
533 | [IWL_RATE_9M_INDEX] = "9M", | ||
534 | [IWL_RATE_12M_INDEX] = "12M", | ||
535 | [IWL_RATE_18M_INDEX] = "18M", | ||
536 | [IWL_RATE_24M_INDEX] = "24M", | ||
537 | [IWL_RATE_36M_INDEX] = "36M", | ||
538 | [IWL_RATE_48M_INDEX] = "48M", | ||
539 | [IWL_RATE_54M_INDEX] = "54M", | ||
540 | }; | ||
541 | static const char *const ht_vht_rates[] = { | ||
542 | [IWL_RATE_MCS_0_INDEX] = "MCS0", | ||
543 | [IWL_RATE_MCS_1_INDEX] = "MCS1", | ||
544 | [IWL_RATE_MCS_2_INDEX] = "MCS2", | ||
545 | [IWL_RATE_MCS_3_INDEX] = "MCS3", | ||
546 | [IWL_RATE_MCS_4_INDEX] = "MCS4", | ||
547 | [IWL_RATE_MCS_5_INDEX] = "MCS5", | ||
548 | [IWL_RATE_MCS_6_INDEX] = "MCS6", | ||
549 | [IWL_RATE_MCS_7_INDEX] = "MCS7", | ||
550 | [IWL_RATE_MCS_8_INDEX] = "MCS8", | ||
551 | [IWL_RATE_MCS_9_INDEX] = "MCS9", | ||
552 | }; | ||
553 | const char *rate_str; | ||
554 | |||
555 | if (is_type_legacy(rate->type)) | ||
556 | rate_str = legacy_rates[rate->index]; | ||
557 | else if (is_type_ht(rate->type) || is_type_vht(rate->type)) | ||
558 | rate_str = ht_vht_rates[rate->index]; | ||
559 | else | ||
560 | rate_str = "BAD_RATE"; | ||
561 | |||
562 | sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type), | ||
563 | rs_pretty_ant(rate->ant), rate_str); | ||
564 | return buf; | ||
565 | } | ||
566 | |||
527 | static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, | 567 | static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, |
528 | const char *prefix) | 568 | const char *prefix) |
529 | { | 569 | { |
530 | IWL_DEBUG_RATE(mvm, | 570 | IWL_DEBUG_RATE(mvm, |
531 | "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", | 571 | "%s: %s BW: %d SGI: %d LDPC: %d STBC: %d\n", |
532 | prefix, rs_pretty_lq_type(rate->type), | 572 | prefix, rs_pretty_rate(rate), rate->bw, |
533 | rate->index, rs_pretty_ant(rate->ant), | 573 | rate->sgi, rate->ldpc, rate->stbc); |
534 | rate->bw, rate->sgi, rate->ldpc, rate->stbc); | ||
535 | } | 574 | } |
536 | 575 | ||
537 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) | 576 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) |
@@ -562,8 +601,8 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) | |||
562 | } | 601 | } |
563 | 602 | ||
564 | static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, | 603 | static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm, |
565 | struct iwl_lq_sta *lq_data, u8 tid, | 604 | struct iwl_lq_sta *lq_data, u8 tid, |
566 | struct ieee80211_sta *sta) | 605 | struct ieee80211_sta *sta) |
567 | { | 606 | { |
568 | int ret = -EAGAIN; | 607 | int ret = -EAGAIN; |
569 | 608 | ||
@@ -1485,7 +1524,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, | |||
1485 | u32 target_tpt; | 1524 | u32 target_tpt; |
1486 | int rate_idx; | 1525 | int rate_idx; |
1487 | 1526 | ||
1488 | if (success_ratio > IWL_MVM_RS_SR_NO_DECREASE) { | 1527 | if (success_ratio >= RS_PERCENT(IWL_MVM_RS_SR_NO_DECREASE)) { |
1489 | target_tpt = 100 * expected_current_tpt; | 1528 | target_tpt = 100 * expected_current_tpt; |
1490 | IWL_DEBUG_RATE(mvm, | 1529 | IWL_DEBUG_RATE(mvm, |
1491 | "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n", | 1530 | "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n", |
@@ -1493,7 +1532,7 @@ static s32 rs_get_best_rate(struct iwl_mvm *mvm, | |||
1493 | } else { | 1532 | } else { |
1494 | target_tpt = lq_sta->last_tpt; | 1533 | target_tpt = lq_sta->last_tpt; |
1495 | IWL_DEBUG_RATE(mvm, | 1534 | IWL_DEBUG_RATE(mvm, |
1496 | "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n", | 1535 | "SR %d not that good. Find rate exceeding ACTUAL_TPT %d\n", |
1497 | success_ratio, target_tpt); | 1536 | success_ratio, target_tpt); |
1498 | } | 1537 | } |
1499 | 1538 | ||
@@ -1622,6 +1661,51 @@ static void rs_update_rate_tbl(struct iwl_mvm *mvm, | |||
1622 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); | 1661 | iwl_mvm_send_lq_cmd(mvm, &lq_sta->lq, false); |
1623 | } | 1662 | } |
1624 | 1663 | ||
1664 | static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm, | ||
1665 | struct ieee80211_sta *sta, | ||
1666 | struct iwl_lq_sta *lq_sta, | ||
1667 | struct iwl_scale_tbl_info *tbl, | ||
1668 | enum rs_action scale_action) | ||
1669 | { | ||
1670 | if (sta->bandwidth != IEEE80211_STA_RX_BW_80) | ||
1671 | return false; | ||
1672 | |||
1673 | if (!is_vht_siso(&tbl->rate)) | ||
1674 | return false; | ||
1675 | |||
1676 | if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_80) && | ||
1677 | (tbl->rate.index == IWL_RATE_MCS_0_INDEX) && | ||
1678 | (scale_action == RS_ACTION_DOWNSCALE)) { | ||
1679 | tbl->rate.bw = RATE_MCS_CHAN_WIDTH_20; | ||
1680 | tbl->rate.index = IWL_RATE_MCS_4_INDEX; | ||
1681 | IWL_DEBUG_RATE(mvm, "Switch 80Mhz SISO MCS0 -> 20Mhz MCS4\n"); | ||
1682 | goto tweaked; | ||
1683 | } | ||
1684 | |||
1685 | /* Go back to 80Mhz MCS1 only if we've established that 20Mhz MCS5 is | ||
1686 | * sustainable, i.e. we're past the test window. We can't go back | ||
1687 | * if MCS5 is just tested as this will happen always after switching | ||
1688 | * to 20Mhz MCS4 because the rate stats are cleared. | ||
1689 | */ | ||
1690 | if ((tbl->rate.bw == RATE_MCS_CHAN_WIDTH_20) && | ||
1691 | (((tbl->rate.index == IWL_RATE_MCS_5_INDEX) && | ||
1692 | (scale_action == RS_ACTION_STAY)) || | ||
1693 | ((tbl->rate.index > IWL_RATE_MCS_5_INDEX) && | ||
1694 | (scale_action == RS_ACTION_UPSCALE)))) { | ||
1695 | tbl->rate.bw = RATE_MCS_CHAN_WIDTH_80; | ||
1696 | tbl->rate.index = IWL_RATE_MCS_1_INDEX; | ||
1697 | IWL_DEBUG_RATE(mvm, "Switch 20Mhz SISO MCS5 -> 80Mhz MCS1\n"); | ||
1698 | goto tweaked; | ||
1699 | } | ||
1700 | |||
1701 | return false; | ||
1702 | |||
1703 | tweaked: | ||
1704 | rs_set_expected_tpt_table(lq_sta, tbl); | ||
1705 | rs_rate_scale_clear_tbl_windows(mvm, tbl); | ||
1706 | return true; | ||
1707 | } | ||
1708 | |||
1625 | static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, | 1709 | static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, |
1626 | struct iwl_lq_sta *lq_sta, | 1710 | struct iwl_lq_sta *lq_sta, |
1627 | struct ieee80211_sta *sta, | 1711 | struct ieee80211_sta *sta, |
@@ -2174,9 +2258,9 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
2174 | if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) && | 2258 | if ((fail_count < IWL_MVM_RS_RATE_MIN_FAILURE_TH) && |
2175 | (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) { | 2259 | (window->success_counter < IWL_MVM_RS_RATE_MIN_SUCCESS_TH)) { |
2176 | IWL_DEBUG_RATE(mvm, | 2260 | IWL_DEBUG_RATE(mvm, |
2177 | "(%s: %d): Test Window: succ %d total %d\n", | 2261 | "%s: Test Window: succ %d total %d\n", |
2178 | rs_pretty_lq_type(rate->type), | 2262 | rs_pretty_rate(rate), |
2179 | index, window->success_counter, window->counter); | 2263 | window->success_counter, window->counter); |
2180 | 2264 | ||
2181 | /* Can't calculate this yet; not enough history */ | 2265 | /* Can't calculate this yet; not enough history */ |
2182 | window->average_tpt = IWL_INVALID_VALUE; | 2266 | window->average_tpt = IWL_INVALID_VALUE; |
@@ -2253,8 +2337,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, | |||
2253 | high_tpt = tbl->win[high].average_tpt; | 2337 | high_tpt = tbl->win[high].average_tpt; |
2254 | 2338 | ||
2255 | IWL_DEBUG_RATE(mvm, | 2339 | IWL_DEBUG_RATE(mvm, |
2256 | "(%s: %d): cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", | 2340 | "%s: cur_tpt %d SR %d low %d high %d low_tpt %d high_tpt %d\n", |
2257 | rs_pretty_lq_type(rate->type), index, current_tpt, sr, | 2341 | rs_pretty_rate(rate), current_tpt, sr, |
2258 | low, high, low_tpt, high_tpt); | 2342 | low, high, low_tpt, high_tpt); |
2259 | 2343 | ||
2260 | scale_action = rs_get_rate_action(mvm, tbl, sr, low, high, | 2344 | scale_action = rs_get_rate_action(mvm, tbl, sr, low, high, |
@@ -2305,6 +2389,8 @@ lq_update: | |||
2305 | /* Replace uCode's rate table for the destination station. */ | 2389 | /* Replace uCode's rate table for the destination station. */ |
2306 | if (update_lq) { | 2390 | if (update_lq) { |
2307 | tbl->rate.index = index; | 2391 | tbl->rate.index = index; |
2392 | if (IWL_MVM_RS_80_20_FAR_RANGE_TWEAK) | ||
2393 | rs_tweak_rate_tbl(mvm, sta, lq_sta, tbl, scale_action); | ||
2308 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl); | 2394 | rs_update_rate_tbl(mvm, sta, lq_sta, tbl); |
2309 | } | 2395 | } |
2310 | 2396 | ||
@@ -2542,7 +2628,6 @@ static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm, | |||
2542 | } | 2628 | } |
2543 | } | 2629 | } |
2544 | 2630 | ||
2545 | rs_dump_rate(mvm, rate, "OPTIMAL RATE"); | ||
2546 | return rate; | 2631 | return rate; |
2547 | } | 2632 | } |
2548 | 2633 | ||
@@ -2983,9 +3068,6 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2983 | else | 3068 | else |
2984 | rs_vht_init(mvm, sta, lq_sta, vht_cap); | 3069 | rs_vht_init(mvm, sta, lq_sta, vht_cap); |
2985 | 3070 | ||
2986 | if (IWL_MVM_RS_DISABLE_P2P_MIMO && sta_priv->vif->p2p) | ||
2987 | lq_sta->active_mimo2_rate = 0; | ||
2988 | |||
2989 | lq_sta->max_legacy_rate_idx = | 3071 | lq_sta->max_legacy_rate_idx = |
2990 | rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); | 3072 | rs_get_max_rate_from_mask(lq_sta->active_legacy_rate); |
2991 | lq_sta->max_siso_rate_idx = | 3073 | lq_sta->max_siso_rate_idx = |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index c37c10a423ce..5b58f5320e8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -202,7 +202,6 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, | |||
202 | return -1; | 202 | return -1; |
203 | 203 | ||
204 | stats->flag |= RX_FLAG_DECRYPTED; | 204 | stats->flag |= RX_FLAG_DECRYPTED; |
205 | IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n"); | ||
206 | *crypt_len = IEEE80211_CCMP_HDR_LEN; | 205 | *crypt_len = IEEE80211_CCMP_HDR_LEN; |
207 | return 0; | 206 | return 0; |
208 | 207 | ||
@@ -299,13 +298,6 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
299 | return; | 298 | return; |
300 | } | 299 | } |
301 | 300 | ||
302 | if ((unlikely(phy_info->cfg_phy_cnt > 20))) { | ||
303 | IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n", | ||
304 | phy_info->cfg_phy_cnt); | ||
305 | kfree_skb(skb); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | /* | 301 | /* |
310 | * Keep packets with CRC errors (and with overrun) for monitor mode | 302 | * Keep packets with CRC errors (and with overrun) for monitor mode |
311 | * (otherwise the firmware discards them) but mark them as bad. | 303 | * (otherwise the firmware discards them) but mark them as bad. |
@@ -354,8 +346,8 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi, | |||
354 | /* This is fine since we don't support multiple AP interfaces */ | 346 | /* This is fine since we don't support multiple AP interfaces */ |
355 | sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL); | 347 | sta = ieee80211_find_sta_by_ifaddr(mvm->hw, hdr->addr2, NULL); |
356 | if (sta) { | 348 | if (sta) { |
357 | struct iwl_mvm_sta *mvmsta; | 349 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
358 | mvmsta = iwl_mvm_sta_from_mac80211(sta); | 350 | |
359 | rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status); | 351 | rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status); |
360 | 352 | ||
361 | if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) && | 353 | if (iwl_fw_dbg_trigger_enabled(mvm->fw, FW_DBG_TRIGGER_RSSI) && |
@@ -459,7 +451,7 @@ static void iwl_mvm_update_rx_statistics(struct iwl_mvm *mvm, | |||
459 | struct iwl_mvm_stat_data { | 451 | struct iwl_mvm_stat_data { |
460 | struct iwl_mvm *mvm; | 452 | struct iwl_mvm *mvm; |
461 | __le32 mac_id; | 453 | __le32 mac_id; |
462 | __s8 beacon_filter_average_energy; | 454 | u8 beacon_filter_average_energy; |
463 | struct mvm_statistics_general_v8 *general; | 455 | struct mvm_statistics_general_v8 *general; |
464 | }; | 456 | }; |
465 | 457 | ||
@@ -577,56 +569,33 @@ iwl_mvm_rx_stats_check_trigger(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) | |||
577 | void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, | 569 | void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm, |
578 | struct iwl_rx_packet *pkt) | 570 | struct iwl_rx_packet *pkt) |
579 | { | 571 | { |
580 | size_t v8_len = sizeof(struct iwl_notif_statistics_v8); | 572 | struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data; |
581 | size_t v10_len = sizeof(struct iwl_notif_statistics_v10); | ||
582 | struct iwl_mvm_stat_data data = { | 573 | struct iwl_mvm_stat_data data = { |
583 | .mvm = mvm, | 574 | .mvm = mvm, |
584 | }; | 575 | }; |
585 | u32 temperature; | 576 | u32 temperature; |
586 | 577 | ||
587 | if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STATS_V10)) { | 578 | if (iwl_rx_packet_payload_len(pkt) != sizeof(*stats)) |
588 | struct iwl_notif_statistics_v10 *stats = (void *)&pkt->data; | 579 | goto invalid; |
589 | |||
590 | if (iwl_rx_packet_payload_len(pkt) != v10_len) | ||
591 | goto invalid; | ||
592 | 580 | ||
593 | temperature = le32_to_cpu(stats->general.radio_temperature); | 581 | temperature = le32_to_cpu(stats->general.radio_temperature); |
594 | data.mac_id = stats->rx.general.mac_id; | 582 | data.mac_id = stats->rx.general.mac_id; |
595 | data.beacon_filter_average_energy = | 583 | data.beacon_filter_average_energy = |
596 | stats->general.beacon_filter_average_energy; | 584 | stats->general.beacon_filter_average_energy; |
597 | 585 | ||
598 | iwl_mvm_update_rx_statistics(mvm, &stats->rx); | 586 | iwl_mvm_update_rx_statistics(mvm, &stats->rx); |
599 | 587 | ||
600 | mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time); | 588 | mvm->radio_stats.rx_time = le64_to_cpu(stats->general.rx_time); |
601 | mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time); | 589 | mvm->radio_stats.tx_time = le64_to_cpu(stats->general.tx_time); |
602 | mvm->radio_stats.on_time_rf = | 590 | mvm->radio_stats.on_time_rf = |
603 | le64_to_cpu(stats->general.on_time_rf); | 591 | le64_to_cpu(stats->general.on_time_rf); |
604 | mvm->radio_stats.on_time_scan = | 592 | mvm->radio_stats.on_time_scan = |
605 | le64_to_cpu(stats->general.on_time_scan); | 593 | le64_to_cpu(stats->general.on_time_scan); |
606 | 594 | ||
607 | data.general = &stats->general; | 595 | data.general = &stats->general; |
608 | } else { | ||
609 | struct iwl_notif_statistics_v8 *stats = (void *)&pkt->data; | ||
610 | |||
611 | if (iwl_rx_packet_payload_len(pkt) != v8_len) | ||
612 | goto invalid; | ||
613 | |||
614 | temperature = le32_to_cpu(stats->general.radio_temperature); | ||
615 | data.mac_id = stats->rx.general.mac_id; | ||
616 | data.beacon_filter_average_energy = | ||
617 | stats->general.beacon_filter_average_energy; | ||
618 | |||
619 | iwl_mvm_update_rx_statistics(mvm, &stats->rx); | ||
620 | } | ||
621 | 596 | ||
622 | iwl_mvm_rx_stats_check_trigger(mvm, pkt); | 597 | iwl_mvm_rx_stats_check_trigger(mvm, pkt); |
623 | 598 | ||
624 | /* Only handle rx statistics temperature changes if async temp | ||
625 | * notifications are not supported | ||
626 | */ | ||
627 | if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_ASYNC_DTM)) | ||
628 | iwl_mvm_tt_temp_changed(mvm, temperature); | ||
629 | |||
630 | ieee80211_iterate_active_interfaces(mvm->hw, | 599 | ieee80211_iterate_active_interfaces(mvm->hw, |
631 | IEEE80211_IFACE_ITER_NORMAL, | 600 | IEEE80211_IFACE_ITER_NORMAL, |
632 | iwl_mvm_stat_iterator, | 601 | iwl_mvm_stat_iterator, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 56559d4d34ad..d6e0c1b5c20c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -131,7 +131,6 @@ struct iwl_mvm_scan_params { | |||
131 | int n_ssids; | 131 | int n_ssids; |
132 | struct cfg80211_ssid *ssids; | 132 | struct cfg80211_ssid *ssids; |
133 | struct ieee80211_channel **channels; | 133 | struct ieee80211_channel **channels; |
134 | u16 interval; /* interval between scans (in secs) */ | ||
135 | u32 flags; | 134 | u32 flags; |
136 | u8 *mac_addr; | 135 | u8 *mac_addr; |
137 | u8 *mac_addr_mask; | 136 | u8 *mac_addr_mask; |
@@ -140,7 +139,8 @@ struct iwl_mvm_scan_params { | |||
140 | int n_match_sets; | 139 | int n_match_sets; |
141 | struct iwl_scan_probe_req preq; | 140 | struct iwl_scan_probe_req preq; |
142 | struct cfg80211_match_set *match_sets; | 141 | struct cfg80211_match_set *match_sets; |
143 | u8 iterations[2]; | 142 | int n_scan_plans; |
143 | struct cfg80211_sched_scan_plan *scan_plans; | ||
144 | }; | 144 | }; |
145 | 145 | ||
146 | static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) | 146 | static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) |
@@ -474,7 +474,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | |||
474 | int ret; | 474 | int ret; |
475 | 475 | ||
476 | if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) | 476 | if (WARN_ON(req->n_match_sets > IWL_SCAN_MAX_PROFILES)) |
477 | return -EIO; | 477 | return -EIO; |
478 | 478 | ||
479 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) | 479 | if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_SHORT_BL) |
480 | blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; | 480 | blacklist_len = IWL_SCAN_SHORT_BLACKLIST_LEN; |
@@ -737,8 +737,7 @@ static inline bool iwl_mvm_scan_fits(struct iwl_mvm *mvm, int n_ssids, | |||
737 | } | 737 | } |
738 | 738 | ||
739 | static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, | 739 | static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, |
740 | struct ieee80211_vif *vif, | 740 | struct ieee80211_vif *vif) |
741 | int n_iterations) | ||
742 | { | 741 | { |
743 | const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; | 742 | const struct iwl_ucode_capabilities *capa = &mvm->fw->ucode_capa; |
744 | 743 | ||
@@ -750,16 +749,9 @@ static inline bool iwl_mvm_scan_use_ebs(struct iwl_mvm *mvm, | |||
750 | */ | 749 | */ |
751 | return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) && | 750 | return ((capa->flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT) && |
752 | mvm->last_ebs_successful && | 751 | mvm->last_ebs_successful && |
753 | (n_iterations > 1 || | ||
754 | fw_has_api(capa, IWL_UCODE_TLV_API_SINGLE_SCAN_EBS)) && | ||
755 | vif->type != NL80211_IFTYPE_P2P_DEVICE); | 752 | vif->type != NL80211_IFTYPE_P2P_DEVICE); |
756 | } | 753 | } |
757 | 754 | ||
758 | static int iwl_mvm_scan_total_iterations(struct iwl_mvm_scan_params *params) | ||
759 | { | ||
760 | return params->iterations[0] + params->iterations[1]; | ||
761 | } | ||
762 | |||
763 | static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, | 755 | static int iwl_mvm_scan_lmac_flags(struct iwl_mvm *mvm, |
764 | struct iwl_mvm_scan_params *params) | 756 | struct iwl_mvm_scan_params *params) |
765 | { | 757 | { |
@@ -798,12 +790,15 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
798 | (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * | 790 | (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) * |
799 | mvm->fw->ucode_capa.n_scan_channels); | 791 | mvm->fw->ucode_capa.n_scan_channels); |
800 | u32 ssid_bitmap = 0; | 792 | u32 ssid_bitmap = 0; |
801 | int n_iterations = iwl_mvm_scan_total_iterations(params); | 793 | int i; |
802 | 794 | ||
803 | lockdep_assert_held(&mvm->mutex); | 795 | lockdep_assert_held(&mvm->mutex); |
804 | 796 | ||
805 | memset(cmd, 0, ksize(cmd)); | 797 | memset(cmd, 0, ksize(cmd)); |
806 | 798 | ||
799 | if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) | ||
800 | return -EINVAL; | ||
801 | |||
807 | iwl_mvm_scan_lmac_dwell(mvm, cmd, params); | 802 | iwl_mvm_scan_lmac_dwell(mvm, cmd, params); |
808 | 803 | ||
809 | cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm); | 804 | cmd->rx_chain_select = iwl_mvm_scan_rx_chain(mvm); |
@@ -823,14 +818,26 @@ static int iwl_mvm_scan_lmac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
823 | /* this API uses bits 1-20 instead of 0-19 */ | 818 | /* this API uses bits 1-20 instead of 0-19 */ |
824 | ssid_bitmap <<= 1; | 819 | ssid_bitmap <<= 1; |
825 | 820 | ||
826 | cmd->schedule[0].delay = cpu_to_le16(params->interval); | 821 | for (i = 0; i < params->n_scan_plans; i++) { |
827 | cmd->schedule[0].iterations = params->iterations[0]; | 822 | struct cfg80211_sched_scan_plan *scan_plan = |
828 | cmd->schedule[0].full_scan_mul = 1; | 823 | ¶ms->scan_plans[i]; |
829 | cmd->schedule[1].delay = cpu_to_le16(params->interval); | 824 | |
830 | cmd->schedule[1].iterations = params->iterations[1]; | 825 | cmd->schedule[i].delay = |
831 | cmd->schedule[1].full_scan_mul = 1; | 826 | cpu_to_le16(scan_plan->interval); |
827 | cmd->schedule[i].iterations = scan_plan->iterations; | ||
828 | cmd->schedule[i].full_scan_mul = 1; | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * If the number of iterations of the last scan plan is set to | ||
833 | * zero, it should run infinitely. However, this is not always the case. | ||
834 | * For example, when regular scan is requested the driver sets one scan | ||
835 | * plan with one iteration. | ||
836 | */ | ||
837 | if (!cmd->schedule[i - 1].iterations) | ||
838 | cmd->schedule[i - 1].iterations = 0xff; | ||
832 | 839 | ||
833 | if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) { | 840 | if (iwl_mvm_scan_use_ebs(mvm, vif)) { |
834 | cmd->channel_opt[0].flags = | 841 | cmd->channel_opt[0].flags = |
835 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | | 842 | cpu_to_le16(IWL_SCAN_CHANNEL_FLAG_EBS | |
836 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | 843 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | |
@@ -894,7 +901,6 @@ static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm) | |||
894 | 901 | ||
895 | int iwl_mvm_config_scan(struct iwl_mvm *mvm) | 902 | int iwl_mvm_config_scan(struct iwl_mvm *mvm) |
896 | { | 903 | { |
897 | |||
898 | struct iwl_scan_config *scan_config; | 904 | struct iwl_scan_config *scan_config; |
899 | struct ieee80211_supported_band *band; | 905 | struct ieee80211_supported_band *band; |
900 | int num_channels = | 906 | int num_channels = |
@@ -970,6 +976,12 @@ static int iwl_mvm_scan_uid_by_status(struct iwl_mvm *mvm, int status) | |||
970 | return -ENOENT; | 976 | return -ENOENT; |
971 | } | 977 | } |
972 | 978 | ||
979 | static inline bool iwl_mvm_is_regular_scan(struct iwl_mvm_scan_params *params) | ||
980 | { | ||
981 | return params->n_scan_plans == 1 && | ||
982 | params->scan_plans[0].iterations == 1; | ||
983 | } | ||
984 | |||
973 | static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, | 985 | static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, |
974 | struct iwl_scan_req_umac *cmd, | 986 | struct iwl_scan_req_umac *cmd, |
975 | struct iwl_mvm_scan_params *params) | 987 | struct iwl_mvm_scan_params *params) |
@@ -982,7 +994,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, | |||
982 | cmd->scan_priority = | 994 | cmd->scan_priority = |
983 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); | 995 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); |
984 | 996 | ||
985 | if (iwl_mvm_scan_total_iterations(params) == 1) | 997 | if (iwl_mvm_is_regular_scan(params)) |
986 | cmd->ooc_priority = | 998 | cmd->ooc_priority = |
987 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); | 999 | iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6); |
988 | else | 1000 | else |
@@ -1029,7 +1041,7 @@ static u32 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, | |||
1029 | else | 1041 | else |
1030 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; | 1042 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH; |
1031 | 1043 | ||
1032 | if (iwl_mvm_scan_total_iterations(params) > 1) | 1044 | if (!iwl_mvm_is_regular_scan(params)) |
1033 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; | 1045 | flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC; |
1034 | 1046 | ||
1035 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 1047 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
@@ -1047,12 +1059,14 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1047 | struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + | 1059 | struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data + |
1048 | sizeof(struct iwl_scan_channel_cfg_umac) * | 1060 | sizeof(struct iwl_scan_channel_cfg_umac) * |
1049 | mvm->fw->ucode_capa.n_scan_channels; | 1061 | mvm->fw->ucode_capa.n_scan_channels; |
1050 | int uid; | 1062 | int uid, i; |
1051 | u32 ssid_bitmap = 0; | 1063 | u32 ssid_bitmap = 0; |
1052 | int n_iterations = iwl_mvm_scan_total_iterations(params); | ||
1053 | 1064 | ||
1054 | lockdep_assert_held(&mvm->mutex); | 1065 | lockdep_assert_held(&mvm->mutex); |
1055 | 1066 | ||
1067 | if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) | ||
1068 | return -EINVAL; | ||
1069 | |||
1056 | uid = iwl_mvm_scan_uid_by_status(mvm, 0); | 1070 | uid = iwl_mvm_scan_uid_by_status(mvm, 0); |
1057 | if (uid < 0) | 1071 | if (uid < 0) |
1058 | return uid; | 1072 | return uid; |
@@ -1069,7 +1083,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1069 | if (type == IWL_MVM_SCAN_SCHED) | 1083 | if (type == IWL_MVM_SCAN_SCHED) |
1070 | cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); | 1084 | cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE); |
1071 | 1085 | ||
1072 | if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations)) | 1086 | if (iwl_mvm_scan_use_ebs(mvm, vif)) |
1073 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | | 1087 | cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS | |
1074 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | | 1088 | IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | |
1075 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; | 1089 | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; |
@@ -1081,12 +1095,23 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1081 | iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, | 1095 | iwl_mvm_umac_scan_cfg_channels(mvm, params->channels, |
1082 | params->n_channels, ssid_bitmap, cmd); | 1096 | params->n_channels, ssid_bitmap, cmd); |
1083 | 1097 | ||
1084 | /* With UMAC we use only one schedule for now, so use the sum | 1098 | for (i = 0; i < params->n_scan_plans; i++) { |
1085 | * of the iterations (with a a maximum of 255). | 1099 | struct cfg80211_sched_scan_plan *scan_plan = |
1100 | ¶ms->scan_plans[i]; | ||
1101 | |||
1102 | sec_part->schedule[i].iter_count = scan_plan->iterations; | ||
1103 | sec_part->schedule[i].interval = | ||
1104 | cpu_to_le16(scan_plan->interval); | ||
1105 | } | ||
1106 | |||
1107 | /* | ||
1108 | * If the number of iterations of the last scan plan is set to | ||
1109 | * zero, it should run infinitely. However, this is not always the case. | ||
1110 | * For example, when regular scan is requested the driver sets one scan | ||
1111 | * plan with one iteration. | ||
1086 | */ | 1112 | */ |
1087 | sec_part->schedule[0].iter_count = | 1113 | if (!sec_part->schedule[i - 1].iter_count) |
1088 | (n_iterations > 255) ? 255 : n_iterations; | 1114 | sec_part->schedule[i - 1].iter_count = 0xff; |
1089 | sec_part->schedule[0].interval = cpu_to_le16(params->interval); | ||
1090 | 1115 | ||
1091 | sec_part->delay = cpu_to_le16(params->delay); | 1116 | sec_part->delay = cpu_to_le16(params->delay); |
1092 | sec_part->preq = params->preq; | 1117 | sec_part->preq = params->preq; |
@@ -1152,6 +1177,7 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1152 | }; | 1177 | }; |
1153 | struct iwl_mvm_scan_params params = {}; | 1178 | struct iwl_mvm_scan_params params = {}; |
1154 | int ret; | 1179 | int ret; |
1180 | struct cfg80211_sched_scan_plan scan_plan = { .iterations = 1 }; | ||
1155 | 1181 | ||
1156 | lockdep_assert_held(&mvm->mutex); | 1182 | lockdep_assert_held(&mvm->mutex); |
1157 | 1183 | ||
@@ -1164,8 +1190,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1164 | if (ret) | 1190 | if (ret) |
1165 | return ret; | 1191 | return ret; |
1166 | 1192 | ||
1167 | iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); | ||
1168 | |||
1169 | /* we should have failed registration if scan_cmd was NULL */ | 1193 | /* we should have failed registration if scan_cmd was NULL */ |
1170 | if (WARN_ON(!mvm->scan_cmd)) | 1194 | if (WARN_ON(!mvm->scan_cmd)) |
1171 | return -ENOMEM; | 1195 | return -ENOMEM; |
@@ -1177,7 +1201,6 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1177 | params.flags = req->flags; | 1201 | params.flags = req->flags; |
1178 | params.n_channels = req->n_channels; | 1202 | params.n_channels = req->n_channels; |
1179 | params.delay = 0; | 1203 | params.delay = 0; |
1180 | params.interval = 0; | ||
1181 | params.ssids = req->ssids; | 1204 | params.ssids = req->ssids; |
1182 | params.channels = req->channels; | 1205 | params.channels = req->channels; |
1183 | params.mac_addr = req->mac_addr; | 1206 | params.mac_addr = req->mac_addr; |
@@ -1187,8 +1210,8 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1187 | params.n_match_sets = 0; | 1210 | params.n_match_sets = 0; |
1188 | params.match_sets = NULL; | 1211 | params.match_sets = NULL; |
1189 | 1212 | ||
1190 | params.iterations[0] = 1; | 1213 | params.scan_plans = &scan_plan; |
1191 | params.iterations[1] = 0; | 1214 | params.n_scan_plans = 1; |
1192 | 1215 | ||
1193 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); | 1216 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); |
1194 | 1217 | ||
@@ -1207,21 +1230,20 @@ int iwl_mvm_reg_scan_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1207 | return ret; | 1230 | return ret; |
1208 | 1231 | ||
1209 | ret = iwl_mvm_send_cmd(mvm, &hcmd); | 1232 | ret = iwl_mvm_send_cmd(mvm, &hcmd); |
1210 | if (!ret) { | 1233 | if (ret) { |
1211 | IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); | ||
1212 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; | ||
1213 | } else { | ||
1214 | /* If the scan failed, it usually means that the FW was unable | 1234 | /* If the scan failed, it usually means that the FW was unable |
1215 | * to allocate the time events. Warn on it, but maybe we | 1235 | * to allocate the time events. Warn on it, but maybe we |
1216 | * should try to send the command again with different params. | 1236 | * should try to send the command again with different params. |
1217 | */ | 1237 | */ |
1218 | IWL_ERR(mvm, "Scan failed! ret %d\n", ret); | 1238 | IWL_ERR(mvm, "Scan failed! ret %d\n", ret); |
1239 | return ret; | ||
1219 | } | 1240 | } |
1220 | 1241 | ||
1221 | if (ret) | 1242 | IWL_DEBUG_SCAN(mvm, "Scan request was sent successfully\n"); |
1222 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | 1243 | mvm->scan_status |= IWL_MVM_SCAN_REGULAR; |
1244 | iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN); | ||
1223 | 1245 | ||
1224 | return ret; | 1246 | return 0; |
1225 | } | 1247 | } |
1226 | 1248 | ||
1227 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | 1249 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, |
@@ -1267,20 +1289,14 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
1267 | params.pass_all = iwl_mvm_scan_pass_all(mvm, req); | 1289 | params.pass_all = iwl_mvm_scan_pass_all(mvm, req); |
1268 | params.n_match_sets = req->n_match_sets; | 1290 | params.n_match_sets = req->n_match_sets; |
1269 | params.match_sets = req->match_sets; | 1291 | params.match_sets = req->match_sets; |
1292 | if (!req->n_scan_plans) | ||
1293 | return -EINVAL; | ||
1270 | 1294 | ||
1271 | params.iterations[0] = 0; | 1295 | params.n_scan_plans = req->n_scan_plans; |
1272 | params.iterations[1] = 0xff; | 1296 | params.scan_plans = req->scan_plans; |
1273 | 1297 | ||
1274 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); | 1298 | params.type = iwl_mvm_get_scan_type(mvm, vif, ¶ms); |
1275 | 1299 | ||
1276 | if (req->interval > U16_MAX) { | ||
1277 | IWL_DEBUG_SCAN(mvm, | ||
1278 | "interval value is > 16-bits, set to max possible\n"); | ||
1279 | params.interval = U16_MAX; | ||
1280 | } else { | ||
1281 | params.interval = req->interval / MSEC_PER_SEC; | ||
1282 | } | ||
1283 | |||
1284 | /* In theory, LMAC scans can handle a 32-bit delay, but since | 1300 | /* In theory, LMAC scans can handle a 32-bit delay, but since |
1285 | * waiting for over 18 hours to start the scan is a bit silly | 1301 | * waiting for over 18 hours to start the scan is a bit silly |
1286 | * and to keep it aligned with UMAC scans (which only support | 1302 | * and to keep it aligned with UMAC scans (which only support |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index df216cd0c98f..300a249486e4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -234,7 +234,9 @@ static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm, | |||
234 | /* Found a place for all queues - enable them */ | 234 | /* Found a place for all queues - enable them */ |
235 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 235 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
236 | iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], | 236 | iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac], |
237 | iwl_mvm_ac_to_tx_fifo[ac], wdg_timeout); | 237 | mvmsta->hw_queue[ac], |
238 | iwl_mvm_ac_to_tx_fifo[ac], 0, | ||
239 | wdg_timeout); | ||
238 | mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); | 240 | mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]); |
239 | } | 241 | } |
240 | 242 | ||
@@ -253,7 +255,7 @@ static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm, | |||
253 | /* disable the TDLS STA-specific queues */ | 255 | /* disable the TDLS STA-specific queues */ |
254 | sta_msk = mvmsta->tfd_queue_msk; | 256 | sta_msk = mvmsta->tfd_queue_msk; |
255 | for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) | 257 | for_each_set_bit(i, &sta_msk, sizeof(sta_msk) * BITS_PER_BYTE) |
256 | iwl_mvm_disable_txq(mvm, i, 0); | 258 | iwl_mvm_disable_txq(mvm, i, i, IWL_MAX_TID_COUNT, 0); |
257 | } | 259 | } |
258 | 260 | ||
259 | int iwl_mvm_add_sta(struct iwl_mvm *mvm, | 261 | int iwl_mvm_add_sta(struct iwl_mvm *mvm, |
@@ -275,6 +277,11 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
275 | if (sta_id == IWL_MVM_STATION_COUNT) | 277 | if (sta_id == IWL_MVM_STATION_COUNT) |
276 | return -ENOSPC; | 278 | return -ENOSPC; |
277 | 279 | ||
280 | if (vif->type == NL80211_IFTYPE_AP) { | ||
281 | mvmvif->ap_assoc_sta_count++; | ||
282 | iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL); | ||
283 | } | ||
284 | |||
278 | spin_lock_init(&mvm_sta->lock); | 285 | spin_lock_init(&mvm_sta->lock); |
279 | 286 | ||
280 | mvm_sta->sta_id = sta_id; | 287 | mvm_sta->sta_id = sta_id; |
@@ -287,7 +294,7 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm, | |||
287 | 294 | ||
288 | /* HW restart, don't assume the memory has been zeroed */ | 295 | /* HW restart, don't assume the memory has been zeroed */ |
289 | atomic_set(&mvm->pending_frames[sta_id], 0); | 296 | atomic_set(&mvm->pending_frames[sta_id], 0); |
290 | mvm_sta->tid_disable_agg = 0; | 297 | mvm_sta->tid_disable_agg = 0xffff; /* No aggs at first */ |
291 | mvm_sta->tfd_queue_msk = 0; | 298 | mvm_sta->tfd_queue_msk = 0; |
292 | 299 | ||
293 | /* allocate new queues for a TDLS station */ | 300 | /* allocate new queues for a TDLS station */ |
@@ -467,7 +474,8 @@ void iwl_mvm_sta_drained_wk(struct work_struct *wk) | |||
467 | unsigned long i, msk = mvm->tfd_drained[sta_id]; | 474 | unsigned long i, msk = mvm->tfd_drained[sta_id]; |
468 | 475 | ||
469 | for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) | 476 | for_each_set_bit(i, &msk, sizeof(msk) * BITS_PER_BYTE) |
470 | iwl_mvm_disable_txq(mvm, i, 0); | 477 | iwl_mvm_disable_txq(mvm, i, i, |
478 | IWL_MAX_TID_COUNT, 0); | ||
471 | 479 | ||
472 | mvm->tfd_drained[sta_id] = 0; | 480 | mvm->tfd_drained[sta_id] = 0; |
473 | IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", | 481 | IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n", |
@@ -494,7 +502,7 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm, | |||
494 | if (ret) | 502 | if (ret) |
495 | return ret; | 503 | return ret; |
496 | /* flush its queues here since we are freeing mvm_sta */ | 504 | /* flush its queues here since we are freeing mvm_sta */ |
497 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true); | 505 | ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, 0); |
498 | if (ret) | 506 | if (ret) |
499 | return ret; | 507 | return ret; |
500 | ret = iwl_trans_wait_tx_queue_empty(mvm->trans, | 508 | ret = iwl_trans_wait_tx_queue_empty(mvm->trans, |
@@ -646,8 +654,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm) | |||
646 | lockdep_assert_held(&mvm->mutex); | 654 | lockdep_assert_held(&mvm->mutex); |
647 | 655 | ||
648 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ | 656 | /* Map Aux queue to fifo - needs to happen before adding Aux station */ |
649 | iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, | 657 | iwl_mvm_enable_ac_txq(mvm, mvm->aux_queue, mvm->aux_queue, |
650 | IWL_MVM_TX_FIFO_MCAST, wdg_timeout); | 658 | IWL_MVM_TX_FIFO_MCAST, 0, wdg_timeout); |
651 | 659 | ||
652 | /* Allocate aux station and assign to it the aux queue */ | 660 | /* Allocate aux station and assign to it the aux queue */ |
653 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), | 661 | ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue), |
@@ -918,6 +926,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
918 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | 926 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); |
919 | struct iwl_mvm_tid_data *tid_data; | 927 | struct iwl_mvm_tid_data *tid_data; |
920 | int txq_id; | 928 | int txq_id; |
929 | int ret; | ||
921 | 930 | ||
922 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) | 931 | if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) |
923 | return -EINVAL; | 932 | return -EINVAL; |
@@ -930,17 +939,6 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
930 | 939 | ||
931 | lockdep_assert_held(&mvm->mutex); | 940 | lockdep_assert_held(&mvm->mutex); |
932 | 941 | ||
933 | for (txq_id = mvm->first_agg_queue; | ||
934 | txq_id <= mvm->last_agg_queue; txq_id++) | ||
935 | if (mvm->queue_to_mac80211[txq_id] == | ||
936 | IWL_INVALID_MAC80211_QUEUE) | ||
937 | break; | ||
938 | |||
939 | if (txq_id > mvm->last_agg_queue) { | ||
940 | IWL_ERR(mvm, "Failed to allocate agg queue\n"); | ||
941 | return -EIO; | ||
942 | } | ||
943 | |||
944 | spin_lock_bh(&mvmsta->lock); | 942 | spin_lock_bh(&mvmsta->lock); |
945 | 943 | ||
946 | /* possible race condition - we entered D0i3 while starting agg */ | 944 | /* possible race condition - we entered D0i3 while starting agg */ |
@@ -950,8 +948,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
950 | return -EIO; | 948 | return -EIO; |
951 | } | 949 | } |
952 | 950 | ||
953 | /* the new tx queue is still connected to the same mac80211 queue */ | 951 | spin_lock_bh(&mvm->queue_info_lock); |
954 | mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]]; | 952 | |
953 | txq_id = iwl_mvm_find_free_queue(mvm, mvm->first_agg_queue, | ||
954 | mvm->last_agg_queue); | ||
955 | if (txq_id < 0) { | ||
956 | ret = txq_id; | ||
957 | spin_unlock_bh(&mvm->queue_info_lock); | ||
958 | IWL_ERR(mvm, "Failed to allocate agg queue\n"); | ||
959 | goto release_locks; | ||
960 | } | ||
961 | mvm->queue_info[txq_id].setup_reserved = true; | ||
962 | spin_unlock_bh(&mvm->queue_info_lock); | ||
955 | 963 | ||
956 | tid_data = &mvmsta->tid_data[tid]; | 964 | tid_data = &mvmsta->tid_data[tid]; |
957 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); | 965 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
@@ -970,9 +978,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
970 | tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA; | 978 | tid_data->state = IWL_EMPTYING_HW_QUEUE_ADDBA; |
971 | } | 979 | } |
972 | 980 | ||
981 | ret = 0; | ||
982 | |||
983 | release_locks: | ||
973 | spin_unlock_bh(&mvmsta->lock); | 984 | spin_unlock_bh(&mvmsta->lock); |
974 | 985 | ||
975 | return 0; | 986 | return ret; |
976 | } | 987 | } |
977 | 988 | ||
978 | int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 989 | int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
@@ -1000,13 +1011,19 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1000 | 1011 | ||
1001 | fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; | 1012 | fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]]; |
1002 | 1013 | ||
1003 | iwl_mvm_enable_agg_txq(mvm, queue, fifo, mvmsta->sta_id, tid, | 1014 | iwl_mvm_enable_agg_txq(mvm, queue, |
1004 | buf_size, ssn, wdg_timeout); | 1015 | vif->hw_queue[tid_to_mac80211_ac[tid]], fifo, |
1016 | mvmsta->sta_id, tid, buf_size, ssn, wdg_timeout); | ||
1005 | 1017 | ||
1006 | ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); | 1018 | ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); |
1007 | if (ret) | 1019 | if (ret) |
1008 | return -EIO; | 1020 | return -EIO; |
1009 | 1021 | ||
1022 | /* No need to mark as reserved */ | ||
1023 | spin_lock_bh(&mvm->queue_info_lock); | ||
1024 | mvm->queue_info[queue].setup_reserved = false; | ||
1025 | spin_unlock_bh(&mvm->queue_info_lock); | ||
1026 | |||
1010 | /* | 1027 | /* |
1011 | * Even though in theory the peer could have different | 1028 | * Even though in theory the peer could have different |
1012 | * aggregation reorder buffer sizes for different sessions, | 1029 | * aggregation reorder buffer sizes for different sessions, |
@@ -1051,6 +1068,11 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1051 | 1068 | ||
1052 | mvmsta->agg_tids &= ~BIT(tid); | 1069 | mvmsta->agg_tids &= ~BIT(tid); |
1053 | 1070 | ||
1071 | /* No need to mark as reserved anymore */ | ||
1072 | spin_lock_bh(&mvm->queue_info_lock); | ||
1073 | mvm->queue_info[txq_id].setup_reserved = false; | ||
1074 | spin_unlock_bh(&mvm->queue_info_lock); | ||
1075 | |||
1054 | switch (tid_data->state) { | 1076 | switch (tid_data->state) { |
1055 | case IWL_AGG_ON: | 1077 | case IWL_AGG_ON: |
1056 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); | 1078 | tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); |
@@ -1068,14 +1090,15 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1068 | 1090 | ||
1069 | tid_data->ssn = 0xffff; | 1091 | tid_data->ssn = 0xffff; |
1070 | tid_data->state = IWL_AGG_OFF; | 1092 | tid_data->state = IWL_AGG_OFF; |
1071 | mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE; | ||
1072 | spin_unlock_bh(&mvmsta->lock); | 1093 | spin_unlock_bh(&mvmsta->lock); |
1073 | 1094 | ||
1074 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1095 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1075 | 1096 | ||
1076 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); | 1097 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); |
1077 | 1098 | ||
1078 | iwl_mvm_disable_txq(mvm, txq_id, 0); | 1099 | iwl_mvm_disable_txq(mvm, txq_id, |
1100 | vif->hw_queue[tid_to_mac80211_ac[tid]], tid, | ||
1101 | 0); | ||
1079 | return 0; | 1102 | return 0; |
1080 | case IWL_AGG_STARTING: | 1103 | case IWL_AGG_STARTING: |
1081 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 1104 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -1086,7 +1109,6 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1086 | 1109 | ||
1087 | /* No barriers since we are under mutex */ | 1110 | /* No barriers since we are under mutex */ |
1088 | lockdep_assert_held(&mvm->mutex); | 1111 | lockdep_assert_held(&mvm->mutex); |
1089 | mvm->queue_to_mac80211[txq_id] = IWL_INVALID_MAC80211_QUEUE; | ||
1090 | 1112 | ||
1091 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 1113 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
1092 | tid_data->state = IWL_AGG_OFF; | 1114 | tid_data->state = IWL_AGG_OFF; |
@@ -1127,9 +1149,14 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1127 | mvmsta->agg_tids &= ~BIT(tid); | 1149 | mvmsta->agg_tids &= ~BIT(tid); |
1128 | spin_unlock_bh(&mvmsta->lock); | 1150 | spin_unlock_bh(&mvmsta->lock); |
1129 | 1151 | ||
1152 | /* No need to mark as reserved */ | ||
1153 | spin_lock_bh(&mvm->queue_info_lock); | ||
1154 | mvm->queue_info[txq_id].setup_reserved = false; | ||
1155 | spin_unlock_bh(&mvm->queue_info_lock); | ||
1156 | |||
1130 | if (old_state >= IWL_AGG_ON) { | 1157 | if (old_state >= IWL_AGG_ON) { |
1131 | iwl_mvm_drain_sta(mvm, mvmsta, true); | 1158 | iwl_mvm_drain_sta(mvm, mvmsta, true); |
1132 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true)) | 1159 | if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), 0)) |
1133 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); | 1160 | IWL_ERR(mvm, "Couldn't flush the AGG queue\n"); |
1134 | iwl_trans_wait_tx_queue_empty(mvm->trans, | 1161 | iwl_trans_wait_tx_queue_empty(mvm->trans, |
1135 | mvmsta->tfd_queue_msk); | 1162 | mvmsta->tfd_queue_msk); |
@@ -1137,12 +1164,11 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1137 | 1164 | ||
1138 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); | 1165 | iwl_mvm_sta_tx_agg(mvm, sta, tid, txq_id, false); |
1139 | 1166 | ||
1140 | iwl_mvm_disable_txq(mvm, tid_data->txq_id, 0); | 1167 | iwl_mvm_disable_txq(mvm, tid_data->txq_id, |
1168 | vif->hw_queue[tid_to_mac80211_ac[tid]], tid, | ||
1169 | 0); | ||
1141 | } | 1170 | } |
1142 | 1171 | ||
1143 | mvm->queue_to_mac80211[tid_data->txq_id] = | ||
1144 | IWL_INVALID_MAC80211_QUEUE; | ||
1145 | |||
1146 | return 0; | 1172 | return 0; |
1147 | } | 1173 | } |
1148 | 1174 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c index dbd7d544575d..7530eb23035d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c | |||
@@ -129,7 +129,7 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk) | |||
129 | * issue as it will have to complete before the next command is | 129 | * issue as it will have to complete before the next command is |
130 | * executed, and a new time event means a new command. | 130 | * executed, and a new time event means a new command. |
131 | */ | 131 | */ |
132 | iwl_mvm_flush_tx_path(mvm, queues, false); | 132 | iwl_mvm_flush_tx_path(mvm, queues, CMD_ASYNC); |
133 | } | 133 | } |
134 | 134 | ||
135 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) | 135 | static void iwl_mvm_roc_finished(struct iwl_mvm *mvm) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.c b/drivers/net/wireless/iwlwifi/mvm/tof.c index 380972f8fb82..4007f1d421dd 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.c +++ b/drivers/net/wireless/iwlwifi/mvm/tof.c | |||
@@ -178,12 +178,14 @@ int iwl_mvm_tof_responder_cmd(struct iwl_mvm *mvm, | |||
178 | if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) | 178 | if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_TOF_SUPPORT)) |
179 | return -EINVAL; | 179 | return -EINVAL; |
180 | 180 | ||
181 | if (vif->p2p || vif->type != NL80211_IFTYPE_AP) { | 181 | if (vif->p2p || vif->type != NL80211_IFTYPE_AP || |
182 | !mvmvif->ap_ibss_active) { | ||
182 | IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); | 183 | IWL_ERR(mvm, "Cannot start responder, not in AP mode\n"); |
183 | return -EIO; | 184 | return -EIO; |
184 | } | 185 | } |
185 | 186 | ||
186 | cmd->sta_id = mvmvif->bcast_sta.sta_id; | 187 | cmd->sta_id = mvmvif->bcast_sta.sta_id; |
188 | memcpy(cmd->bssid, vif->addr, ETH_ALEN); | ||
187 | return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, | 189 | return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_CMD, |
188 | IWL_ALWAYS_LONG_GROUP, 0), | 190 | IWL_ALWAYS_LONG_GROUP, 0), |
189 | 0, sizeof(*cmd), cmd); | 191 | 0, sizeof(*cmd), cmd); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tof.h b/drivers/net/wireless/iwlwifi/mvm/tof.h index 50ae8adaaa6e..9beebc33cb8d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tof.h +++ b/drivers/net/wireless/iwlwifi/mvm/tof.h | |||
@@ -60,7 +60,7 @@ | |||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #ifndef __tof | 63 | #ifndef __tof_h__ |
64 | #define __tof_h__ | 64 | #define __tof_h__ |
65 | 65 | ||
66 | #include "fw-api-tof.h" | 66 | #include "fw-api-tof.h" |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index fe7145c2c98a..cadfc0460597 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -176,17 +176,34 @@ static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm) | |||
176 | struct iwl_dts_measurement_cmd cmd = { | 176 | struct iwl_dts_measurement_cmd cmd = { |
177 | .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), | 177 | .flags = cpu_to_le32(DTS_TRIGGER_CMD_FLAGS_TEMP), |
178 | }; | 178 | }; |
179 | struct iwl_ext_dts_measurement_cmd extcmd = { | ||
180 | .control_mode = cpu_to_le32(DTS_AUTOMATIC), | ||
181 | }; | ||
182 | u32 cmdid; | ||
183 | |||
184 | if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) | ||
185 | cmdid = iwl_cmd_id(CMD_DTS_MEASUREMENT_TRIGGER_WIDE, | ||
186 | PHY_OPS_GROUP, 0); | ||
187 | else | ||
188 | cmdid = CMD_DTS_MEASUREMENT_TRIGGER; | ||
179 | 189 | ||
180 | return iwl_mvm_send_cmd_pdu(mvm, CMD_DTS_MEASUREMENT_TRIGGER, 0, | 190 | if (!fw_has_capa(&mvm->fw->ucode_capa, |
181 | sizeof(cmd), &cmd); | 191 | IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE)) |
192 | return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(cmd), &cmd); | ||
193 | |||
194 | return iwl_mvm_send_cmd_pdu(mvm, cmdid, 0, sizeof(extcmd), &extcmd); | ||
182 | } | 195 | } |
183 | 196 | ||
184 | int iwl_mvm_get_temp(struct iwl_mvm *mvm) | 197 | int iwl_mvm_get_temp(struct iwl_mvm *mvm) |
185 | { | 198 | { |
186 | struct iwl_notification_wait wait_temp_notif; | 199 | struct iwl_notification_wait wait_temp_notif; |
187 | static const u16 temp_notif[] = { DTS_MEASUREMENT_NOTIFICATION }; | 200 | static u16 temp_notif[] = { WIDE_ID(PHY_OPS_GROUP, |
201 | DTS_MEASUREMENT_NOTIF_WIDE) }; | ||
188 | int ret, temp; | 202 | int ret, temp; |
189 | 203 | ||
204 | if (!fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_WIDE_CMD_HDR)) | ||
205 | temp_notif[0] = DTS_MEASUREMENT_NOTIFICATION; | ||
206 | |||
190 | lockdep_assert_held(&mvm->mutex); | 207 | lockdep_assert_held(&mvm->mutex); |
191 | 208 | ||
192 | iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif, | 209 | iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 6df5aada4f16..c652a66be803 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -560,15 +560,10 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, | |||
560 | IWL_DEBUG_TX_QUEUES(mvm, | 560 | IWL_DEBUG_TX_QUEUES(mvm, |
561 | "Can continue DELBA flow ssn = next_recl = %d\n", | 561 | "Can continue DELBA flow ssn = next_recl = %d\n", |
562 | tid_data->next_reclaimed); | 562 | tid_data->next_reclaimed); |
563 | iwl_mvm_disable_txq(mvm, tid_data->txq_id, CMD_ASYNC); | 563 | iwl_mvm_disable_txq(mvm, tid_data->txq_id, |
564 | vif->hw_queue[tid_to_mac80211_ac[tid]], tid, | ||
565 | CMD_ASYNC); | ||
564 | tid_data->state = IWL_AGG_OFF; | 566 | tid_data->state = IWL_AGG_OFF; |
565 | /* | ||
566 | * we can't hold the mutex - but since we are after a sequence | ||
567 | * point (call to iwl_mvm_disable_txq(), so we don't even need | ||
568 | * a memory barrier. | ||
569 | */ | ||
570 | mvm->queue_to_mac80211[tid_data->txq_id] = | ||
571 | IWL_INVALID_MAC80211_QUEUE; | ||
572 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 567 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
573 | break; | 568 | break; |
574 | 569 | ||
@@ -1104,7 +1099,7 @@ out: | |||
1104 | * 2) flush the Tx path | 1099 | * 2) flush the Tx path |
1105 | * 3) wait for the transport queues to be empty | 1100 | * 3) wait for the transport queues to be empty |
1106 | */ | 1101 | */ |
1107 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) | 1102 | int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, u32 flags) |
1108 | { | 1103 | { |
1109 | int ret; | 1104 | int ret; |
1110 | struct iwl_tx_path_flush_cmd flush_cmd = { | 1105 | struct iwl_tx_path_flush_cmd flush_cmd = { |
@@ -1112,8 +1107,6 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync) | |||
1112 | .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), | 1107 | .flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH), |
1113 | }; | 1108 | }; |
1114 | 1109 | ||
1115 | u32 flags = sync ? 0 : CMD_ASYNC; | ||
1116 | |||
1117 | ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, | 1110 | ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags, |
1118 | sizeof(flush_cmd), &flush_cmd); | 1111 | sizeof(flush_cmd), &flush_cmd); |
1119 | if (ret) | 1112 | if (ret) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index a7d434256423..ad0f16909e2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * | 7 | * |
8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. |
9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH |
10 | * Copyright (C) 2015 Intel Deutschland GmbH | ||
10 | * | 11 | * |
11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
@@ -657,45 +658,143 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) | |||
657 | if (mvm->support_umac_log) | 658 | if (mvm->support_umac_log) |
658 | iwl_mvm_dump_umac_error_log(mvm); | 659 | iwl_mvm_dump_umac_error_log(mvm); |
659 | } | 660 | } |
660 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, u16 ssn, | 661 | |
661 | const struct iwl_trans_txq_scd_cfg *cfg, | 662 | int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 minq, u8 maxq) |
663 | { | ||
664 | int i; | ||
665 | |||
666 | lockdep_assert_held(&mvm->queue_info_lock); | ||
667 | |||
668 | for (i = minq; i <= maxq; i++) | ||
669 | if (mvm->queue_info[i].hw_queue_refcount == 0 && | ||
670 | !mvm->queue_info[i].setup_reserved) | ||
671 | return i; | ||
672 | |||
673 | return -ENOSPC; | ||
674 | } | ||
675 | |||
676 | void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, | ||
677 | u16 ssn, const struct iwl_trans_txq_scd_cfg *cfg, | ||
662 | unsigned int wdg_timeout) | 678 | unsigned int wdg_timeout) |
663 | { | 679 | { |
664 | struct iwl_scd_txq_cfg_cmd cmd = { | 680 | bool enable_queue = true; |
665 | .scd_queue = queue, | ||
666 | .enable = 1, | ||
667 | .window = cfg->frame_limit, | ||
668 | .sta_id = cfg->sta_id, | ||
669 | .ssn = cpu_to_le16(ssn), | ||
670 | .tx_fifo = cfg->fifo, | ||
671 | .aggregate = cfg->aggregate, | ||
672 | .tid = cfg->tid, | ||
673 | }; | ||
674 | 681 | ||
675 | if (!iwl_mvm_is_scd_cfg_supported(mvm)) { | 682 | spin_lock_bh(&mvm->queue_info_lock); |
676 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, cfg, | 683 | |
677 | wdg_timeout); | 684 | /* Make sure this TID isn't already enabled */ |
685 | if (mvm->queue_info[queue].tid_bitmap & BIT(cfg->tid)) { | ||
686 | spin_unlock_bh(&mvm->queue_info_lock); | ||
687 | IWL_ERR(mvm, "Trying to enable TXQ with existing TID %d\n", | ||
688 | cfg->tid); | ||
678 | return; | 689 | return; |
679 | } | 690 | } |
680 | 691 | ||
681 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, wdg_timeout); | 692 | /* Update mappings and refcounts */ |
682 | WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), &cmd), | 693 | mvm->queue_info[queue].hw_queue_to_mac80211 |= BIT(mac80211_queue); |
683 | "Failed to configure queue %d on FIFO %d\n", queue, cfg->fifo); | 694 | mvm->queue_info[queue].hw_queue_refcount++; |
695 | if (mvm->queue_info[queue].hw_queue_refcount > 1) | ||
696 | enable_queue = false; | ||
697 | mvm->queue_info[queue].tid_bitmap |= BIT(cfg->tid); | ||
698 | |||
699 | IWL_DEBUG_TX_QUEUES(mvm, | ||
700 | "Enabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", | ||
701 | queue, mvm->queue_info[queue].hw_queue_refcount, | ||
702 | mvm->queue_info[queue].hw_queue_to_mac80211); | ||
703 | |||
704 | spin_unlock_bh(&mvm->queue_info_lock); | ||
705 | |||
706 | /* Send the enabling command if we need to */ | ||
707 | if (enable_queue) { | ||
708 | struct iwl_scd_txq_cfg_cmd cmd = { | ||
709 | .scd_queue = queue, | ||
710 | .enable = 1, | ||
711 | .window = cfg->frame_limit, | ||
712 | .sta_id = cfg->sta_id, | ||
713 | .ssn = cpu_to_le16(ssn), | ||
714 | .tx_fifo = cfg->fifo, | ||
715 | .aggregate = cfg->aggregate, | ||
716 | .tid = cfg->tid, | ||
717 | }; | ||
718 | |||
719 | iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL, | ||
720 | wdg_timeout); | ||
721 | WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd), | ||
722 | &cmd), | ||
723 | "Failed to configure queue %d on FIFO %d\n", queue, | ||
724 | cfg->fifo); | ||
725 | } | ||
684 | } | 726 | } |
685 | 727 | ||
686 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, u8 flags) | 728 | void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, |
729 | u8 tid, u8 flags) | ||
687 | { | 730 | { |
688 | struct iwl_scd_txq_cfg_cmd cmd = { | 731 | struct iwl_scd_txq_cfg_cmd cmd = { |
689 | .scd_queue = queue, | 732 | .scd_queue = queue, |
690 | .enable = 0, | 733 | .enable = 0, |
691 | }; | 734 | }; |
735 | bool remove_mac_queue = true; | ||
692 | int ret; | 736 | int ret; |
693 | 737 | ||
694 | if (!iwl_mvm_is_scd_cfg_supported(mvm)) { | 738 | spin_lock_bh(&mvm->queue_info_lock); |
695 | iwl_trans_txq_disable(mvm->trans, queue, true); | 739 | |
740 | if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) { | ||
741 | spin_unlock_bh(&mvm->queue_info_lock); | ||
742 | return; | ||
743 | } | ||
744 | |||
745 | mvm->queue_info[queue].tid_bitmap &= ~BIT(tid); | ||
746 | |||
747 | /* | ||
748 | * If there is another TID with the same AC - don't remove the MAC queue | ||
749 | * from the mapping | ||
750 | */ | ||
751 | if (tid < IWL_MAX_TID_COUNT) { | ||
752 | unsigned long tid_bitmap = | ||
753 | mvm->queue_info[queue].tid_bitmap; | ||
754 | int ac = tid_to_mac80211_ac[tid]; | ||
755 | int i; | ||
756 | |||
757 | for_each_set_bit(i, &tid_bitmap, IWL_MAX_TID_COUNT) { | ||
758 | if (tid_to_mac80211_ac[i] == ac) | ||
759 | remove_mac_queue = false; | ||
760 | } | ||
761 | } | ||
762 | |||
763 | if (remove_mac_queue) | ||
764 | mvm->queue_info[queue].hw_queue_to_mac80211 &= | ||
765 | ~BIT(mac80211_queue); | ||
766 | mvm->queue_info[queue].hw_queue_refcount--; | ||
767 | |||
768 | cmd.enable = mvm->queue_info[queue].hw_queue_refcount ? 1 : 0; | ||
769 | |||
770 | IWL_DEBUG_TX_QUEUES(mvm, | ||
771 | "Disabling TXQ #%d refcount=%d (mac80211 map:0x%x)\n", | ||
772 | queue, | ||
773 | mvm->queue_info[queue].hw_queue_refcount, | ||
774 | mvm->queue_info[queue].hw_queue_to_mac80211); | ||
775 | |||
776 | /* If the queue is still enabled - nothing left to do in this func */ | ||
777 | if (cmd.enable) { | ||
778 | spin_unlock_bh(&mvm->queue_info_lock); | ||
696 | return; | 779 | return; |
697 | } | 780 | } |
698 | 781 | ||
782 | /* Make sure queue info is correct even though we overwrite it */ | ||
783 | WARN(mvm->queue_info[queue].hw_queue_refcount || | ||
784 | mvm->queue_info[queue].tid_bitmap || | ||
785 | mvm->queue_info[queue].hw_queue_to_mac80211, | ||
786 | "TXQ #%d info out-of-sync - refcount=%d, mac map=0x%x, tid=0x%x\n", | ||
787 | queue, mvm->queue_info[queue].hw_queue_refcount, | ||
788 | mvm->queue_info[queue].hw_queue_to_mac80211, | ||
789 | mvm->queue_info[queue].tid_bitmap); | ||
790 | |||
791 | /* If we are here - the queue is freed and we can zero out these vals */ | ||
792 | mvm->queue_info[queue].hw_queue_refcount = 0; | ||
793 | mvm->queue_info[queue].tid_bitmap = 0; | ||
794 | mvm->queue_info[queue].hw_queue_to_mac80211 = 0; | ||
795 | |||
796 | spin_unlock_bh(&mvm->queue_info_lock); | ||
797 | |||
699 | iwl_trans_txq_disable(mvm->trans, queue, false); | 798 | iwl_trans_txq_disable(mvm->trans, queue, false); |
700 | ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, | 799 | ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, flags, |
701 | sizeof(cmd), &cmd); | 800 | sizeof(cmd), &cmd); |