You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
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: Manikanta Pubbisetty <mpubbise@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
committed by
Kalle Valo
parent
377c0a94ad
commit
243874c64c
@@ -3,6 +3,7 @@ config ATH11K
|
||||
tristate "Qualcomm Technologies 802.11ax chipset support"
|
||||
depends on MAC80211 && HAS_DMA
|
||||
depends on REMOTEPROC
|
||||
depends on CRYPTO_MICHAEL_MIC
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
select ATH_COMMON
|
||||
select QCOM_QMI_HELPERS
|
||||
|
||||
@@ -77,6 +77,7 @@ struct ath11k_skb_rxcb {
|
||||
u8 err_code;
|
||||
u8 mac_id;
|
||||
u8 unmapped;
|
||||
u8 is_frag;
|
||||
};
|
||||
|
||||
enum ath11k_hw_rev {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <crypto/hash.h>
|
||||
#include "core.h"
|
||||
#include "dp_tx.h"
|
||||
#include "hal_tx.h"
|
||||
@@ -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);
|
||||
crypto_free_shash(peer->tfm_mmic);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -22,6 +22,18 @@ struct dp_rx_tid {
|
||||
u32 size;
|
||||
u32 ba_win_sz;
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -84,5 +84,6 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
|
||||
gfp_t gfp);
|
||||
int ath11k_dp_rx_pdev_mon_detach(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 */
|
||||
|
||||
@@ -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);
|
||||
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;
|
||||
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;
|
||||
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 */
|
||||
ath11k_warn(ab, "peer %pM disappeared!\n", peer_addr);
|
||||
spin_unlock_bh(&ab->base_lock);
|
||||
|
||||
@@ -17,6 +17,13 @@ struct ath11k_peer {
|
||||
/* protected by ab->data_lock */
|
||||
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 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);
|
||||
|
||||
@@ -342,7 +342,7 @@ struct rx_attention {
|
||||
#define RX_MPDU_START_INFO0_PROTO_VER_ERR BIT(12)
|
||||
#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_MAC_ADDR1_VALID BIT(2)
|
||||
#define RX_MPDU_START_INFO1_MAC_ADDR2_VALID BIT(3)
|
||||
|
||||
Reference in New Issue
Block a user