Commit 243874c6 authored by Manikanta Pubbisetty's avatar Manikanta Pubbisetty Committed by Kalle Valo

ath11k: handle RX fragments

IPQ8074 HW has support to verify the PN of the received frames.
For all frames except for fragmented ones, HW checks the PN and
delivers them to the driver. For fragmented frames, driver is
required to do a little more; it has to reassemble the fragments
and then reinject them to the HW for verifying the PN. Currently,
to keep the logic simple, PN verifcation is disabled in HW and is
handled in mac80211 for all the frames (fragmented and unfragmented).

On the contrary, offloading PN Validation to the HW brings important
benefits. It reduces CPU cycles spent on the host CPU for verifying
the same; helps in enabling features which improve performance like
mac80211 fast RX path, enabling multiple REO rings for parallel RX
processing, 802.11 decapsulation offloading. All these features are
dependent on PN offload which in turn is dependent on handling of
the received fragments in the driver.

When TKIP security is used, additional handling is required while
processing the fragments; since MIC is computed on an MSDU in TKIP,
only the last fragment has the MIC info. In this case, driver has to
compute the MIC after reassembly and compare it against the MIC
present in the frame. For this, MICHAEL_MIC kernel crypto library
APIs are used and the dependencies are appropriately set.
Signed-off-by: default avatarManikanta Pubbisetty <mpubbise@codeaurora.org>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 377c0a94
...@@ -3,6 +3,7 @@ config ATH11K ...@@ -3,6 +3,7 @@ config ATH11K
tristate "Qualcomm Technologies 802.11ax chipset support" tristate "Qualcomm Technologies 802.11ax chipset support"
depends on MAC80211 && HAS_DMA depends on MAC80211 && HAS_DMA
depends on REMOTEPROC depends on REMOTEPROC
depends on CRYPTO_MICHAEL_MIC
depends on ARCH_QCOM || COMPILE_TEST depends on ARCH_QCOM || COMPILE_TEST
select ATH_COMMON select ATH_COMMON
select QCOM_QMI_HELPERS select QCOM_QMI_HELPERS
......
...@@ -77,6 +77,7 @@ struct ath11k_skb_rxcb { ...@@ -77,6 +77,7 @@ struct ath11k_skb_rxcb {
u8 err_code; u8 err_code;
u8 mac_id; u8 mac_id;
u8 unmapped; u8 unmapped;
u8 is_frag;
}; };
enum ath11k_hw_rev { enum ath11k_hw_rev {
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
*/ */
#include <crypto/hash.h>
#include "core.h" #include "core.h"
#include "dp_tx.h" #include "dp_tx.h"
#include "hal_tx.h" #include "hal_tx.h"
...@@ -33,6 +34,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr) ...@@ -33,6 +34,7 @@ void ath11k_dp_peer_cleanup(struct ath11k *ar, int vdev_id, const u8 *addr)
} }
ath11k_peer_rx_tid_cleanup(ar, peer); ath11k_peer_rx_tid_cleanup(ar, peer);
crypto_free_shash(peer->tfm_mmic);
spin_unlock_bh(&ab->base_lock); spin_unlock_bh(&ab->base_lock);
} }
...@@ -65,6 +67,12 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr) ...@@ -65,6 +67,12 @@ int ath11k_dp_peer_setup(struct ath11k *ar, int vdev_id, const u8 *addr)
} }
} }
ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id);
if (ret) {
ath11k_warn(ab, "failed to setup rx defrag context\n");
return ret;
}
/* TODO: Setup other peer specific resource used in data path */ /* TODO: Setup other peer specific resource used in data path */
return 0; return 0;
......
...@@ -22,6 +22,18 @@ struct dp_rx_tid { ...@@ -22,6 +22,18 @@ struct dp_rx_tid {
u32 size; u32 size;
u32 ba_win_sz; u32 ba_win_sz;
bool active; bool active;
/* Info related to rx fragments */
u32 cur_sn;
u16 last_frag_no;
u16 rx_frag_bitmap;
struct sk_buff_head rx_frags;
struct hal_reo_dest_ring *dst_ring_desc;
/* Timer info related to fragments */
struct timer_list frag_timer;
struct ath11k_base *ab;
}; };
#define DP_REO_DESC_FREE_TIMEOUT_MS 1000 #define DP_REO_DESC_FREE_TIMEOUT_MS 1000
......
This diff is collapsed.
...@@ -84,5 +84,6 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id, ...@@ -84,5 +84,6 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
gfp_t gfp); gfp_t gfp);
int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar); int ath11k_dp_rx_pdev_mon_detach(struct ath11k *ar);
int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar); int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar);
int ath11k_peer_rx_frag_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id);
#endif /* ATH11K_DP_RX_H */ #endif /* ATH11K_DP_RX_H */
...@@ -2384,11 +2384,19 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -2384,11 +2384,19 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
spin_lock_bh(&ab->base_lock); spin_lock_bh(&ab->base_lock);
peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr); peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
if (peer && cmd == SET_KEY) if (peer && cmd == SET_KEY) {
peer->keys[key->keyidx] = key; peer->keys[key->keyidx] = key;
else if (peer && cmd == DISABLE_KEY) if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
peer->ucast_keyidx = key->keyidx;
else
peer->mcast_keyidx = key->keyidx;
} else if (peer && cmd == DISABLE_KEY) {
peer->keys[key->keyidx] = NULL; peer->keys[key->keyidx] = NULL;
else if (!peer) if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
peer->ucast_keyidx = 0;
else
peer->mcast_keyidx = 0;
} else if (!peer)
/* impossible unless FW goes crazy */ /* impossible unless FW goes crazy */
ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr); ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
spin_unlock_bh(&ab->base_lock); spin_unlock_bh(&ab->base_lock);
......
...@@ -17,6 +17,13 @@ struct ath11k_peer { ...@@ -17,6 +17,13 @@ struct ath11k_peer {
/* protected by ab->data_lock */ /* protected by ab->data_lock */
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
/* Info used in MMIC verification of
* RX fragments
*/
struct crypto_shash *tfm_mmic;
u8 mcast_keyidx;
u8 ucast_keyidx;
}; };
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id); void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
......
...@@ -342,7 +342,7 @@ struct rx_attention { ...@@ -342,7 +342,7 @@ struct rx_attention {
#define RX_MPDU_START_INFO0_PROTO_VER_ERR BIT(12) #define RX_MPDU_START_INFO0_PROTO_VER_ERR BIT(12)
#define RX_MPDU_START_INFO0_AST_LOOKUP_VALID BIT(13) #define RX_MPDU_START_INFO0_AST_LOOKUP_VALID BIT(13)
#define RX_MPDU_START_INFO1_MPDU_CTRL_VALID BIT(0) #define RX_MPDU_START_INFO1_MPDU_FCTRL_VALID BIT(0)
#define RX_MPDU_START_INFO1_MPDU_DUR_VALID BIT(1) #define RX_MPDU_START_INFO1_MPDU_DUR_VALID BIT(1)
#define RX_MPDU_START_INFO1_MAC_ADDR1_VALID BIT(2) #define RX_MPDU_START_INFO1_MAC_ADDR1_VALID BIT(2)
#define RX_MPDU_START_INFO1_MAC_ADDR2_VALID BIT(3) #define RX_MPDU_START_INFO1_MAC_ADDR2_VALID BIT(3)
......
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