]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.28/iwlwifi-mvm-pcie-adjust-a-msdu-tx_cmd-length-in-pcie.patch
Fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 4.9.28 / iwlwifi-mvm-pcie-adjust-a-msdu-tx_cmd-length-in-pcie.patch
CommitLineData
b74db2ac
GKH
1From 05e5a7e58d3f8f597ebe6f78aaa13a2656b78239 Mon Sep 17 00:00:00 2001
2From: Johannes Berg <johannes.berg@intel.com>
3Date: Fri, 2 Dec 2016 10:04:49 +0100
4Subject: iwlwifi: mvm/pcie: adjust A-MSDU tx_cmd length in PCIe
5
6From: Johannes Berg <johannes.berg@intel.com>
7
8commit 05e5a7e58d3f8f597ebe6f78aaa13a2656b78239 upstream.
9
10Instead of setting the tx_cmd length in the mvm code, which is
11complicated by the fact that DQA may want to temporarily store
12the SKB on the side, adjust the length in the PCIe code which
13also knows about this since it's responsible for duplicating
14all those headers that are account for in this code.
15
16As the PCIe code already relies on the tx_cmd->len field, this
17doesn't really introduce any new dependencies.
18
19To make this possible we need to move the memcpy() of the TX
20command until after it was updated.
21
22This does even simplify the code though, since the PCIe code
23already does a lot of manipulations to build A-MSDUs correctly
24and changing the length becomes a simple operation to see how
25much was added/removed, rather than predicting it.
26
27Fixes: 24afba7690e4 ("iwlwifi: mvm: support bss dynamic alloc/dealloc of queues")
28Signed-off-by: Johannes Berg <johannes.berg@intel.com>
29Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
30Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31
32---
33 drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 38 ++-------------------------
34 drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 23 +++++++++++++---
35 2 files changed, 22 insertions(+), 39 deletions(-)
36
37--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
38+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
39@@ -202,7 +202,6 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *
40 struct iwl_tx_cmd *tx_cmd,
41 struct ieee80211_tx_info *info, u8 sta_id)
42 {
43- struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
44 struct ieee80211_hdr *hdr = (void *)skb->data;
45 __le16 fc = hdr->frame_control;
46 u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
47@@ -284,9 +283,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *
48 tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
49
50 tx_cmd->tx_flags = cpu_to_le32(tx_flags);
51- /* Total # bytes to be transmitted */
52- tx_cmd->len = cpu_to_le16((u16)skb->len +
53- (uintptr_t)skb_info->driver_data[0]);
54+ /* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
55+ tx_cmd->len = cpu_to_le16((u16)skb->len);
56 tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
57 tx_cmd->sta_id = sta_id;
58
59@@ -555,9 +553,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mv
60 info.hw_queue != info.control.vif->cab_queue)))
61 return -1;
62
63- /* This holds the amsdu headers length */
64- skb_info->driver_data[0] = (void *)(uintptr_t)0;
65-
66 queue = info.hw_queue;
67
68 /*
69@@ -644,7 +639,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm
70 unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
71 bool ipv4 = (skb->protocol == htons(ETH_P_IP));
72 u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
73- u16 amsdu_add, snap_ip_tcp, pad, i = 0;
74+ u16 snap_ip_tcp, pad, i = 0;
75 unsigned int dbg_max_amsdu_len;
76 netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG;
77 u8 *qc, tid, txf;
78@@ -746,21 +741,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm
79
80 /* This skb fits in one single A-MSDU */
81 if (num_subframes * mss >= tcp_payload_len) {
82- struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
83-
84- /*
85- * Compute the length of all the data added for the A-MSDU.
86- * This will be used to compute the length to write in the TX
87- * command. We have: SNAP + IP + TCP for n -1 subframes and
88- * ETH header for n subframes. Note that the original skb
89- * already had one set of SNAP / IP / TCP headers.
90- */
91- num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
92- amsdu_add = num_subframes * sizeof(struct ethhdr) +
93- (num_subframes - 1) * (snap_ip_tcp + pad);
94- /* This holds the amsdu headers length */
95- skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add;
96-
97 __skb_queue_tail(mpdus_skb, skb);
98 return 0;
99 }
100@@ -799,14 +779,6 @@ segment:
101 ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
102
103 if (tcp_payload_len > mss) {
104- struct ieee80211_tx_info *skb_info =
105- IEEE80211_SKB_CB(tmp);
106-
107- num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
108- amsdu_add = num_subframes * sizeof(struct ethhdr) +
109- (num_subframes - 1) * (snap_ip_tcp + pad);
110- skb_info->driver_data[0] =
111- (void *)(uintptr_t)amsdu_add;
112 skb_shinfo(tmp)->gso_size = mss;
113 } else {
114 qc = ieee80211_get_qos_ctl((void *)tmp->data);
115@@ -1052,7 +1024,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm,
116 struct ieee80211_sta *sta)
117 {
118 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
119- struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
120 struct ieee80211_tx_info info;
121 struct sk_buff_head mpdus_skbs;
122 unsigned int payload_len;
123@@ -1066,9 +1037,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm,
124
125 memcpy(&info, skb->cb, sizeof(info));
126
127- /* This holds the amsdu headers length */
128- skb_info->driver_data[0] = (void *)(uintptr_t)0;
129-
130 if (!skb_is_gso(skb))
131 return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
132
133--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
134+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
135@@ -2096,6 +2096,7 @@ static int iwl_fill_data_tbs_amsdu(struc
136 struct iwl_cmd_meta *out_meta,
137 struct iwl_device_cmd *dev_cmd, u16 tb1_len)
138 {
139+ struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
140 struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
141 struct ieee80211_hdr *hdr = (void *)skb->data;
142 unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
143@@ -2145,6 +2146,13 @@ static int iwl_fill_data_tbs_amsdu(struc
144 */
145 skb_pull(skb, hdr_len + iv_len);
146
147+ /*
148+ * Remove the length of all the headers that we don't actually
149+ * have in the MPDU by themselves, but that we duplicate into
150+ * all the different MSDUs inside the A-MSDU.
151+ */
152+ le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
153+
154 tso_start(skb, &tso);
155
156 while (total_len) {
157@@ -2155,7 +2163,7 @@ static int iwl_fill_data_tbs_amsdu(struc
158 unsigned int hdr_tb_len;
159 dma_addr_t hdr_tb_phys;
160 struct tcphdr *tcph;
161- u8 *iph;
162+ u8 *iph, *subf_hdrs_start = hdr_page->pos;
163
164 total_len -= data_left;
165
166@@ -2216,6 +2224,8 @@ static int iwl_fill_data_tbs_amsdu(struc
167 hdr_tb_len, false);
168 trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr,
169 hdr_tb_len);
170+ /* add this subframe's headers' length to the tx_cmd */
171+ le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);
172
173 /* prepare the start_hdr for the next subframe */
174 start_hdr = hdr_page->pos;
175@@ -2408,9 +2418,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *
176 tb1_len = len;
177 }
178
179- /* The first TB points to bi-directional DMA data */
180- memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
181- IWL_FIRST_TB_SIZE);
182+ /*
183+ * The first TB points to bi-directional DMA data, we'll
184+ * memcpy the data into it later.
185+ */
186 iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
187 IWL_FIRST_TB_SIZE, true);
188
189@@ -2434,6 +2445,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *
190 goto out_err;
191 }
192
193+ /* building the A-MSDU might have changed this data, so memcpy it now */
194+ memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
195+ IWL_FIRST_TB_SIZE);
196+
197 tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
198 /* Set up entry for this TFD in Tx byte-count array */
199 iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),