[PATCH 4.10 047/129] iwlwifi: mvm: overwrite skb info later

From: Greg Kroah-Hartman
Date: Thu May 11 2017 - 10:16:41 EST


4.10-stable review patch. If anyone has any objections, please let me know.

------------------

From: Johannes Berg <johannes.berg@xxxxxxxxx>

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@xxxxxxxxx>
Signed-off-by: Luca Coelho <luciano.coelho@xxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

---
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)

--- 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 *mv
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 *mv

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,
@@ -598,6 +603,9 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
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 */
@@ -908,7 +916,6 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv
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
@@ -1015,6 +1022,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mv
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;