aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/sta.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c99
1 files changed, 87 insertions, 12 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 274f44e2ef60..0fd96e4da461 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -22,7 +22,7 @@
22 * USA 22 * USA
23 * 23 *
24 * The full GNU General Public License is included in this distribution 24 * The full GNU General Public License is included in this distribution
25 * in the file called LICENSE.GPL. 25 * in the file called COPYING.
26 * 26 *
27 * Contact Information: 27 * Contact Information:
28 * Intel Linux Wireless <ilw@linux.intel.com> 28 * Intel Linux Wireless <ilw@linux.intel.com>
@@ -101,8 +101,55 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
101 } 101 }
102 add_sta_cmd.add_modify = update ? 1 : 0; 102 add_sta_cmd.add_modify = update ? 1 : 0;
103 103
104 /* STA_FLG_FAT_EN_MSK ? */ 104 add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
105 /* STA_FLG_MIMO_EN_MSK ? */ 105 STA_FLG_MIMO_EN_MSK);
106
107 switch (sta->bandwidth) {
108 case IEEE80211_STA_RX_BW_160:
109 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_160MHZ);
110 /* fall through */
111 case IEEE80211_STA_RX_BW_80:
112 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_80MHZ);
113 /* fall through */
114 case IEEE80211_STA_RX_BW_40:
115 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_FAT_EN_40MHZ);
116 /* fall through */
117 case IEEE80211_STA_RX_BW_20:
118 if (sta->ht_cap.ht_supported)
119 add_sta_cmd.station_flags |=
120 cpu_to_le32(STA_FLG_FAT_EN_20MHZ);
121 break;
122 }
123
124 switch (sta->rx_nss) {
125 case 1:
126 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
127 break;
128 case 2:
129 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO2);
130 break;
131 case 3 ... 8:
132 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_MIMO3);
133 break;
134 }
135
136 switch (sta->smps_mode) {
137 case IEEE80211_SMPS_AUTOMATIC:
138 case IEEE80211_SMPS_NUM_MODES:
139 WARN_ON(1);
140 break;
141 case IEEE80211_SMPS_STATIC:
142 /* override NSS */
143 add_sta_cmd.station_flags &= ~cpu_to_le32(STA_FLG_MIMO_EN_MSK);
144 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_MIMO_EN_SISO);
145 break;
146 case IEEE80211_SMPS_DYNAMIC:
147 add_sta_cmd.station_flags |= cpu_to_le32(STA_FLG_RTS_MIMO_PROT);
148 break;
149 case IEEE80211_SMPS_OFF:
150 /* nothing */
151 break;
152 }
106 153
107 if (sta->ht_cap.ht_supported) { 154 if (sta->ht_cap.ht_supported) {
108 add_sta_cmd.station_flags_msk |= 155 add_sta_cmd.station_flags_msk |=
@@ -340,6 +387,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
340 387
341 if (vif->type == NL80211_IFTYPE_STATION && 388 if (vif->type == NL80211_IFTYPE_STATION &&
342 mvmvif->ap_sta_id == mvm_sta->sta_id) { 389 mvmvif->ap_sta_id == mvm_sta->sta_id) {
390 /* flush its queues here since we are freeing mvm_sta */
391 ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
392
343 /* 393 /*
344 * Put a non-NULL since the fw station isn't removed. 394 * Put a non-NULL since the fw station isn't removed.
345 * It will be removed after the MAC will be set as 395 * It will be removed after the MAC will be set as
@@ -348,9 +398,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
348 rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id], 398 rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
349 ERR_PTR(-EINVAL)); 399 ERR_PTR(-EINVAL));
350 400
351 /* flush its queues here since we are freeing mvm_sta */
352 ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
353
354 /* if we are associated - we can't remove the AP STA now */ 401 /* if we are associated - we can't remove the AP STA now */
355 if (vif->bss_conf.assoc) 402 if (vif->bss_conf.assoc)
356 return ret; 403 return ret;
@@ -686,7 +733,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
686 733
687 spin_lock_bh(&mvmsta->lock); 734 spin_lock_bh(&mvmsta->lock);
688 tid_data = &mvmsta->tid_data[tid]; 735 tid_data = &mvmsta->tid_data[tid];
689 tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); 736 tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
690 tid_data->txq_id = txq_id; 737 tid_data->txq_id = txq_id;
691 *ssn = tid_data->ssn; 738 *ssn = tid_data->ssn;
692 739
@@ -789,7 +836,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
789 836
790 switch (tid_data->state) { 837 switch (tid_data->state) {
791 case IWL_AGG_ON: 838 case IWL_AGG_ON:
792 tid_data->ssn = SEQ_TO_SN(tid_data->seq_number); 839 tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
793 840
794 IWL_DEBUG_TX_QUEUES(mvm, 841 IWL_DEBUG_TX_QUEUES(mvm,
795 "ssn = %d, next_recl = %d\n", 842 "ssn = %d, next_recl = %d\n",
@@ -834,6 +881,34 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
834 return err; 881 return err;
835} 882}
836 883
884int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
885 struct ieee80211_sta *sta, u16 tid)
886{
887 struct iwl_mvm_sta *mvmsta = (void *)sta->drv_priv;
888 struct iwl_mvm_tid_data *tid_data = &mvmsta->tid_data[tid];
889 u16 txq_id;
890
891 /*
892 * First set the agg state to OFF to avoid calling
893 * ieee80211_stop_tx_ba_cb in iwl_mvm_check_ratid_empty.
894 */
895 spin_lock_bh(&mvmsta->lock);
896 txq_id = tid_data->txq_id;
897 IWL_DEBUG_TX_QUEUES(mvm, "Flush AGG: sta %d tid %d q %d state %d\n",
898 mvmsta->sta_id, tid, txq_id, tid_data->state);
899 tid_data->state = IWL_AGG_OFF;
900 spin_unlock_bh(&mvmsta->lock);
901
902 if (iwl_mvm_flush_tx_path(mvm, BIT(txq_id), true))
903 IWL_ERR(mvm, "Couldn't flush the AGG queue\n");
904
905 iwl_trans_txq_disable(mvm->trans, tid_data->txq_id);
906 mvm->queue_to_mac80211[tid_data->txq_id] =
907 IWL_INVALID_MAC80211_QUEUE;
908
909 return 0;
910}
911
837static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm) 912static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
838{ 913{
839 int i; 914 int i;
@@ -870,7 +945,7 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
870 mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) 945 mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
871 return mvmvif->ap_sta_id; 946 return mvmvif->ap_sta_id;
872 947
873 return IWL_INVALID_STATION; 948 return IWL_MVM_STATION_COUNT;
874} 949}
875 950
876static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm, 951static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
@@ -1018,7 +1093,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
1018 1093
1019 /* Get the station id from the mvm local station table */ 1094 /* Get the station id from the mvm local station table */
1020 sta_id = iwl_mvm_get_key_sta_id(vif, sta); 1095 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1021 if (sta_id == IWL_INVALID_STATION) { 1096 if (sta_id == IWL_MVM_STATION_COUNT) {
1022 IWL_ERR(mvm, "Failed to find station id\n"); 1097 IWL_ERR(mvm, "Failed to find station id\n");
1023 return -EINVAL; 1098 return -EINVAL;
1024 } 1099 }
@@ -1113,7 +1188,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
1113 return -ENOENT; 1188 return -ENOENT;
1114 } 1189 }
1115 1190
1116 if (sta_id == IWL_INVALID_STATION) { 1191 if (sta_id == IWL_MVM_STATION_COUNT) {
1117 IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n"); 1192 IWL_DEBUG_WEP(mvm, "station non-existent, early return.\n");
1118 return 0; 1193 return 0;
1119 } 1194 }
@@ -1179,7 +1254,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
1179 struct iwl_mvm_sta *mvm_sta; 1254 struct iwl_mvm_sta *mvm_sta;
1180 u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta); 1255 u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
1181 1256
1182 if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION)) 1257 if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
1183 return; 1258 return;
1184 1259
1185 rcu_read_lock(); 1260 rcu_read_lock();