aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/mac80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/mac80211.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c59
1 files changed, 50 insertions, 9 deletions
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,