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.c213
1 files changed, 162 insertions, 51 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 3397f59cd4e4..f339ef884250 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);
@@ -175,19 +175,30 @@ static int iwl_mvm_send_add_sta_key_cmd(struct iwl_mvm *mvm,
175 &sta_cmd); 175 &sta_cmd);
176} 176}
177 177
178static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm) 178static int iwl_mvm_find_free_sta_id(struct iwl_mvm *mvm,
179 enum nl80211_iftype iftype)
179{ 180{
180 int sta_id; 181 int sta_id;
182 u32 reserved_ids = 0;
181 183
184 BUILD_BUG_ON(IWL_MVM_STATION_COUNT > 32);
182 WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)); 185 WARN_ON_ONCE(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status));
183 186
184 lockdep_assert_held(&mvm->mutex); 187 lockdep_assert_held(&mvm->mutex);
185 188
189 /* d0i3/d3 assumes the AP's sta_id (of sta vif) is 0. reserve it. */
190 if (iftype != NL80211_IFTYPE_STATION)
191 reserved_ids = BIT(0);
192
186 /* Don't take rcu_read_lock() since we are protected by mvm->mutex */ 193 /* Don't take rcu_read_lock() since we are protected by mvm->mutex */
187 for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++) 194 for (sta_id = 0; sta_id < IWL_MVM_STATION_COUNT; sta_id++) {
195 if (BIT(sta_id) & reserved_ids)
196 continue;
197
188 if (!rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id], 198 if (!rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
189 lockdep_is_held(&mvm->mutex))) 199 lockdep_is_held(&mvm->mutex)))
190 return sta_id; 200 return sta_id;
201 }
191 return IWL_MVM_STATION_COUNT; 202 return IWL_MVM_STATION_COUNT;
192} 203}
193 204
@@ -196,7 +207,7 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
196 bool update) 207 bool update)
197{ 208{
198 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 209 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
199 struct iwl_mvm_add_sta_cmd_v6 add_sta_cmd; 210 struct iwl_mvm_add_sta_cmd_v7 add_sta_cmd;
200 int ret; 211 int ret;
201 u32 status; 212 u32 status;
202 u32 agg_size = 0, mpdu_dens = 0; 213 u32 agg_size = 0, mpdu_dens = 0;
@@ -312,7 +323,8 @@ int iwl_mvm_add_sta(struct iwl_mvm *mvm,
312 lockdep_assert_held(&mvm->mutex); 323 lockdep_assert_held(&mvm->mutex);
313 324
314 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) 325 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
315 sta_id = iwl_mvm_find_free_sta_id(mvm); 326 sta_id = iwl_mvm_find_free_sta_id(mvm,
327 ieee80211_vif_type_p2p(vif));
316 else 328 else
317 sta_id = mvm_sta->sta_id; 329 sta_id = mvm_sta->sta_id;
318 330
@@ -368,7 +380,7 @@ int iwl_mvm_update_sta(struct iwl_mvm *mvm,
368int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, 380int iwl_mvm_drain_sta(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
369 bool drain) 381 bool drain)
370{ 382{
371 struct iwl_mvm_add_sta_cmd_v6 cmd = {}; 383 struct iwl_mvm_add_sta_cmd_v7 cmd = {};
372 int ret; 384 int ret;
373 u32 status; 385 u32 status;
374 386
@@ -522,6 +534,10 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
522 534
523 /* unassoc - go ahead - remove the AP STA now */ 535 /* unassoc - go ahead - remove the AP STA now */
524 mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT; 536 mvmvif->ap_sta_id = IWL_MVM_STATION_COUNT;
537
538 /* clear d0i3_ap_sta_id if no longer relevant */
539 if (mvm->d0i3_ap_sta_id == mvm_sta->sta_id)
540 mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
525 } 541 }
526 542
527 /* 543 /*
@@ -560,10 +576,10 @@ int iwl_mvm_rm_sta_id(struct iwl_mvm *mvm,
560} 576}
561 577
562int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta, 578int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta,
563 u32 qmask) 579 u32 qmask, enum nl80211_iftype iftype)
564{ 580{
565 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { 581 if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
566 sta->sta_id = iwl_mvm_find_free_sta_id(mvm); 582 sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype);
567 if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_STATION_COUNT)) 583 if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_STATION_COUNT))
568 return -ENOSPC; 584 return -ENOSPC;
569 } 585 }
@@ -587,13 +603,13 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm,
587 const u8 *addr, 603 const u8 *addr,
588 u16 mac_id, u16 color) 604 u16 mac_id, u16 color)
589{ 605{
590 struct iwl_mvm_add_sta_cmd_v6 cmd; 606 struct iwl_mvm_add_sta_cmd_v7 cmd;
591 int ret; 607 int ret;
592 u32 status; 608 u32 status;
593 609
594 lockdep_assert_held(&mvm->mutex); 610 lockdep_assert_held(&mvm->mutex);
595 611
596 memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v6)); 612 memset(&cmd, 0, sizeof(struct iwl_mvm_add_sta_cmd_v7));
597 cmd.sta_id = sta->sta_id; 613 cmd.sta_id = sta->sta_id;
598 cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id, 614 cmd.mac_id_n_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mac_id,
599 color)); 615 color));
@@ -627,7 +643,8 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
627 lockdep_assert_held(&mvm->mutex); 643 lockdep_assert_held(&mvm->mutex);
628 644
629 /* Add the aux station, but without any queues */ 645 /* Add the aux station, but without any queues */
630 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0); 646 ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0,
647 NL80211_IFTYPE_UNSPECIFIED);
631 if (ret) 648 if (ret)
632 return ret; 649 return ret;
633 650
@@ -699,7 +716,8 @@ int iwl_mvm_add_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
699 lockdep_assert_held(&mvm->mutex); 716 lockdep_assert_held(&mvm->mutex);
700 717
701 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); 718 qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
702 ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask); 719 ret = iwl_mvm_allocate_int_sta(mvm, bsta, qmask,
720 ieee80211_vif_type_p2p(vif));
703 if (ret) 721 if (ret)
704 return ret; 722 return ret;
705 723
@@ -735,7 +753,7 @@ int iwl_mvm_sta_rx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
735 int tid, u16 ssn, bool start) 753 int tid, u16 ssn, bool start)
736{ 754{
737 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 755 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
738 struct iwl_mvm_add_sta_cmd_v6 cmd = {}; 756 struct iwl_mvm_add_sta_cmd_v7 cmd = {};
739 int ret; 757 int ret;
740 u32 status; 758 u32 status;
741 759
@@ -794,7 +812,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
794 int tid, u8 queue, bool start) 812 int tid, u8 queue, bool start)
795{ 813{
796 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv; 814 struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
797 struct iwl_mvm_add_sta_cmd_v6 cmd = {}; 815 struct iwl_mvm_add_sta_cmd_v7 cmd = {};
798 int ret; 816 int ret;
799 u32 status; 817 u32 status;
800 818
@@ -833,7 +851,7 @@ static int iwl_mvm_sta_tx_agg(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
833 return ret; 851 return ret;
834} 852}
835 853
836static const u8 tid_to_ac[] = { 854const u8 tid_to_mac80211_ac[] = {
837 IEEE80211_AC_BE, 855 IEEE80211_AC_BE,
838 IEEE80211_AC_BK, 856 IEEE80211_AC_BK,
839 IEEE80211_AC_BK, 857 IEEE80211_AC_BK,
@@ -844,6 +862,17 @@ static const u8 tid_to_ac[] = {
844 IEEE80211_AC_VO, 862 IEEE80211_AC_VO,
845}; 863};
846 864
865static const u8 tid_to_ucode_ac[] = {
866 AC_BE,
867 AC_BK,
868 AC_BK,
869 AC_BE,
870 AC_VI,
871 AC_VI,
872 AC_VO,
873 AC_VO,
874};
875
847int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 876int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
848 struct ieee80211_sta *sta, u16 tid, u16 *ssn) 877 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
849{ 878{
@@ -873,10 +902,18 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
873 return -EIO; 902 return -EIO;
874 } 903 }
875 904
905 spin_lock_bh(&mvmsta->lock);
906
907 /* possible race condition - we entered D0i3 while starting agg */
908 if (test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status)) {
909 spin_unlock_bh(&mvmsta->lock);
910 IWL_ERR(mvm, "Entered D0i3 while starting Tx agg\n");
911 return -EIO;
912 }
913
876 /* the new tx queue is still connected to the same mac80211 queue */ 914 /* 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]]; 915 mvm->queue_to_mac80211[txq_id] = vif->hw_queue[tid_to_mac80211_ac[tid]];
878 916
879 spin_lock_bh(&mvmsta->lock);
880 tid_data = &mvmsta->tid_data[tid]; 917 tid_data = &mvmsta->tid_data[tid];
881 tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number); 918 tid_data->ssn = IEEE80211_SEQ_TO_SN(tid_data->seq_number);
882 tid_data->txq_id = txq_id; 919 tid_data->txq_id = txq_id;
@@ -916,7 +953,7 @@ int iwl_mvm_sta_tx_agg_oper(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
916 tid_data->ssn = 0xffff; 953 tid_data->ssn = 0xffff;
917 spin_unlock_bh(&mvmsta->lock); 954 spin_unlock_bh(&mvmsta->lock);
918 955
919 fifo = iwl_mvm_ac_to_tx_fifo[tid_to_ac[tid]]; 956 fifo = iwl_mvm_ac_to_tx_fifo[tid_to_mac80211_ac[tid]];
920 957
921 ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true); 958 ret = iwl_mvm_sta_tx_agg(mvm, sta, tid, queue, true);
922 if (ret) 959 if (ret)
@@ -1411,7 +1448,7 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
1411 struct ieee80211_sta *sta) 1448 struct ieee80211_sta *sta)
1412{ 1449{
1413 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 1450 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1414 struct iwl_mvm_add_sta_cmd_v6 cmd = { 1451 struct iwl_mvm_add_sta_cmd_v7 cmd = {
1415 .add_modify = STA_MODE_MODIFY, 1452 .add_modify = STA_MODE_MODIFY,
1416 .sta_id = mvmsta->sta_id, 1453 .sta_id = mvmsta->sta_id,
1417 .station_flags_msk = cpu_to_le32(STA_FLG_PS), 1454 .station_flags_msk = cpu_to_le32(STA_FLG_PS),
@@ -1427,28 +1464,102 @@ void iwl_mvm_sta_modify_ps_wake(struct iwl_mvm *mvm,
1427void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm, 1464void iwl_mvm_sta_modify_sleep_tx_count(struct iwl_mvm *mvm,
1428 struct ieee80211_sta *sta, 1465 struct ieee80211_sta *sta,
1429 enum ieee80211_frame_release_type reason, 1466 enum ieee80211_frame_release_type reason,
1430 u16 cnt) 1467 u16 cnt, u16 tids, bool more_data,
1468 bool agg)
1431{ 1469{
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); 1470 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1436 struct iwl_mvm_add_sta_cmd_v6 cmd = { 1471 struct iwl_mvm_add_sta_cmd_v7 cmd = {
1437 .add_modify = STA_MODE_MODIFY, 1472 .add_modify = STA_MODE_MODIFY,
1438 .sta_id = mvmsta->sta_id, 1473 .sta_id = mvmsta->sta_id,
1439 .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT, 1474 .modify_mask = STA_MODIFY_SLEEPING_STA_TX_COUNT,
1440 .sleep_tx_count = cpu_to_le16(cnt), 1475 .sleep_tx_count = cpu_to_le16(cnt),
1441 .mac_id_n_color = cpu_to_le32(mvmsta->mac_id_n_color), 1476 .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 }; 1477 };
1448 int ret; 1478 int tid, ret;
1479 unsigned long _tids = tids;
1480
1481 /* convert TIDs to ACs - we don't support TSPEC so that's OK
1482 * Note that this field is reserved and unused by firmware not
1483 * supporting GO uAPSD, so it's safe to always do this.
1484 */
1485 for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT)
1486 cmd.awake_acs |= BIT(tid_to_ucode_ac[tid]);
1487
1488 /* If we're releasing frames from aggregation queues then check if the
1489 * all queues combined that we're releasing frames from have
1490 * - more frames than the service period, in which case more_data
1491 * needs to be set
1492 * - fewer than 'cnt' frames, in which case we need to adjust the
1493 * firmware command (but do that unconditionally)
1494 */
1495 if (agg) {
1496 int remaining = cnt;
1497
1498 spin_lock_bh(&mvmsta->lock);
1499 for_each_set_bit(tid, &_tids, IWL_MAX_TID_COUNT) {
1500 struct iwl_mvm_tid_data *tid_data;
1501 u16 n_queued;
1502
1503 tid_data = &mvmsta->tid_data[tid];
1504 if (WARN(tid_data->state != IWL_AGG_ON &&
1505 tid_data->state != IWL_EMPTYING_HW_QUEUE_DELBA,
1506 "TID %d state is %d\n",
1507 tid, tid_data->state)) {
1508 spin_unlock_bh(&mvmsta->lock);
1509 ieee80211_sta_eosp(sta);
1510 return;
1511 }
1512
1513 n_queued = iwl_mvm_tid_queued(tid_data);
1514 if (n_queued > remaining) {
1515 more_data = true;
1516 remaining = 0;
1517 break;
1518 }
1519 remaining -= n_queued;
1520 }
1521 spin_unlock_bh(&mvmsta->lock);
1522
1523 cmd.sleep_tx_count = cpu_to_le16(cnt - remaining);
1524 if (WARN_ON(cnt - remaining == 0)) {
1525 ieee80211_sta_eosp(sta);
1526 return;
1527 }
1528 }
1529
1530 /* Note: this is ignored by firmware not supporting GO uAPSD */
1531 if (more_data)
1532 cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_MOREDATA);
1533
1534 if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) {
1535 mvmsta->next_status_eosp = true;
1536 cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_PS_POLL);
1537 } else {
1538 cmd.sleep_state_flags |= cpu_to_le16(STA_SLEEP_STATE_UAPSD);
1539 }
1449 1540
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); 1541 ret = iwl_mvm_send_add_sta_cmd(mvm, CMD_ASYNC, &cmd);
1452 if (ret) 1542 if (ret)
1453 IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret); 1543 IWL_ERR(mvm, "Failed to send ADD_STA command (%d)\n", ret);
1454} 1544}
1545
1546int iwl_mvm_rx_eosp_notif(struct iwl_mvm *mvm,
1547 struct iwl_rx_cmd_buffer *rxb,
1548 struct iwl_device_cmd *cmd)
1549{
1550 struct iwl_rx_packet *pkt = rxb_addr(rxb);
1551 struct iwl_mvm_eosp_notification *notif = (void *)pkt->data;
1552 struct ieee80211_sta *sta;
1553 u32 sta_id = le32_to_cpu(notif->sta_id);
1554
1555 if (WARN_ON_ONCE(sta_id >= IWL_MVM_STATION_COUNT))
1556 return 0;
1557
1558 rcu_read_lock();
1559 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
1560 if (!IS_ERR_OR_NULL(sta))
1561 ieee80211_sta_eosp(sta);
1562 rcu_read_unlock();
1563
1564 return 0;
1565}