| From foo@baz Sat Nov 10 10:48:43 PST 2018 |
| From: Sara Sharon <sara.sharon@intel.com> |
| Date: Tue, 1 May 2018 14:54:22 +0300 |
| Subject: iwlwifi: mvm: fix BAR seq ctrl reporting |
| |
| From: Sara Sharon <sara.sharon@intel.com> |
| |
| [ Upstream commit 941ab4eb66c10bc5c7234e83a7a858b2806ed151 ] |
| |
| There is a bug in FW where the sequence control may be |
| incorrect, and the driver overrides it with the value |
| of the ieee80211 header. |
| |
| However, in BAR there is no sequence control in the header, |
| which result with arbitrary sequence. |
| |
| This access to an unknown location is bad and it makes the |
| logs very confusing - so fix it. |
| |
| Signed-off-by: Sara Sharon <sara.sharon@intel.com> |
| Signed-off-by: Luca Coelho <luciano.coelho@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 9 +++++---- |
| 1 file changed, 5 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c |
| +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c |
| @@ -1385,6 +1385,7 @@ static void iwl_mvm_rx_tx_cmd_single(str |
| 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++; |
| @@ -1429,11 +1430,11 @@ static void iwl_mvm_rx_tx_cmd_single(str |
| 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; |