aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h31
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api.h1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c59
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c171
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.h57
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c23
8 files changed, 270 insertions, 77 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index 5f1493c44097..726327782401 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -95,6 +95,7 @@
95 * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a 95 * @IWL_UCODE_TLV_FLAGS_P2P_PS: P2P client power save is supported (only on a
96 * single bound interface). 96 * single bound interface).
97 * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save 97 * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
98 * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
98 */ 99 */
99enum iwl_ucode_tlv_flag { 100enum iwl_ucode_tlv_flag {
100 IWL_UCODE_TLV_FLAGS_PAN = BIT(0), 101 IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
@@ -119,6 +120,7 @@ enum iwl_ucode_tlv_flag {
119 IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21), 120 IWL_UCODE_TLV_FLAGS_P2P_PS = BIT(21),
120 IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24), 121 IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
121 IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26), 122 IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
123 IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30),
122}; 124};
123 125
124/* The default calibrate table size if not specified by firmware file */ 126/* The default calibrate table size if not specified by firmware file */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
index 1b60fdff6a56..d63647867262 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-sta.h
@@ -199,11 +199,14 @@ enum iwl_sta_modify_flag {
199 * @STA_SLEEP_STATE_AWAKE: 199 * @STA_SLEEP_STATE_AWAKE:
200 * @STA_SLEEP_STATE_PS_POLL: 200 * @STA_SLEEP_STATE_PS_POLL:
201 * @STA_SLEEP_STATE_UAPSD: 201 * @STA_SLEEP_STATE_UAPSD:
202 * @STA_SLEEP_STATE_MOREDATA: set more-data bit on
203 * (last) released frame
202 */ 204 */
203enum iwl_sta_sleep_flag { 205enum iwl_sta_sleep_flag {
204 STA_SLEEP_STATE_AWAKE = 0, 206 STA_SLEEP_STATE_AWAKE = 0,
205 STA_SLEEP_STATE_PS_POLL = BIT(0), 207 STA_SLEEP_STATE_PS_POLL = BIT(0),
206 STA_SLEEP_STATE_UAPSD = BIT(1), 208 STA_SLEEP_STATE_UAPSD = BIT(1),
209 STA_SLEEP_STATE_MOREDATA = BIT(2),
207}; 210};
208 211
209/* STA ID and color bits definitions */ 212/* STA ID and color bits definitions */
@@ -318,13 +321,15 @@ struct iwl_mvm_add_sta_cmd_v5 {
318} __packed; /* ADD_STA_CMD_API_S_VER_5 */ 321} __packed; /* ADD_STA_CMD_API_S_VER_5 */
319 322
320/** 323/**
321 * struct iwl_mvm_add_sta_cmd_v6 - Add / modify a station 324 * struct iwl_mvm_add_sta_cmd_v7 - Add / modify a station
322 * VER_6 of this command is quite similar to VER_5 except 325 * VER_7 of this command is quite similar to VER_5 except
323 * exclusion of all fields related to the security key installation. 326 * exclusion of all fields related to the security key installation.
327 * It only differs from VER_6 by the "awake_acs" field that is
328 * reserved and ignored in VER_6.
324 */ 329 */
325struct iwl_mvm_add_sta_cmd_v6 { 330struct iwl_mvm_add_sta_cmd_v7 {
326 u8 add_modify; 331 u8 add_modify;
327 u8 reserved1; 332 u8 awake_acs;
328 __le16 tid_disable_tx; 333 __le16 tid_disable_tx;
329 __le32 mac_id_n_color; 334 __le32 mac_id_n_color;
330 u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */ 335 u8 addr[ETH_ALEN]; /* _STA_ID_MODIFY_INFO_API_S_VER_1 */
@@ -342,7 +347,7 @@ struct iwl_mvm_add_sta_cmd_v6 {
342 __le16 assoc_id; 347 __le16 assoc_id;
343 __le16 beamform_flags; 348 __le16 beamform_flags;
344 __le32 tfd_queue_msk; 349 __le32 tfd_queue_msk;
345} __packed; /* ADD_STA_CMD_API_S_VER_6 */ 350} __packed; /* ADD_STA_CMD_API_S_VER_7 */
346 351
347/** 352/**
348 * struct iwl_mvm_add_sta_key_cmd - add/modify sta key 353 * struct iwl_mvm_add_sta_key_cmd - add/modify sta key
@@ -432,5 +437,15 @@ struct iwl_mvm_wep_key_cmd {
432 struct iwl_mvm_wep_key wep_key[0]; 437 struct iwl_mvm_wep_key wep_key[0];
433} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */ 438} __packed; /* SEC_CURR_WEP_KEY_CMD_API_S_VER_2 */
434 439
440/**
441 * struct iwl_mvm_eosp_notification - EOSP notification from firmware
442 * @remain_frame_count: # of frames remaining, non-zero if SP was cut
443 * short by GO absence
444 * @sta_id: station ID
445 */
446struct iwl_mvm_eosp_notification {
447 __le32 remain_frame_count;
448 __le32 sta_id;
449} __packed; /* UAPSD_EOSP_NTFY_API_S_VER_1 */
435 450
436#endif /* __fw_api_sta_h__ */ 451#endif /* __fw_api_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 989d7dbdca6c..a043a1f2f06f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -163,6 +163,7 @@ enum {
163 TX_ANT_CONFIGURATION_CMD = 0x98, 163 TX_ANT_CONFIGURATION_CMD = 0x98,
164 BT_CONFIG = 0x9b, 164 BT_CONFIG = 0x9b,
165 STATISTICS_NOTIFICATION = 0x9d, 165 STATISTICS_NOTIFICATION = 0x9d,
166 EOSP_NOTIFICATION = 0x9e,
166 REDUCE_TX_POWER_CMD = 0x9f, 167 REDUCE_TX_POWER_CMD = 0x9f,
167 168
168 /* RF-KILL commands and notifications */ 169 /* RF-KILL commands and notifications */
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index c49b5073c251..5b9cfe1f35bd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -203,6 +203,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
203 hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG | 203 hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
204 REGULATORY_DISABLE_BEACON_HINTS; 204 REGULATORY_DISABLE_BEACON_HINTS;
205 205
206 if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
207 hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
208
206 hw->wiphy->iface_combinations = iwl_mvm_iface_combinations; 209 hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
207 hw->wiphy->n_iface_combinations = 210 hw->wiphy->n_iface_combinations =
208 ARRAY_SIZE(iwl_mvm_iface_combinations); 211 ARRAY_SIZE(iwl_mvm_iface_combinations);
@@ -305,6 +308,9 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
305 struct sk_buff *skb) 308 struct sk_buff *skb)
306{ 309{
307 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 310 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
311 struct ieee80211_sta *sta = control->sta;
312 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
313 struct ieee80211_hdr *hdr = (void *)skb->data;
308 314
309 if (iwl_mvm_is_radio_killed(mvm)) { 315 if (iwl_mvm_is_radio_killed(mvm)) {
310 IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n"); 316 IWL_DEBUG_DROP(mvm, "Dropping - RF/CT KILL\n");
@@ -315,8 +321,16 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
315 !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) 321 !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
316 goto drop; 322 goto drop;
317 323
318 if (control->sta) { 324 /* treat non-bufferable MMPDUs as broadcast if sta is sleeping */
319 if (iwl_mvm_tx_skb(mvm, skb, control->sta)) 325 if (unlikely(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER &&
326 ieee80211_is_mgmt(hdr->frame_control) &&
327 !ieee80211_is_deauth(hdr->frame_control) &&
328 !ieee80211_is_disassoc(hdr->frame_control) &&
329 !ieee80211_is_action(hdr->frame_control)))
330 sta = NULL;
331
332 if (sta) {
333 if (iwl_mvm_tx_skb(mvm, skb, sta))
320 goto drop; 334 goto drop;
321 return; 335 return;
322 } 336 }
@@ -1168,20 +1182,32 @@ static void iwl_mvm_mac_cancel_hw_scan(struct ieee80211_hw *hw,
1168 1182
1169static void 1183static void
1170iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw, 1184iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw,
1171 struct ieee80211_sta *sta, u16 tid, 1185 struct ieee80211_sta *sta, u16 tids,
1172 int num_frames, 1186 int num_frames,
1173 enum ieee80211_frame_release_type reason, 1187 enum ieee80211_frame_release_type reason,
1174 bool more_data) 1188 bool more_data)
1175{ 1189{
1176 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1190 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1177 1191
1178 /* TODO: how do we tell the fw to send frames for a specific TID */ 1192 /* Called when we need to transmit (a) frame(s) from mac80211 */
1179 1193
1180 /* 1194 iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
1181 * The fw will send EOSP notification when the last frame will be 1195 tids, more_data, false);
1182 * transmitted. 1196}
1183 */ 1197
1184 iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames); 1198static void
1199iwl_mvm_mac_release_buffered_frames(struct ieee80211_hw *hw,
1200 struct ieee80211_sta *sta, u16 tids,
1201 int num_frames,
1202 enum ieee80211_frame_release_type reason,
1203 bool more_data)
1204{
1205 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1206
1207 /* Called when we need to transmit (a) frame(s) from agg queue */
1208
1209 iwl_mvm_sta_modify_sleep_tx_count(mvm, sta, reason, num_frames,
1210 tids, more_data, true);
1185} 1211}
1186 1212
1187static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, 1213static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
@@ -1191,11 +1217,25 @@ static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw,
1191{ 1217{
1192 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 1218 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
1193 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 1219 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1220 int tid;
1194 1221
1195 switch (cmd) { 1222 switch (cmd) {
1196 case STA_NOTIFY_SLEEP: 1223 case STA_NOTIFY_SLEEP:
1197 if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0) 1224 if (atomic_read(&mvm->pending_frames[mvmsta->sta_id]) > 0)
1198 ieee80211_sta_block_awake(hw, sta, true); 1225 ieee80211_sta_block_awake(hw, sta, true);
1226 spin_lock_bh(&mvmsta->lock);
1227 for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
1228 struct iwl_mvm_tid_data *tid_data;
1229
1230 tid_data = &mvmsta->tid_data[tid];
1231 if (tid_data->state != IWL_AGG_ON &&
1232 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA)
1233 continue;
1234 if (iwl_mvm_tid_queued(tid_data) == 0)
1235 continue;
1236 ieee80211_sta_set_buffered(sta, tid, true);
1237 }
1238 spin_unlock_bh(&mvmsta->lock);
1199 /* 1239 /*
1200 * The fw updates the STA to be asleep. Tx packets on the Tx 1240 * The fw updates the STA to be asleep. Tx packets on the Tx
1201 * queues to this station will not be transmitted. The fw will 1241 * queues to this station will not be transmitted. The fw will
@@ -1914,6 +1954,7 @@ struct ieee80211_ops iwl_mvm_hw_ops = {
1914 .sta_state = iwl_mvm_mac_sta_state, 1954 .sta_state = iwl_mvm_mac_sta_state,
1915 .sta_notify = iwl_mvm_mac_sta_notify, 1955 .sta_notify = iwl_mvm_mac_sta_notify,
1916 .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames, 1956 .allow_buffered_frames = iwl_mvm_mac_allow_buffered_frames,
1957 .release_buffered_frames = iwl_mvm_mac_release_buffered_frames,
1917 .set_rts_threshold = iwl_mvm_mac_set_rts_threshold, 1958 .set_rts_threshold = iwl_mvm_mac_set_rts_threshold,
1918 .sta_rc_update = iwl_mvm_sta_rc_update, 1959 .sta_rc_update = iwl_mvm_sta_rc_update,
1919 .conf_tx = iwl_mvm_mac_conf_tx, 1960 .conf_tx = iwl_mvm_mac_conf_tx,
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index a3d43de342d7..a65eeb335cfb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -222,6 +222,8 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
222 222
223 RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false), 223 RX_HANDLER(TIME_EVENT_NOTIFICATION, iwl_mvm_rx_time_event_notif, false),
224 224
225 RX_HANDLER(EOSP_NOTIFICATION, iwl_mvm_rx_eosp_notif, false),
226
225 RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false), 227 RX_HANDLER(SCAN_REQUEST_CMD, iwl_mvm_rx_scan_response, false),
226 RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false), 228 RX_HANDLER(SCAN_COMPLETE_NOTIFICATION, iwl_mvm_rx_scan_complete, false),
227 RX_HANDLER(SCAN_OFFLOAD_COMPLETE, 229 RX_HANDLER(SCAN_OFFLOAD_COMPLETE,
@@ -284,6 +286,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
284 CMD(BEACON_NOTIFICATION), 286 CMD(BEACON_NOTIFICATION),
285 CMD(BEACON_TEMPLATE_CMD), 287 CMD(BEACON_TEMPLATE_CMD),
286 CMD(STATISTICS_NOTIFICATION), 288 CMD(STATISTICS_NOTIFICATION),
289 CMD(EOSP_NOTIFICATION),
287 CMD(REDUCE_TX_POWER_CMD), 290 CMD(REDUCE_TX_POWER_CMD),
288 CMD(TX_ANT_CONFIGURATION_CMD), 291 CMD(TX_ANT_CONFIGURATION_CMD),
289 CMD(D3_CONFIG_CMD), 292 CMD(D3_CONFIG_CMD),
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index ec1812133235..af94f75c3999 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -66,27 +66,27 @@
66#include "sta.h" 66#include "sta.h"
67#include "rs.h" 67#include "rs.h"
68 68
69static void iwl_mvm_add_sta_cmd_v6_to_v5(struct iwl_mvm_add_sta_cmd_v6 *cmd_v6, 69static void iwl_mvm_add_sta_cmd_v7_to_v5(struct iwl_mvm_add_sta_cmd_v7 *cmd_v7,
70 struct iwl_mvm_add_sta_cmd_v5 *cmd_v5) 70 struct iwl_mvm_add_sta_cmd_v5 *cmd_v5)
71{ 71{
72 memset(cmd_v5, 0, sizeof(*cmd_v5)); 72 memset(cmd_v5, 0, sizeof(*cmd_v5));
73 73
74 cmd_v5->add_modify = cmd_v6->add_modify; 74 cmd_v5->add_modify = cmd_v7->add_modify;
75 cmd_v5->tid_disable_tx = cmd_v6->tid_disable_tx; 75 cmd_v5->tid_disable_tx = cmd_v7->tid_disable_tx;
76 cmd_v5->mac_id_n_color = cmd_v6->mac_id_n_color; 76 cmd_v5->mac_id_n_color = cmd_v7->mac_id_n_color;
77 memcpy(cmd_v5->addr, cmd_v6->addr, ETH_ALEN); 77 memcpy(cmd_v5->addr, cmd_v7->addr, ETH_ALEN);
78 cmd_v5->sta_id = cmd_v6->sta_id; 78 cmd_v5->sta_id = cmd_v7->sta_id;
79 cmd_v5->modify_mask = cmd_v6->modify_mask; 79 cmd_v5->modify_mask = cmd_v7->modify_mask;
80 cmd_v5->station_flags = cmd_v6->station_flags; 80 cmd_v5->station_flags = cmd_v7->station_flags;
81 cmd_v5->station_flags_msk = cmd_v6->station_flags_msk; 81 cmd_v5->station_flags_msk = cmd_v7->station_flags_msk;
82 cmd_v5->add_immediate_ba_tid = cmd_v6->add_immediate_ba_tid; 82 cmd_v5->add_immediate_ba_tid = cmd_v7->add_immediate_ba_tid;
83 cmd_v5->remove_immediate_ba_tid = cmd_v6->remove_immediate_ba_tid; 83 cmd_v5->remove_immediate_ba_tid = cmd_v7->remove_immediate_ba_tid;
84 cmd_v5->add_immediate_ba_ssn = cmd_v6->add_immediate_ba_ssn; 84 cmd_v5->add_immediate_ba_ssn = cmd_v7->add_immediate_ba_ssn;
85 cmd_v5->sleep_tx_count = cmd_v6->sleep_tx_count; 85 cmd_v5->sleep_tx_count = cmd_v7->sleep_tx_count;
86 cmd_v5->sleep_state_flags = cmd_v6->sleep_state_flags; 86 cmd_v5->sleep_state_flags = cmd_v7->sleep_state_flags;
87 cmd_v5->assoc_id = cmd_v6->assoc_id; 87 cmd_v5->assoc_id = cmd_v7->assoc_id;
88 cmd_v5->beamform_flags = cmd_v6->beamform_flags; 88 cmd_v5->beamform_flags = cmd_v7->beamform_flags;
89 cmd_v5->tfd_queue_msk = cmd_v6->tfd_queue_msk; 89 cmd_v5->tfd_queue_msk = cmd_v7->tfd_queue_msk;
90} 90}
91 91
92static void 92static void
@@ -110,7 +110,7 @@ iwl_mvm_add_sta_key_to_add_sta_cmd_v5(struct iwl_mvm_add_sta_key_cmd *key_cmd,
110} 110}
111 111
112static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm, 112static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm,
113 struct iwl_mvm_add_sta_cmd_v6 *cmd, 113 struct iwl_mvm_add_sta_cmd_v7 *cmd,
114 int *status) 114 int *status)
115{ 115{
116 struct iwl_mvm_add_sta_cmd_v5 cmd_v5; 116 struct iwl_mvm_add_sta_cmd_v5 cmd_v5;
@@ -119,14 +119,14 @@ static int iwl_mvm_send_add_sta_cmd_status(struct iwl_mvm *mvm,
119 return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd), 119 return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(*cmd),
120 cmd, status); 120 cmd, status);
121 121
122 iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); 122 iwl_mvm_add_sta_cmd_v7_to_v5(cmd, &cmd_v5);
123 123
124 return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5), 124 return iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA, sizeof(cmd_v5),
125 &cmd_v5, status); 125 &cmd_v5, status);
126} 126}
127 127
128static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags, 128static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags,
129 struct iwl_mvm_add_sta_cmd_v6 *cmd) 129 struct iwl_mvm_add_sta_cmd_v7 *cmd)
130{ 130{
131 struct iwl_mvm_add_sta_cmd_v5 cmd_v5; 131 struct iwl_mvm_add_sta_cmd_v5 cmd_v5;
132 132
@@ -134,7 +134,7 @@ static int iwl_mvm_send_add_sta_cmd(struct iwl_mvm *mvm, u32 flags,
134 return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, 134 return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags,
135 sizeof(*cmd), cmd); 135 sizeof(*cmd), cmd);
136 136
137 iwl_mvm_add_sta_cmd_v6_to_v5(cmd, &cmd_v5); 137 iwl_mvm_add_sta_cmd_v7_to_v5(cmd, &cmd_v5);
138 138
139 return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5), 139 return iwl_mvm_send_cmd_pdu(mvm, ADD_STA, flags, sizeof(cmd_v5),
140 &cmd_v5); 140 &cmd_v5);
@@ -196,7 +196,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
196 bool update) 196 bool update)
197{ 197{
198 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 198 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
199 struct iwl_mvm_add_sta_cmd_v6 add_sta_cmd; 199 struct iwl_mvm_add_sta_cmd_v7 add_sta_cmd;
200 int ret; 200 int ret;
201 u32 status; 201 u32 status;
202 u32 agg_size = 0, mpdu_dens = 0; 202 u32 agg_size = 0, mpdu_dens = 0;
@@ -368,7 +368,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm,
368int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, 368int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
369 bool drain) 369 bool drain)
370{ 370{
371 struct iwl_mvm_add_sta_cmd_v6 cmd = {}; 371 struct iwl_mvm_add_sta_cmd_v7 cmd = {};
372 int ret; 372 int ret;
373 u32 status; 373 u32 status;
374 374
@@ -587,13 +587,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
587 const u8 *addr, 587 const u8 *addr,
588 u16 mac_id, u16 color) 588 u16 mac_id, u16 color)
589{ 589{
590 struct iwl_mvm_add_sta_cmd_v6 cmd; 590 struct iwl_mvm_add_sta_cmd_v7 cmd;
591 int ret; 591 int ret;
592 u32 status; 592 u32 status;
593 593
594 lockdep_assert_held(&mvm->mutex); 594 lockdep_assert_held(&mvm->mutex);
595 595
596 memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v6)); 596 memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v7));
597 cmd.sta_id = sta->sta_id; 597 cmd.sta_id = sta->sta_id;
598 cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, 598 cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
599 color)); 599 color));
@@ -735,7 +735,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
735 int tid, u16 ssn, bool start) 735 int tid, u16 ssn, bool start)
736{ 736{
737 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 737 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
738 struct iwl_mvm_add_sta_cmd_v6 cmd = {}; 738 struct iwl_mvm_add_sta_cmd_v7 cmd = {};
739 int ret; 739 int ret;
740 u32 status; 740 u32 status;
741 741
@@ -794,7 +794,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
794 int tid, u8 queue, bool start) 794 int tid, u8 queue, bool start)
795{ 795{
796 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 796 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
797 struct iwl_mvm_add_sta_cmd_v6 cmd = {}; 797 struct iwl_mvm_add_sta_cmd_v7 cmd = {};
798 int ret; 798 int ret;
799 u32 status; 799 u32 status;
800 800
@@ -833,7 +833,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
833 return ret; 833 return ret;
834} 834}
835 835
836static const u8 tid_to_ac[] = { 836static const u8 tid_to_mac80211_ac[] = {
837 IEEE80211_AC_BE, 837 IEEE80211_AC_BE,
838 IEEE80211_AC_BK, 838 IEEE80211_AC_BK,
839 IEEE80211_AC_BK, 839 IEEE80211_AC_BK,
@@ -844,6 +844,17 @@ static const u8 tid_to_ac[] = {
844 IEEE80211_AC_VO, 844 IEEE80211_AC_VO,
845}; 845};
846 846
847static const u8 tid_to_ucode_ac[] = {
848 AC_BE,
849 AC_BK,
850 AC_BK,
851 AC_BE,
852 AC_VI,
853 AC_VI,
854 AC_VO,
855 AC_VO,
856};
857
847int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 858int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
848 struct ieee80211_sta *sta, u16 tid, u16 *ssn) 859 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
849{ 860{
@@ -874,7 +885,7 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
874 } 885 }
875 886
876 /* the new tx queue is still connected to the same mac80211 queue */ 887 /* the new tx queue is still connected to the same mac80211 queue */
877 mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_ac[tid]]; 888 mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]];
878 889
879 spin_lock_bh(&mvmsta->lock); 890 spin_lock_bh(&mvmsta->lock);
880 tid_data = &mvmsta->tid_data[tid]; 891 tid_data = &mvmsta->tid_data[tid];
@@ -916,7 +927,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
916 tid_data->ssn = 0xffff; 927 tid_data->ssn = 0xffff;
917 spin_unlock_bh(&mvmsta->lock); 928 spin_unlock_bh(&mvmsta->lock);
918 929
919 fifo = iwl_mvm_ac_to_tx_fifo[tid_to_ac[tid]]; 930 fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
920 931
921 ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); 932 ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
922 if (ret) 933 if (ret)
@@ -1411,7 +1422,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
1411 struct ieee80211_sta *sta) 1422 struct ieee80211_sta *sta)
1412{ 1423{
1413 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 1424 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1414 struct iwl_mvm_add_sta_cmd_v6 cmd = { 1425 struct iwl_mvm_add_sta_cmd_v7 cmd = {
1415 .add_modify = STA_MODE_MODIFY, 1426 .add_modify = STA_MODE_MODIFY,
1416 .sta_id = mvmsta->sta_id, 1427 .sta_id = mvmsta->sta_id,
1417 .station_flags_msk = cpu_to_le32(STA_FLG_PS), 1428 .station_flags_msk = cpu_to_le32(STA_FLG_PS),
@@ -1427,28 +1438,102 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
1427void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, 1438void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
1428 struct ieee80211_sta *sta, 1439 struct ieee80211_sta *sta,
1429 enum ieee80211_frame_release_type reason, 1440 enum ieee80211_frame_release_type reason,
1430 u16 cnt) 1441 u16 cnt, u16 tids, bool more_data,
1442 bool agg)
1431{ 1443{
1432 u16 sleep_state_flags =
1433 (reason == IEEE80211_FRAME_RELEASE_UAPSD) ?
1434 STA_SLEEP_STATE_UAPSD : STA_SLEEP_STATE_PS_POLL;
1435 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 1444 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1436 struct iwl_mvm_add_sta_cmd_v6 cmd = { 1445 struct iwl_mvm_add_sta_cmd_v7 cmd = {
1437 .add_modify = STA_MODE_MODIFY, 1446 .add_modify = STA_MODE_MODIFY,
1438 .sta_id = mvmsta->sta_id, 1447 .sta_id = mvmsta->sta_id,
1439 .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, 1448 .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
1440 .sleep_tx_count = cpu_to_le16(cnt), 1449 .sleep_tx_count = cpu_to_le16(cnt),
1441 .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), 1450 .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color),
1442 /*
1443 * Same modify mask for sleep_tx_count and sleep_state_flags so
1444 * we must set the sleep_state_flags too.
1445 */
1446 .sleep_state_flags = cpu_to_le16(sleep_state_flags),
1447 }; 1451 };
1448 int ret; 1452 int tid, ret;
1453 unsigned long _tids = tids;
1454
1455 /* convert TIDs to ACs - we don't support TSPEC so that's OK
1456 * Note that this field is reserved and unused by firmware not
1457 * supporting GO uAPSD, so it's safe to always do this.
1458 */
1459 for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT)
1460 cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]);
1461
1462 /* If we're releasing frames from aggregation queues then check if the
1463 * all queues combined that we're releasing frames from have
1464 * - more frames than the service period, in which case more_data
1465 * needs to be set
1466 * - fewer than 'cnt' frames, in which case we need to adjust the
1467 * firmware command (but do that unconditionally)
1468 */
1469 if (agg) {
1470 int remaining = cnt;
1471
1472 spin_lock_bh(&mvmsta->lock);
1473 for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT) {
1474 struct iwl_mvm_tid_data *tid_data;
1475 u16 n_queued;
1476
1477 tid_data = &mvmsta->tid_data[tid];
1478 if (WARN(tid_data->state != IWL_AGG_ON &&
1479 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA,
1480 "TID %d state is %d\n",
1481 tid, tid_data->state)) {
1482 spin_unlock_bh(&mvmsta->lock);
1483 ieee80211_sta_eosp(sta);
1484 return;
1485 }
1486
1487 n_queued = iwl_mvm_tid_queued(tid_data);
1488 if (n_queued > remaining) {
1489 more_data = true;
1490 remaining = 0;
1491 break;
1492 }
1493 remaining -= n_queued;
1494 }
1495 spin_unlock_bh(&mvmsta->lock);
1496
1497 cmd.sleep_tx_count = cpu_to_le16(cnt - remaining);
1498 if (WARN_ON(cnt - remaining == 0)) {
1499 ieee80211_sta_eosp(sta);
1500 return;
1501 }
1502 }
1503
1504 /* Note: this is ignored by firmware not supporting GO uAPSD */
1505 if (more_data)
1506 cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_MOREDATA);
1507
1508 if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) {
1509 mvmsta->next_status_eosp = true;
1510 cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_PS_POLL);
1511 } else {
1512 cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_UAPSD);
1513 }
1449 1514
1450 /* TODO: somehow the fw doesn't seem to take PS_POLL into account */
1451 ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd); 1515 ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd);
1452 if (ret) 1516 if (ret)
1453 IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); 1517 IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
1454} 1518}
1519
1520int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
1521 struct iwl_rx_cmd_buffer *rxb,
1522 struct iwl_device_cmd *cmd)
1523{
1524 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1525 struct iwl_mvm_eosp_notification *notif = (void *)pkt->data;
1526 struct ieee80211_sta *sta;
1527 u32 sta_id = le32_to_cpu(notif->sta_id);
1528
1529 if (WARN_ON_ONCE(sta_id >= IWL_MVM_STATION_COUNT))
1530 return 0;
1531
1532 rcu_read_lock();
1533 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
1534 if (!IS_ERR_OR_NULL(sta))
1535 ieee80211_sta_eosp(sta);
1536 rcu_read_unlock();
1537
1538 return 0;
1539}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index 4968d0237dc5..64f9a1bf7c43 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -195,24 +195,33 @@ struct iwl_mvm;
195/** 195/**
196 * DOC: AP mode - PS 196 * DOC: AP mode - PS
197 * 197 *
198 * When a station is asleep, the fw will set it as "asleep". All the 198 * When a station is asleep, the fw will set it as "asleep". All frames on
199 * non-aggregation frames to that station will be dropped by the fw 199 * shared queues (i.e. non-aggregation queues) to that station will be dropped
200 * (%TX_STATUS_FAIL_DEST_PS failure code). 200 * by the fw (%TX_STATUS_FAIL_DEST_PS failure code).
201 *
201 * AMPDUs are in a separate queue that is stopped by the fw. We just need to 202 * AMPDUs are in a separate queue that is stopped by the fw. We just need to
202 * let mac80211 know how many frames we have in these queues so that it can 203 * let mac80211 know when there are frames in these queues so that it can
203 * properly handle trigger frames. 204 * properly handle trigger frames.
204 * When the a trigger frame is received, mac80211 tells the driver to send 205 *
205 * frames from the AMPDU queues or AC queue depending on which queue are 206 * When a trigger frame is received, mac80211 tells the driver to send frames
206 * delivery-enabled and what TID has frames to transmit (Note that mac80211 has 207 * from the AMPDU queues or sends frames to non-aggregation queues itself,
207 * all the knowledege since all the non-agg frames are buffered / filtered, and 208 * depending on which ACs are delivery-enabled and what TID has frames to
208 * the driver tells mac80211 about agg frames). The driver needs to tell the fw 209 * transmit. Note that mac80211 has all the knowledege since all the non-agg
209 * to let frames out even if the station is asleep. This is done by 210 * frames are buffered / filtered, and the driver tells mac80211 about agg
210 * %iwl_mvm_sta_modify_sleep_tx_count. 211 * frames). The driver needs to tell the fw to let frames out even if the
211 * When we receive a frame from that station with PM bit unset, the 212 * station is asleep. This is done by %iwl_mvm_sta_modify_sleep_tx_count.
212 * driver needs to let the fw know that this station isn't alseep any more. 213 *
213 * This is done by %iwl_mvm_sta_modify_ps_wake. 214 * When we receive a frame from that station with PM bit unset, the driver
214 * 215 * needs to let the fw know that this station isn't asleep any more. This is
215 * TODO - EOSP handling 216 * done by %iwl_mvm_sta_modify_ps_wake in response to mac80211 signalling the
217 * station's wakeup.
218 *
219 * For a GO, the Service Period might be cut short due to an absence period
220 * of the GO. In this (and all other cases) the firmware notifies us with the
221 * EOSP_NOTIFICATION, and we notify mac80211 of that. Further frames that we
222 * already sent to the device will be rejected again.
223 *
224 * See also "AP support for powersaving clients" in mac80211.h.
216 */ 225 */
217 226
218/** 227/**
@@ -261,6 +270,12 @@ struct iwl_mvm_tid_data {
261 u16 ssn; 270 u16 ssn;
262}; 271};
263 272
273static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
274{
275 return ieee80211_sn_sub(IEEE80211_SEQ_TO_SN(tid_data->seq_number),
276 tid_data->next_reclaimed);
277}
278
264/** 279/**
265 * struct iwl_mvm_sta - representation of a station in the driver 280 * struct iwl_mvm_sta - representation of a station in the driver
266 * @sta_id: the index of the station in the fw (will be replaced by id_n_color) 281 * @sta_id: the index of the station in the fw (will be replaced by id_n_color)
@@ -270,6 +285,8 @@ struct iwl_mvm_tid_data {
270 * tid. 285 * tid.
271 * @max_agg_bufsize: the maximal size of the AGG buffer for this station 286 * @max_agg_bufsize: the maximal size of the AGG buffer for this station
272 * @bt_reduced_txpower: is reduced tx power enabled for this station 287 * @bt_reduced_txpower: is reduced tx power enabled for this station
288 * @next_status_eosp: the next reclaimed packet is a PS-Poll response and
289 * we need to signal the EOSP
273 * @lock: lock to protect the whole struct. Since %tid_data is access from Tx 290 * @lock: lock to protect the whole struct. Since %tid_data is access from Tx
274 * and from Tx response flow, it needs a spinlock. 291 * and from Tx response flow, it needs a spinlock.
275 * @tid_data: per tid data. Look at %iwl_mvm_tid_data. 292 * @tid_data: per tid data. Look at %iwl_mvm_tid_data.
@@ -288,6 +305,7 @@ struct iwl_mvm_sta {
288 u16 tid_disable_agg; 305 u16 tid_disable_agg;
289 u8 max_agg_bufsize; 306 u8 max_agg_bufsize;
290 bool bt_reduced_txpower; 307 bool bt_reduced_txpower;
308 bool next_status_eosp;
291 spinlock_t lock; 309 spinlock_t lock;
292 struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT]; 310 struct iwl_mvm_tid_data tid_data[IWL_MAX_TID_COUNT];
293 struct iwl_lq_sta lq_sta; 311 struct iwl_lq_sta lq_sta;
@@ -345,6 +363,10 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
345 struct ieee80211_sta *sta, u32 iv32, 363 struct ieee80211_sta *sta, u32 iv32,
346 u16 *phase1key); 364 u16 *phase1key);
347 365
366int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
367 struct iwl_rx_cmd_buffer *rxb,
368 struct iwl_device_cmd *cmd);
369
348/* AMPDU */ 370/* AMPDU */
349int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta, 371int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
350 int tid, u16 ssn, bool start); 372 int tid, u16 ssn, bool start);
@@ -375,7 +397,8 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
375void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, 397void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
376 struct ieee80211_sta *sta, 398 struct ieee80211_sta *sta,
377 enum ieee80211_frame_release_type reason, 399 enum ieee80211_frame_release_type reason,
378 u16 cnt); 400 u16 cnt, u16 tids, bool more_data,
401 bool agg);
379int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, 402int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
380 bool drain); 403 bool drain);
381 404
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 90378c217bc7..8d18bf23e4bf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -377,6 +377,13 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
377 tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; 377 tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload;
378 /* From now on, we cannot access info->control */ 378 /* From now on, we cannot access info->control */
379 379
380 /*
381 * we handle that entirely ourselves -- for uAPSD the firmware
382 * will always send a notification, and for PS-Poll responses
383 * we'll notify mac80211 when getting frame status
384 */
385 info->flags &= ~IEEE80211_TX_STATUS_EOSP;
386
380 spin_lock(&mvmsta->lock); 387 spin_lock(&mvmsta->lock);
381 388
382 if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { 389 if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
@@ -437,6 +444,17 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm,
437 444
438 lockdep_assert_held(&mvmsta->lock); 445 lockdep_assert_held(&mvmsta->lock);
439 446
447 if ((tid_data->state == IWL_AGG_ON ||
448 tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) &&
449 iwl_mvm_tid_queued(tid_data) == 0) {
450 /*
451 * Now that this aggregation queue is empty tell mac80211 so it
452 * knows we no longer have frames buffered for the station on
453 * this TID (for the TIM bitmap calculation.)
454 */
455 ieee80211_sta_set_buffered(sta, tid, false);
456 }
457
440 if (tid_data->ssn != tid_data->next_reclaimed) 458 if (tid_data->ssn != tid_data->next_reclaimed)
441 return; 459 return;
442 460
@@ -674,6 +692,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
674 iwl_mvm_check_ratid_empty(mvm, sta, tid); 692 iwl_mvm_check_ratid_empty(mvm, sta, tid);
675 spin_unlock_bh(&mvmsta->lock); 693 spin_unlock_bh(&mvmsta->lock);
676 } 694 }
695
696 if (mvmsta->next_status_eosp) {
697 mvmsta->next_status_eosp = false;
698 ieee80211_sta_eosp(sta);
699 }
677 } else { 700 } else {
678 sta = NULL; 701 sta = NULL;
679 mvmsta = NULL; 702 mvmsta = NULL;