Commit 93190fb0 authored by Avri Altman's avatar Avri Altman Committed by Emmanuel Grumbach

iwlwifi: mvm: Enable Rx Checksum hw

TCP software implementation on the host requires extensive computing
power.  Offloading even some of the TCP/IP stack to the NIC might save
a significant overhead. In order to enable this feature on our hw,
we need to configure it first. Once done, we mark this capability,
to be advertised later to the OS via ieee80211_register_hw.
The driver Rx indications for TCP Checksum is integrated within the
standard Rx status. The driver responds to those indications as follows:
If the frame was tested by hw and checksum ok report CHECKSUM_UNNECESSARY.
Otherwise, report CHECKSUM_NONE.
Signed-off-by: default avatarAvri Altman <avri.altman@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 869f3b15
...@@ -154,6 +154,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { ...@@ -154,6 +154,7 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \ .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
.d0i3 = true, \ .d0i3 = true, \
.features = NETIF_F_RXCSUM, \
.non_shared_ant = ANT_A, \ .non_shared_ant = ANT_A, \
.dccm_offset = IWL8260_DCCM_OFFSET, \ .dccm_offset = IWL8260_DCCM_OFFSET, \
.dccm_len = IWL8260_DCCM_LEN, \ .dccm_len = IWL8260_DCCM_LEN, \
......
...@@ -297,6 +297,7 @@ struct iwl_pwr_tx_backoff { ...@@ -297,6 +297,7 @@ struct iwl_pwr_tx_backoff {
* mode set * mode set
* @d0i3: device uses d0i3 instead of d3 * @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section * @nvm_hw_section_num: the ID of the HW NVM section
* @features: hw features, any combination of feature_whitelist
* @pwr_tx_backoffs: translation table between power limits and backoffs * @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
* @max_tx_agg_size: max TX aggregation size of the ADDBA request/response * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
...@@ -348,6 +349,7 @@ struct iwl_cfg { ...@@ -348,6 +349,7 @@ struct iwl_cfg {
bool no_power_up_nic_in_init; bool no_power_up_nic_in_init;
const char *default_nvm_file_B_step; const char *default_nvm_file_B_step;
const char *default_nvm_file_C_step; const char *default_nvm_file_C_step;
netdev_features_t features;
unsigned int max_rx_agg_size; unsigned int max_rx_agg_size;
bool disable_dummy_notification; bool disable_dummy_notification;
unsigned int max_tx_agg_size; unsigned int max_tx_agg_size;
......
...@@ -297,6 +297,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t; ...@@ -297,6 +297,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching * @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching
* @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
* @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command * @IWL_UCODE_TLV_CAPA_DC2DC_SUPPORT: supports DC2DC Command
* @IWL_UCODE_TLV_CAPA_CSUM_SUPPORT: supports TCP Checksum Offload
* @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics * @IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS: support radio and beacon statistics
* @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running * @IWL_UCODE_TLV_CAPA_BT_COEX_PLCR: enabled BT Coex packet level co-running
* @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different * @IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC: ucode supports LAR updates with different
...@@ -320,6 +321,7 @@ enum iwl_ucode_tlv_capa { ...@@ -320,6 +321,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH = (__force iwl_ucode_tlv_capa_t)13, IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH = (__force iwl_ucode_tlv_capa_t)13,
IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = (__force iwl_ucode_tlv_capa_t)18, IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = (__force iwl_ucode_tlv_capa_t)18,
IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19, IWL_UCODE_TLV_CAPA_DC2DC_CONFIG_SUPPORT = (__force iwl_ucode_tlv_capa_t)19,
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT = (__force iwl_ucode_tlv_capa_t)21,
IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = (__force iwl_ucode_tlv_capa_t)22, IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS = (__force iwl_ucode_tlv_capa_t)22,
IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = (__force iwl_ucode_tlv_capa_t)28, IWL_UCODE_TLV_CAPA_BT_COEX_PLCR = (__force iwl_ucode_tlv_capa_t)28,
IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29, IWL_UCODE_TLV_CAPA_LAR_MULTI_MCC = (__force iwl_ucode_tlv_capa_t)29,
......
...@@ -292,6 +292,9 @@ ...@@ -292,6 +292,9 @@
/*********************** END TX SCHEDULER *************************************/ /*********************** END TX SCHEDULER *************************************/
/* tcp checksum offload */
#define RX_EN_CSUM (0x00a00d88)
/* Oscillator clock */ /* Oscillator clock */
#define OSC_CLK (0xa04068) #define OSC_CLK (0xa04068)
#define OSC_CLK_FORCE_CONTROL (0x8) #define OSC_CLK_FORCE_CONTROL (0x8)
......
...@@ -1085,10 +1085,33 @@ struct iwl_rx_phy_info { ...@@ -1085,10 +1085,33 @@ struct iwl_rx_phy_info {
__le16 frame_time; __le16 frame_time;
} __packed; } __packed;
/*
* TCP offload Rx assist info
*
* bits 0:3 - reserved
* bits 4:7 - MIC CRC length
* bits 8:12 - MAC header length
* bit 13 - Padding indication
* bit 14 - A-AMSDU indication
* bit 15 - Offload enabled
*/
enum iwl_csum_rx_assist_info {
CSUM_RXA_RESERVED_MASK = 0x000f,
CSUM_RXA_MICSIZE_MASK = 0x00f0,
CSUM_RXA_HEADERLEN_MASK = 0x1f00,
CSUM_RXA_PADD = BIT(13),
CSUM_RXA_AMSDU = BIT(14),
CSUM_RXA_ENA = BIT(15)
};
/**
* struct iwl_rx_mpdu_res_start - phy info
* @assist: see CSUM_RX_ASSIST_ above
*/
struct iwl_rx_mpdu_res_start { struct iwl_rx_mpdu_res_start {
__le16 byte_count; __le16 byte_count;
__le16 reserved; __le16 assist;
} __packed; } __packed; /* _RX_MPDU_RES_START_API_S_VER_2 */
/** /**
* enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags * enum iwl_rx_phy_flags - to parse %iwl_rx_phy_info phy_flags
...@@ -1141,6 +1164,8 @@ enum iwl_rx_phy_flags { ...@@ -1141,6 +1164,8 @@ enum iwl_rx_phy_flags {
* @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP:
* @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT:
* @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame
* @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw
* @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
* @RX_MPDU_RES_STATUS_HASH_INDEX_MSK: * @RX_MPDU_RES_STATUS_HASH_INDEX_MSK:
* @RX_MPDU_RES_STATUS_STA_ID_MSK: * @RX_MPDU_RES_STATUS_STA_ID_MSK:
* @RX_MPDU_RES_STATUS_RRF_KILL: * @RX_MPDU_RES_STATUS_RRF_KILL:
...@@ -1170,6 +1195,8 @@ enum iwl_mvm_rx_status { ...@@ -1170,6 +1195,8 @@ enum iwl_mvm_rx_status {
RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13), RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP = BIT(13),
RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14), RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT = BIT(14),
RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15), RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME = BIT(15),
RX_MPDU_RES_STATUS_CSUM_DONE = BIT(16),
RX_MPDU_RES_STATUS_CSUM_OK = BIT(17),
RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000), RX_MPDU_RES_STATUS_HASH_INDEX_MSK = (0x3F0000),
RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000), RX_MPDU_RES_STATUS_STA_ID_MSK = (0x1f000000),
RX_MPDU_RES_STATUS_RRF_KILL = BIT(29), RX_MPDU_RES_STATUS_RRF_KILL = BIT(29),
......
...@@ -752,6 +752,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -752,6 +752,10 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
goto error; goto error;
} }
if (iwl_mvm_is_csum_supported(mvm) &&
mvm->cfg->features & NETIF_F_RXCSUM)
iwl_trans_write_prph(mvm->trans, RX_EN_CSUM, 0x3);
/* allow FW/transport low power modes if not during restart */ /* allow FW/transport low power modes if not during restart */
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN); iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
......
...@@ -649,6 +649,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -649,6 +649,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH; hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
} }
hw->netdev_features |= mvm->cfg->features;
if (!iwl_mvm_is_csum_supported(mvm))
hw->netdev_features &= ~NETIF_F_RXCSUM;
ret = ieee80211_register_hw(mvm->hw); ret = ieee80211_register_hw(mvm->hw);
if (ret) if (ret)
iwl_mvm_leds_exit(mvm); iwl_mvm_leds_exit(mvm);
...@@ -1651,6 +1655,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -1651,6 +1655,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
goto out_unlock; goto out_unlock;
} }
mvmvif->features |= hw->netdev_features;
ret = iwl_mvm_mac_ctxt_add(mvm, vif); ret = iwl_mvm_mac_ctxt_add(mvm, vif);
if (ret) if (ret)
goto out_release; goto out_release;
......
...@@ -357,6 +357,7 @@ struct iwl_mvm_vif_bf_data { ...@@ -357,6 +357,7 @@ struct iwl_mvm_vif_bf_data {
* # of received beacons accumulated over FW restart, and the current * # of received beacons accumulated over FW restart, and the current
* average signal of beacons retrieved from the firmware * average signal of beacons retrieved from the firmware
* @csa_failed: CSA failed to schedule time event, report an error later * @csa_failed: CSA failed to schedule time event, report an error later
* @features: hw features active for this vif
*/ */
struct iwl_mvm_vif { struct iwl_mvm_vif {
struct iwl_mvm *mvm; struct iwl_mvm *mvm;
...@@ -437,6 +438,9 @@ struct iwl_mvm_vif { ...@@ -437,6 +438,9 @@ struct iwl_mvm_vif {
/* Indicates that CSA countdown may be started */ /* Indicates that CSA countdown may be started */
bool csa_countdown; bool csa_countdown;
bool csa_failed; bool csa_failed;
/* TCP Checksum Offload */
netdev_features_t features;
}; };
static inline struct iwl_mvm_vif * static inline struct iwl_mvm_vif *
...@@ -943,6 +947,12 @@ static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm) ...@@ -943,6 +947,12 @@ static inline bool iwl_mvm_bt_is_rrc_supported(struct iwl_mvm *mvm)
IWL_MVM_BT_COEX_RRC; IWL_MVM_BT_COEX_RRC;
} }
static inline bool iwl_mvm_is_csum_supported(struct iwl_mvm *mvm)
{
return fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_CSUM_SUPPORT);
}
extern const u8 iwl_mvm_ac_to_tx_fifo[]; extern const u8 iwl_mvm_ac_to_tx_fifo[];
struct iwl_rate_info { struct iwl_rate_info {
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#include <linux/skbuff.h>
#include "iwl-trans.h" #include "iwl-trans.h"
#include "mvm.h" #include "mvm.h"
#include "fw-api.h" #include "fw-api.h"
...@@ -234,6 +235,19 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, ...@@ -234,6 +235,19 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
return 0; return 0;
} }
static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
struct sk_buff *skb,
u32 status)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
if (mvmvif->features & NETIF_F_RXCSUM &&
status & RX_MPDU_RES_STATUS_CSUM_DONE &&
status & RX_MPDU_RES_STATUS_CSUM_OK)
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
/* /*
* iwl_mvm_rx_rx_mpdu - REPLY_RX_MPDU_CMD handler * iwl_mvm_rx_rx_mpdu - REPLY_RX_MPDU_CMD handler
* *
...@@ -362,6 +376,9 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) ...@@ -362,6 +376,9 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
} }
} }
if (sta && ieee80211_is_data(hdr->frame_control))
iwl_mvm_rx_csum(sta, skb, rx_pkt_status);
rcu_read_unlock(); rcu_read_unlock();
/* set the preamble flag if appropriate */ /* set the preamble flag if appropriate */
......
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