|
@@ -1480,6 +1480,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
|
|
while (!skb_queue_empty(&skbs)) {
|
|
|
struct sk_buff *skb = __skb_dequeue(&skbs);
|
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
+ struct ieee80211_hdr *hdr = (void *)skb->data;
|
|
|
bool flushed = false;
|
|
|
|
|
|
skb_freed++;
|
|
@@ -1524,11 +1525,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
|
|
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
|
|
|
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
|
|
|
|
|
- /* W/A FW bug: seq_ctl is wrong when the status isn't success */
|
|
|
- if (status != TX_STATUS_SUCCESS) {
|
|
|
- struct ieee80211_hdr *hdr = (void *)skb->data;
|
|
|
+ /* W/A FW bug: seq_ctl is wrong upon failure / BAR frame */
|
|
|
+ if (ieee80211_is_back_req(hdr->frame_control))
|
|
|
+ seq_ctl = 0;
|
|
|
+ else if (status != TX_STATUS_SUCCESS)
|
|
|
seq_ctl = le16_to_cpu(hdr->seq_ctrl);
|
|
|
- }
|
|
|
|
|
|
if (unlikely(!seq_ctl)) {
|
|
|
struct ieee80211_hdr *hdr = (void *)skb->data;
|