| From 85f84b1ab6be2bd79e27dfbb463ffe381202782f Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Fri, 2 Dec 2016 09:57:40 +0100 |
| Subject: [PATCH] iwlwifi: mvm: overwrite skb info later |
| |
| commit bd05a5bd6b11d7fd26a668de83c5cb996de05f8f upstream. |
| |
| We don't really need clear the skb's status area nor store the |
| dev_cmd into it until we really commit to the frame by handing |
| it to the transport - defer those operations until just before |
| we do that. |
| |
| This doesn't entirely fix the bug with frames not getting sent |
| out after having been deferred due to DQA, because it doesn't |
| restore the info->driver_data[0] place that was already set to |
| zero (or another value) by the A-MSDU logic. |
| |
| Fixes: 24afba7690e4 ("iwlwifi: mvm: support bss dynamic alloc/dealloc of queues") |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Luca Coelho <luciano.coelho@intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c |
| index a0c1e3d07db5..b392b3a8121b 100644 |
| --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c |
| +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c |
| @@ -459,7 +459,6 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, |
| struct ieee80211_sta *sta, u8 sta_id) |
| { |
| struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
| - struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); |
| struct iwl_device_cmd *dev_cmd; |
| struct iwl_tx_cmd *tx_cmd; |
| |
| @@ -479,12 +478,18 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, |
| |
| iwl_mvm_set_tx_cmd_rate(mvm, tx_cmd, info, sta, hdr->frame_control); |
| |
| + return dev_cmd; |
| +} |
| + |
| +static void iwl_mvm_skb_prepare_status(struct sk_buff *skb, |
| + struct iwl_device_cmd *cmd) |
| +{ |
| + struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb); |
| + |
| memset(&skb_info->status, 0, sizeof(skb_info->status)); |
| memset(skb_info->driver_data, 0, sizeof(skb_info->driver_data)); |
| |
| - skb_info->driver_data[1] = dev_cmd; |
| - |
| - return dev_cmd; |
| + skb_info->driver_data[1] = cmd; |
| } |
| |
| static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, |
| @@ -577,6 +582,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) |
| if (!dev_cmd) |
| return -1; |
| |
| + /* From now on, we cannot access info->control */ |
| + iwl_mvm_skb_prepare_status(skb, dev_cmd); |
| + |
| tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; |
| |
| /* Copy MAC header from skb into command buffer */ |
| @@ -871,7 +879,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, |
| goto drop; |
| |
| tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; |
| - /* From now on, we cannot access info->control */ |
| |
| /* |
| * we handle that entirely ourselves -- for uAPSD the firmware |
| @@ -962,6 +969,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, |
| IWL_DEBUG_TX(mvm, "TX to [%d|%d] Q:%d - seq: 0x%x\n", mvmsta->sta_id, |
| tid, txq_id, IEEE80211_SEQ_TO_SN(seq_number)); |
| |
| + /* From now on, we cannot access info->control */ |
| + iwl_mvm_skb_prepare_status(skb, dev_cmd); |
| + |
| if (iwl_trans_tx(mvm->trans, skb, dev_cmd, txq_id)) |
| goto drop_unlock_sta; |
| |
| -- |
| 2.12.0 |
| |