|
@@ -2210,6 +2210,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|
|
__le16 fc;
|
|
|
u8 hdr_len;
|
|
|
u16 wifi_seq;
|
|
|
+ bool amsdu;
|
|
|
|
|
|
txq = &trans_pcie->txq[txq_id];
|
|
|
q = &txq->q;
|
|
@@ -2301,11 +2302,18 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|
|
*/
|
|
|
len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
|
|
|
hdr_len - IWL_HCMD_SCRATCHBUF_SIZE;
|
|
|
- tb1_len = ALIGN(len, 4);
|
|
|
-
|
|
|
- /* Tell NIC about any 2-byte padding after MAC header */
|
|
|
- if (tb1_len != len)
|
|
|
- tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
|
|
|
+ /* do not align A-MSDU to dword as the subframe header aligns it */
|
|
|
+ amsdu = ieee80211_is_data_qos(fc) &&
|
|
|
+ (*ieee80211_get_qos_ctl(hdr) &
|
|
|
+ IEEE80211_QOS_CTL_A_MSDU_PRESENT);
|
|
|
+ if (trans_pcie->sw_csum_tx || !amsdu) {
|
|
|
+ tb1_len = ALIGN(len, 4);
|
|
|
+ /* Tell NIC about any 2-byte padding after MAC header */
|
|
|
+ if (tb1_len != len)
|
|
|
+ tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
|
|
|
+ } else {
|
|
|
+ tb1_len = len;
|
|
|
+ }
|
|
|
|
|
|
/* The first TB points to the scratchbuf data - min_copy bytes */
|
|
|
memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
|
|
@@ -2323,8 +2331,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
|
|
goto out_err;
|
|
|
iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false);
|
|
|
|
|
|
- if (ieee80211_is_data_qos(fc) &&
|
|
|
- (*ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_A_MSDU_PRESENT)) {
|
|
|
+ if (amsdu) {
|
|
|
if (unlikely(iwl_fill_data_tbs_amsdu(trans, skb, txq, hdr_len,
|
|
|
out_meta, dev_cmd,
|
|
|
tb1_len)))
|