aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tx.c38
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/tx.c23
2 files changed, 22 insertions, 39 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index e129661e4d99..1d116c06cd1c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -202,7 +202,6 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
202 struct iwl_tx_cmd *tx_cmd, 202 struct iwl_tx_cmd *tx_cmd,
203 struct ieee80211_tx_info *info, u8 sta_id) 203 struct ieee80211_tx_info *info, u8 sta_id)
204{ 204{
205 struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
206 struct ieee80211_hdr *hdr = (void *)skb->data; 205 struct ieee80211_hdr *hdr = (void *)skb->data;
207 __le16 fc = hdr->frame_control; 206 __le16 fc = hdr->frame_control;
208 u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); 207 u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
@@ -284,9 +283,8 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
284 tx_flags |= TX_CMD_FLG_WRITE_TX_POWER; 283 tx_flags |= TX_CMD_FLG_WRITE_TX_POWER;
285 284
286 tx_cmd->tx_flags = cpu_to_le32(tx_flags); 285 tx_cmd->tx_flags = cpu_to_le32(tx_flags);
287 /* Total # bytes to be transmitted */ 286 /* Total # bytes to be transmitted - PCIe code will adjust for A-MSDU */
288 tx_cmd->len = cpu_to_le16((u16)skb->len + 287 tx_cmd->len = cpu_to_le16((u16)skb->len);
289 (uintptr_t)skb_info->driver_data[0]);
290 tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); 288 tx_cmd->life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
291 tx_cmd->sta_id = sta_id; 289 tx_cmd->sta_id = sta_id;
292 290
@@ -555,9 +553,6 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
555 info.hw_queue != info.control.vif->cab_queue))) 553 info.hw_queue != info.control.vif->cab_queue)))
556 return -1; 554 return -1;
557 555
558 /* This holds the amsdu headers length */
559 skb_info->driver_data[0] = (void *)(uintptr_t)0;
560
561 queue = info.hw_queue; 556 queue = info.hw_queue;
562 557
563 /* 558 /*
@@ -644,7 +639,7 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
644 unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len; 639 unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len;
645 bool ipv4 = (skb->protocol == htons(ETH_P_IP)); 640 bool ipv4 = (skb->protocol == htons(ETH_P_IP));
646 u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; 641 u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0;
647 u16 amsdu_add, snap_ip_tcp, pad, i = 0; 642 u16 snap_ip_tcp, pad, i = 0;
648 unsigned int dbg_max_amsdu_len; 643 unsigned int dbg_max_amsdu_len;
649 netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG; 644 netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG;
650 u8 *qc, tid, txf; 645 u8 *qc, tid, txf;
@@ -746,21 +741,6 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb,
746 741
747 /* This skb fits in one single A-MSDU */ 742 /* This skb fits in one single A-MSDU */
748 if (num_subframes * mss >= tcp_payload_len) { 743 if (num_subframes * mss >= tcp_payload_len) {
749 struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
750
751 /*
752 * Compute the length of all the data added for the A-MSDU.
753 * This will be used to compute the length to write in the TX
754 * command. We have: SNAP + IP + TCP for n -1 subframes and
755 * ETH header for n subframes. Note that the original skb
756 * already had one set of SNAP / IP / TCP headers.
757 */
758 num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
759 amsdu_add = num_subframes * sizeof(struct ethhdr) +
760 (num_subframes - 1) * (snap_ip_tcp + pad);
761 /* This holds the amsdu headers length */
762 skb_info->driver_data[0] = (void *)(uintptr_t)amsdu_add;
763
764 __skb_queue_tail(mpdus_skb, skb); 744 __skb_queue_tail(mpdus_skb, skb);
765 return 0; 745 return 0;
766 } 746 }
@@ -799,14 +779,6 @@ segment:
799 ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); 779 ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes);
800 780
801 if (tcp_payload_len > mss) { 781 if (tcp_payload_len > mss) {
802 struct ieee80211_tx_info *skb_info =
803 IEEE80211_SKB_CB(tmp);
804
805 num_subframes = DIV_ROUND_UP(tcp_payload_len, mss);
806 amsdu_add = num_subframes * sizeof(struct ethhdr) +
807 (num_subframes - 1) * (snap_ip_tcp + pad);
808 skb_info->driver_data[0] =
809 (void *)(uintptr_t)amsdu_add;
810 skb_shinfo(tmp)->gso_size = mss; 782 skb_shinfo(tmp)->gso_size = mss;
811 } else { 783 } else {
812 qc = ieee80211_get_qos_ctl((void *)tmp->data); 784 qc = ieee80211_get_qos_ctl((void *)tmp->data);
@@ -1052,7 +1024,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
1052 struct ieee80211_sta *sta) 1024 struct ieee80211_sta *sta)
1053{ 1025{
1054 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); 1026 struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1055 struct ieee80211_tx_info *skb_info = IEEE80211_SKB_CB(skb);
1056 struct ieee80211_tx_info info; 1027 struct ieee80211_tx_info info;
1057 struct sk_buff_head mpdus_skbs; 1028 struct sk_buff_head mpdus_skbs;
1058 unsigned int payload_len; 1029 unsigned int payload_len;
@@ -1066,9 +1037,6 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
1066 1037
1067 memcpy(&info, skb->cb, sizeof(info)); 1038 memcpy(&info, skb->cb, sizeof(info));
1068 1039
1069 /* This holds the amsdu headers length */
1070 skb_info->driver_data[0] = (void *)(uintptr_t)0;
1071
1072 if (!skb_is_gso(skb)) 1040 if (!skb_is_gso(skb))
1073 return iwl_mvm_tx_mpdu(mvm, skb, &info, sta); 1041 return iwl_mvm_tx_mpdu(mvm, skb, &info, sta);
1074 1042
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
index 5f840f16f40b..e1bfc9522cbe 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c
@@ -2096,6 +2096,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
2096 struct iwl_cmd_meta *out_meta, 2096 struct iwl_cmd_meta *out_meta,
2097 struct iwl_device_cmd *dev_cmd, u16 tb1_len) 2097 struct iwl_device_cmd *dev_cmd, u16 tb1_len)
2098{ 2098{
2099 struct iwl_tx_cmd *tx_cmd = (void *)dev_cmd->payload;
2099 struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; 2100 struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
2100 struct ieee80211_hdr *hdr = (void *)skb->data; 2101 struct ieee80211_hdr *hdr = (void *)skb->data;
2101 unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room; 2102 unsigned int snap_ip_tcp_hdrlen, ip_hdrlen, total_len, hdr_room;
@@ -2145,6 +2146,13 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
2145 */ 2146 */
2146 skb_pull(skb, hdr_len + iv_len); 2147 skb_pull(skb, hdr_len + iv_len);
2147 2148
2149 /*
2150 * Remove the length of all the headers that we don't actually
2151 * have in the MPDU by themselves, but that we duplicate into
2152 * all the different MSDUs inside the A-MSDU.
2153 */
2154 le16_add_cpu(&tx_cmd->len, -snap_ip_tcp_hdrlen);
2155
2148 tso_start(skb, &tso); 2156 tso_start(skb, &tso);
2149 2157
2150 while (total_len) { 2158 while (total_len) {
@@ -2155,7 +2163,7 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
2155 unsigned int hdr_tb_len; 2163 unsigned int hdr_tb_len;
2156 dma_addr_t hdr_tb_phys; 2164 dma_addr_t hdr_tb_phys;
2157 struct tcphdr *tcph; 2165 struct tcphdr *tcph;
2158 u8 *iph; 2166 u8 *iph, *subf_hdrs_start = hdr_page->pos;
2159 2167
2160 total_len -= data_left; 2168 total_len -= data_left;
2161 2169
@@ -2216,6 +2224,8 @@ static int iwl_fill_data_tbs_amsdu(struct iwl_trans *trans, struct sk_buff *skb,
2216 hdr_tb_len, false); 2224 hdr_tb_len, false);
2217 trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr, 2225 trace_iwlwifi_dev_tx_tso_chunk(trans->dev, start_hdr,
2218 hdr_tb_len); 2226 hdr_tb_len);
2227 /* add this subframe's headers' length to the tx_cmd */
2228 le16_add_cpu(&tx_cmd->len, hdr_page->pos - subf_hdrs_start);
2219 2229
2220 /* prepare the start_hdr for the next subframe */ 2230 /* prepare the start_hdr for the next subframe */
2221 start_hdr = hdr_page->pos; 2231 start_hdr = hdr_page->pos;
@@ -2408,9 +2418,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
2408 tb1_len = len; 2418 tb1_len = len;
2409 } 2419 }
2410 2420
2411 /* The first TB points to bi-directional DMA data */ 2421 /*
2412 memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr, 2422 * The first TB points to bi-directional DMA data, we'll
2413 IWL_FIRST_TB_SIZE); 2423 * memcpy the data into it later.
2424 */
2414 iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, 2425 iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
2415 IWL_FIRST_TB_SIZE, true); 2426 IWL_FIRST_TB_SIZE, true);
2416 2427
@@ -2434,6 +2445,10 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
2434 goto out_err; 2445 goto out_err;
2435 } 2446 }
2436 2447
2448 /* building the A-MSDU might have changed this data, so memcpy it now */
2449 memcpy(&txq->first_tb_bufs[txq->write_ptr], &dev_cmd->hdr,
2450 IWL_FIRST_TB_SIZE);
2451
2437 tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr); 2452 tfd = iwl_pcie_get_tfd(trans_pcie, txq, txq->write_ptr);
2438 /* Set up entry for this TFD in Tx byte-count array */ 2453 /* Set up entry for this TFD in Tx byte-count array */
2439 iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len), 2454 iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len),