Commit 275896ab authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho

iwlwifi: mvm: properly enable IP header checksumming

The code was intended to enable IP header checksumming on AMSDUs, but
failed to really do so because the A-MSDU bit was set after all the
checksumming bits, and thus checking for A-MSDU could never be true.

Fix this by setting the A-MSDU bit before the offload bits.

Fixes: 5e6a98dc ("iwlwifi: mvm: enable TCP/UDP checksum support for 9000 family")
Reported-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent c42ff65d
...@@ -105,9 +105,9 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr, ...@@ -105,9 +105,9 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
static u16 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb, static u16 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_hdr *hdr, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info) struct ieee80211_tx_info *info,
u16 offload_assist)
{ {
u16 offload_assist = 0;
#if IS_ENABLED(CONFIG_INET) #if IS_ENABLED(CONFIG_INET)
u16 mh_len = ieee80211_hdrlen(hdr->frame_control); u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u8 protocol = 0; u8 protocol = 0;
...@@ -207,6 +207,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -207,6 +207,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
__le16 fc = hdr->frame_control; __le16 fc = hdr->frame_control;
u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags); u32 tx_flags = le32_to_cpu(tx_cmd->tx_flags);
u32 len = skb->len + FCS_LEN; u32 len = skb->len + FCS_LEN;
u16 offload_assist = 0;
u8 ac; u8 ac;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
...@@ -225,8 +226,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -225,8 +226,7 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
tx_cmd->tid_tspec = qc[0] & 0xf; tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL; tx_flags &= ~TX_CMD_FLG_SEQ_CTL;
if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
tx_cmd->offload_assist |= offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU));
} else if (ieee80211_is_back_req(fc)) { } else if (ieee80211_is_back_req(fc)) {
struct ieee80211_bar *bar = (void *)skb->data; struct ieee80211_bar *bar = (void *)skb->data;
u16 control = le16_to_cpu(bar->control); u16 control = le16_to_cpu(bar->control);
...@@ -291,11 +291,12 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -291,11 +291,12 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
/* padding is inserted later in transport */ /* padding is inserted later in transport */
if (ieee80211_hdrlen(fc) % 4 && if (ieee80211_hdrlen(fc) % 4 &&
!(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU)))) !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD)); offload_assist |= BIT(TX_CMD_OFFLD_PAD);
tx_cmd->offload_assist |= tx_cmd->offload_assist |=
cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info)); cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info,
offload_assist));
} }
static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
...@@ -481,7 +482,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -481,7 +482,7 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
if (iwl_mvm_has_new_tx_api(mvm)) { if (iwl_mvm_has_new_tx_api(mvm)) {
struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload; struct iwl_tx_cmd_gen2 *cmd = (void *)dev_cmd->payload;
u16 offload_assist = iwl_mvm_tx_csum(mvm, skb, hdr, info); u16 offload_assist = 0;
if (ieee80211_is_data_qos(hdr->frame_control)) { if (ieee80211_is_data_qos(hdr->frame_control)) {
u8 *qc = ieee80211_get_qos_ctl(hdr); u8 *qc = ieee80211_get_qos_ctl(hdr);
...@@ -490,6 +491,9 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -490,6 +491,9 @@ iwl_mvm_set_tx_params(struct iwl_mvm *mvm, struct sk_buff *skb,
offload_assist |= BIT(TX_CMD_OFFLD_AMSDU); offload_assist |= BIT(TX_CMD_OFFLD_AMSDU);
} }
offload_assist = iwl_mvm_tx_csum(mvm, skb, hdr, info,
offload_assist);
/* padding is inserted later in transport */ /* padding is inserted later in transport */
if (ieee80211_hdrlen(hdr->frame_control) % 4 && if (ieee80211_hdrlen(hdr->frame_control) % 4 &&
!(offload_assist & BIT(TX_CMD_OFFLD_AMSDU))) !(offload_assist & BIT(TX_CMD_OFFLD_AMSDU)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment