Commit 2167fa60 authored by Sriram R's avatar Sriram R Committed by Kalle Valo

ath11k: Add support for RX decapsulation offload

Add support for rx decapsulation offload by advertising
the support to mac80211 during registration. Also ensure
the frames have the RX_FLAG_8023 flag set in decap offload
frames before passing to mac80211.

Since the packets delivered to the driver are in 802.3 format, these
can be sent to the network core with minimal processing in mac80211.
This helps in releasing some CPU cycles in the host processor and
thereby improving the performance.

Two exceptions are made before passing decap frames, one is
for EAPOL packets since mac80211 8023 fast rx for the sta
is set only after authorization, other case is for multicast
packets to validate PN in mac80211. In both the cases the
decap frames are converted to 80211 frame and sent to mac80211.

Ethernet decap can be enabled by using frame_mode modparam:

insmod ath11k frame_mode=2

Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-00844-QCAHKSWPL_SILICONZ-1 v2
Co-developed-by: default avatarManikanta Pubbisetty <mpubbise@codeaurora.org>
Signed-off-by: default avatarManikanta Pubbisetty <mpubbise@codeaurora.org>
Signed-off-by: default avatarSriram R <srirrama@codeaurora.org>
Signed-off-by: default avatarJouni Malinen <jouni@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210721204217.120572-1-jouni@codeaurora.org
parent aadf7c81
...@@ -93,6 +93,8 @@ struct ath11k_skb_rxcb { ...@@ -93,6 +93,8 @@ struct ath11k_skb_rxcb {
bool is_first_msdu; bool is_first_msdu;
bool is_last_msdu; bool is_last_msdu;
bool is_continuation; bool is_continuation;
bool is_mcbc;
bool is_eapol;
struct hal_rx_desc *rx_desc; struct hal_rx_desc *rx_desc;
u8 err_rel_src; u8 err_rel_src;
u8 err_code; u8 err_code;
...@@ -100,6 +102,8 @@ struct ath11k_skb_rxcb { ...@@ -100,6 +102,8 @@ struct ath11k_skb_rxcb {
u8 unmapped; u8 unmapped;
u8 is_frag; u8 is_frag;
u8 tid; u8 tid;
u16 peer_id;
u16 seq_no;
}; };
enum ath11k_hw_rev { enum ath11k_hw_rev {
......
This diff is collapsed.
...@@ -496,6 +496,8 @@ struct hal_tlv_hdr { ...@@ -496,6 +496,8 @@ struct hal_tlv_hdr {
#define RX_MPDU_DESC_INFO0_DA_IDX_TIMEOUT BIT(29) #define RX_MPDU_DESC_INFO0_DA_IDX_TIMEOUT BIT(29)
#define RX_MPDU_DESC_INFO0_RAW_MPDU BIT(30) #define RX_MPDU_DESC_INFO0_RAW_MPDU BIT(30)
#define RX_MPDU_DESC_META_DATA_PEER_ID GENMASK(15, 0)
struct rx_mpdu_desc { struct rx_mpdu_desc {
u32 info0; /* %RX_MPDU_DESC_INFO */ u32 info0; /* %RX_MPDU_DESC_INFO */
u32 meta_data; u32 meta_data;
......
...@@ -374,6 +374,17 @@ static void ath11k_hw_ipq8074_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16 ...@@ -374,6 +374,17 @@ static void ath11k_hw_ipq8074_rx_desc_set_msdu_len(struct hal_rx_desc *desc, u16
desc->u.ipq8074.msdu_start.info1 = __cpu_to_le32(info); desc->u.ipq8074.msdu_start.info1 = __cpu_to_le32(info);
} }
static bool ath11k_hw_ipq8074_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.ipq8074.mpdu_start.info1) &
RX_MPDU_START_INFO1_MAC_ADDR2_VALID;
}
static u8 *ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
{
return desc->u.ipq8074.mpdu_start.addr2;
}
static static
struct rx_attention *ath11k_hw_ipq8074_rx_desc_get_attention(struct hal_rx_desc *desc) struct rx_attention *ath11k_hw_ipq8074_rx_desc_get_attention(struct hal_rx_desc *desc)
{ {
...@@ -545,6 +556,17 @@ static u8 *ath11k_hw_qcn9074_rx_desc_get_msdu_payload(struct hal_rx_desc *desc) ...@@ -545,6 +556,17 @@ static u8 *ath11k_hw_qcn9074_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
return &desc->u.qcn9074.msdu_payload[0]; return &desc->u.qcn9074.msdu_payload[0];
} }
static bool ath11k_hw_ipq9074_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.qcn9074.mpdu_start.info11) &
RX_MPDU_START_INFO11_MAC_ADDR2_VALID;
}
static u8 *ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
{
return desc->u.qcn9074.mpdu_start.addr2;
}
static bool ath11k_hw_wcn6855_rx_desc_get_first_msdu(struct hal_rx_desc *desc) static bool ath11k_hw_wcn6855_rx_desc_get_first_msdu(struct hal_rx_desc *desc)
{ {
return !!FIELD_GET(RX_MSDU_END_INFO2_FIRST_MSDU_WCN6855, return !!FIELD_GET(RX_MSDU_END_INFO2_FIRST_MSDU_WCN6855,
...@@ -705,6 +727,17 @@ static u8 *ath11k_hw_wcn6855_rx_desc_get_msdu_payload(struct hal_rx_desc *desc) ...@@ -705,6 +727,17 @@ static u8 *ath11k_hw_wcn6855_rx_desc_get_msdu_payload(struct hal_rx_desc *desc)
return &desc->u.wcn6855.msdu_payload[0]; return &desc->u.wcn6855.msdu_payload[0];
} }
static bool ath11k_hw_wcn6855_rx_desc_mac_addr2_valid(struct hal_rx_desc *desc)
{
return __le32_to_cpu(desc->u.wcn6855.mpdu_start.info1) &
RX_MPDU_START_INFO1_MAC_ADDR2_VALID;
}
static u8 *ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
{
return desc->u.wcn6855.mpdu_start.addr2;
}
static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab) static void ath11k_hw_wcn6855_reo_setup(struct ath11k_base *ab)
{ {
u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG; u32 reo_base = HAL_SEQ_WCSS_UMAC_REO_REG;
...@@ -801,6 +834,8 @@ const struct ath11k_hw_ops ipq8074_ops = { ...@@ -801,6 +834,8 @@ const struct ath11k_hw_ops ipq8074_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload, .rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup, .reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
}; };
const struct ath11k_hw_ops ipq6018_ops = { const struct ath11k_hw_ops ipq6018_ops = {
...@@ -837,6 +872,8 @@ const struct ath11k_hw_ops ipq6018_ops = { ...@@ -837,6 +872,8 @@ const struct ath11k_hw_ops ipq6018_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload, .rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup, .reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
}; };
const struct ath11k_hw_ops qca6390_ops = { const struct ath11k_hw_ops qca6390_ops = {
...@@ -873,6 +910,8 @@ const struct ath11k_hw_ops qca6390_ops = { ...@@ -873,6 +910,8 @@ const struct ath11k_hw_ops qca6390_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload, .rx_desc_get_msdu_payload = ath11k_hw_ipq8074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup, .reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq8074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq8074_rx_desc_mpdu_start_addr2,
}; };
const struct ath11k_hw_ops qcn9074_ops = { const struct ath11k_hw_ops qcn9074_ops = {
...@@ -909,6 +948,8 @@ const struct ath11k_hw_ops qcn9074_ops = { ...@@ -909,6 +948,8 @@ const struct ath11k_hw_ops qcn9074_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload, .rx_desc_get_msdu_payload = ath11k_hw_qcn9074_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_ipq8074_reo_setup, .reo_setup = ath11k_hw_ipq8074_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid, .mpdu_info_get_peerid = ath11k_hw_ipq8074_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_ipq9074_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_ipq9074_rx_desc_mpdu_start_addr2,
}; };
const struct ath11k_hw_ops wcn6855_ops = { const struct ath11k_hw_ops wcn6855_ops = {
...@@ -945,6 +986,8 @@ const struct ath11k_hw_ops wcn6855_ops = { ...@@ -945,6 +986,8 @@ const struct ath11k_hw_ops wcn6855_ops = {
.rx_desc_get_msdu_payload = ath11k_hw_wcn6855_rx_desc_get_msdu_payload, .rx_desc_get_msdu_payload = ath11k_hw_wcn6855_rx_desc_get_msdu_payload,
.reo_setup = ath11k_hw_wcn6855_reo_setup, .reo_setup = ath11k_hw_wcn6855_reo_setup,
.mpdu_info_get_peerid = ath11k_hw_wcn6855_mpdu_info_get_peerid, .mpdu_info_get_peerid = ath11k_hw_wcn6855_mpdu_info_get_peerid,
.rx_desc_mac_addr2_valid = ath11k_hw_wcn6855_rx_desc_mac_addr2_valid,
.rx_desc_mpdu_start_addr2 = ath11k_hw_wcn6855_rx_desc_mpdu_start_addr2,
}; };
#define ATH11K_TX_RING_MASK_0 0x1 #define ATH11K_TX_RING_MASK_0 0x1
......
...@@ -209,6 +209,8 @@ struct ath11k_hw_ops { ...@@ -209,6 +209,8 @@ struct ath11k_hw_ops {
u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc); u8 *(*rx_desc_get_msdu_payload)(struct hal_rx_desc *desc);
void (*reo_setup)(struct ath11k_base *ab); void (*reo_setup)(struct ath11k_base *ab);
u16 (*mpdu_info_get_peerid)(u8 *tlv_data); u16 (*mpdu_info_get_peerid)(u8 *tlv_data);
bool (*rx_desc_mac_addr2_valid)(struct hal_rx_desc *desc);
u8* (*rx_desc_mpdu_start_addr2)(struct hal_rx_desc *desc);
}; };
extern const struct ath11k_hw_ops ipq8074_ops; extern const struct ath11k_hw_ops ipq8074_ops;
......
...@@ -5370,7 +5370,8 @@ static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, ...@@ -5370,7 +5370,8 @@ static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET || if (ath11k_frame_mode != ATH11K_HW_TXRX_ETHERNET ||
(vif->type != NL80211_IFTYPE_STATION && (vif->type != NL80211_IFTYPE_STATION &&
vif->type != NL80211_IFTYPE_AP)) vif->type != NL80211_IFTYPE_AP))
vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; vif->offload_flags &= ~(IEEE80211_OFFLOAD_ENCAP_ENABLED |
IEEE80211_OFFLOAD_DECAP_ENABLED);
if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED) if (vif->offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED)
param_value = ATH11K_HW_TXRX_ETHERNET; param_value = ATH11K_HW_TXRX_ETHERNET;
...@@ -5386,6 +5387,22 @@ static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, ...@@ -5386,6 +5387,22 @@ static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw,
arvif->vdev_id, ret); arvif->vdev_id, ret);
vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; vif->offload_flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
} }
param_id = WMI_VDEV_PARAM_RX_DECAP_TYPE;
if (vif->offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED)
param_value = ATH11K_HW_TXRX_ETHERNET;
else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
param_value = ATH11K_HW_TXRX_RAW;
else
param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
param_id, param_value);
if (ret) {
ath11k_warn(ab, "failed to set vdev %d rx decap mode: %d\n",
arvif->vdev_id, ret);
vif->offload_flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
}
} }
static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
...@@ -7550,7 +7567,11 @@ static int __ath11k_mac_register(struct ath11k *ar) ...@@ -7550,7 +7567,11 @@ static int __ath11k_mac_register(struct ath11k *ar)
ieee80211_hw_set(ar->hw, QUEUE_CONTROL); ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG); ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK); ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
if (ath11k_frame_mode == ATH11K_HW_TXRX_ETHERNET) {
ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD); ieee80211_hw_set(ar->hw, SUPPORTS_TX_ENCAP_OFFLOAD);
ieee80211_hw_set(ar->hw, SUPPORTS_RX_DECAP_OFFLOAD);
}
if (cap->nss_ratio_enabled) if (cap->nss_ratio_enabled)
ieee80211_hw_set(ar->hw, SUPPORTS_VHT_EXT_NSS_BW); ieee80211_hw_set(ar->hw, SUPPORTS_VHT_EXT_NSS_BW);
......
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