diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/mac80211.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 59 |
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 | ||
1169 | static void | 1183 | static void |
1170 | iwl_mvm_mac_allow_buffered_frames(struct ieee80211_hw *hw, | 1184 | iwl_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); | 1198 | static void |
1199 | iwl_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 | ||
1187 | static void iwl_mvm_mac_sta_notify(struct ieee80211_hw *hw, | 1213 | static 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, |