qcacmn: Enable PN check for 2K-jump and OOR frames

Currently the EAPOL/ARP/DHCP frames arriving as 2K-jump
or out-of-order frmaes are being delivered to the network
stack, without checking for the packet-number sequence.

WCN7850 has hardware support to provide the packet number
of the previous successful re-ordered packet from hardware.
Use this feature to check if the packet-number are in proper
sequence for these EAPOL/ARP/DHCP packets arriving as 2k-jump
or out-of-order packets before submitting it to the network
stack.

Change-Id: I1078452afce4bc00b2509436295e5bd80000feb4
CRs-Fixed: 2965086
This commit is contained in:
Rakesh Pillai
2021-03-29 23:48:32 -07:00
committed by Madan Koyyalamudi
parent e4c918b6ca
commit 5d44eac10a
8 changed files with 259 additions and 3 deletions

View File

@@ -13393,6 +13393,8 @@ void *dp_soc_init(struct dp_soc *soc, HTC_HANDLE htc_handle,
hal_reo_set_err_dst_remap(soc->hal_soc);
soc->features.pn_in_reo_dest = hal_reo_enable_pn_in_dest(soc->hal_soc);
qdf_atomic_set(&soc->cmn_init_done, 1);
qdf_nbuf_queue_init(&soc->htt_stats.msg);

View File

@@ -510,6 +510,32 @@ free_nbuf:
qdf_nbuf_free(nbuf);
}
/**
* dp_rx_err_nbuf_pn_check() - Check if the PN number of this current packet
* is a monotonous increment of packet number
* from the previous successfully re-ordered
* frame.
* @soc: Datapath SOC handle
* @ring_desc: REO ring descriptor
* @nbuf: Current packet
*
* Return: QDF_STATUS_SUCCESS, if the pn check passes, else QDF_STATUS_E_FAILURE
*/
static inline QDF_STATUS
dp_rx_err_nbuf_pn_check(struct dp_soc *soc, hal_ring_desc_t ring_desc,
qdf_nbuf_t nbuf)
{
uint64_t prev_pn, curr_pn;
hal_rx_reo_prev_pn_get(soc->hal_soc, ring_desc, &prev_pn);
hal_rx_tlv_get_pn_num(soc->hal_soc, qdf_nbuf_data(nbuf), &curr_pn);
if (curr_pn > prev_pn)
return QDF_STATUS_SUCCESS;
return QDF_STATUS_E_FAILURE;
}
/**
* dp_rx_reo_err_entry_process() - Handles for REO error entry processing
*
@@ -551,6 +577,7 @@ dp_rx_reo_err_entry_process(struct dp_soc *soc,
qdf_nbuf_t head_nbuf = NULL;
qdf_nbuf_t tail_nbuf = NULL;
uint16_t msdu_processed = 0;
QDF_STATUS status;
bool ret;
peer_id = DP_PEER_METADATA_PEER_ID_GET(
@@ -615,6 +642,22 @@ more_msdu_link_desc:
DP_STATS_INC(soc, rx.err.reo_err_oor_sg_count, 1);
}
if (soc->features.pn_in_reo_dest) {
status = dp_rx_err_nbuf_pn_check(soc, ring_desc, nbuf);
if (QDF_IS_STATUS_ERROR(status)) {
DP_STATS_INC(soc, rx.err.pn_in_dest_check_fail,
1);
qdf_nbuf_free(nbuf);
goto process_next_msdu;
}
hal_rx_tlv_populate_mpdu_desc_info(soc->hal_soc,
qdf_nbuf_data(nbuf),
mpdu_desc_info);
peer_id = DP_PEER_METADATA_PEER_ID_GET(
mpdu_desc_info->peer_meta_data);
}
switch (err_code) {
case HAL_REO_ERR_REGULAR_FRAME_2K_JUMP:
/*
@@ -1948,6 +1991,27 @@ static int dp_rx_err_exception(struct dp_soc *soc, hal_ring_desc_t ring_desc)
}
#endif /* HANDLE_RX_REROUTE_ERR */
/**
* dp_rx_err_is_pn_check_needed() - Check if the packet number check is needed
* for this frame received in REO error ring.
* @soc: Datapath SOC handle
* @error: REO error detected or not
* @error_code: Error code in case of REO error
*
* Return: true if pn check if needed in software,
* false, if pn check if not needed.
*/
static inline bool
dp_rx_err_is_pn_check_needed(struct dp_soc *soc, uint8_t error,
uint32_t error_code)
{
return (soc->features.pn_in_reo_dest &&
(error == HAL_REO_ERROR_DETECTED &&
(hal_rx_reo_is_2k_jump(error_code) ||
hal_rx_reo_is_oor_error(error_code) ||
hal_rx_reo_is_bar_oor_2k_jump(error_code))));
}
uint32_t
dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
hal_ring_handle_t hal_ring_hdl, uint32_t quota)
@@ -1972,6 +2036,7 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
QDF_STATUS status;
bool ret;
uint32_t error_code = 0;
bool sw_pn_check_needed;
/* Debug -- Remove later */
qdf_assert(soc && hal_ring_hdl);
@@ -2006,10 +2071,23 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
error_code = hal_rx_get_reo_error_code(hal_soc,
ring_desc);
/* Get the MPDU DESC info */
hal_rx_mpdu_desc_info_get(hal_soc, ring_desc, &mpdu_desc_info);
qdf_mem_set(&mpdu_desc_info, sizeof(mpdu_desc_info), 0);
sw_pn_check_needed = dp_rx_err_is_pn_check_needed(soc,
err_status,
error_code);
if (!sw_pn_check_needed) {
/*
* MPDU desc info will be present in the REO desc
* only in the below scenarios
* 1) pn_in_dest_disabled: always
* 2) pn_in_dest enabled: All cases except 2k-jup
* and OOR errors
*/
hal_rx_mpdu_desc_info_get(hal_soc, ring_desc,
&mpdu_desc_info);
}
if (mpdu_desc_info.msdu_count == 0)
if (HAL_RX_REO_DESC_MSDU_COUNT_GET(ring_desc) == 0)
goto next_entry;
/*
@@ -2074,6 +2152,10 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
mac_id = rx_desc->pool_id;
if (sw_pn_check_needed) {
goto process_oor_2k_jump;
}
if (mpdu_desc_info.bar_frame) {
qdf_assert_always(mpdu_desc_info.msdu_count == 1);
@@ -2158,6 +2240,7 @@ dp_rx_err_process(struct dp_intr *int_ctx, struct dp_soc *soc,
goto next_entry;
}
process_oor_2k_jump:
if (hal_rx_reo_is_2k_jump(error_code)) {
/* TOD0 */
DP_STATS_INC(soc,

View File

@@ -6040,6 +6040,8 @@ void dp_txrx_path_stats(struct dp_soc *soc)
pdev->soc->stats.rx.err.ipa_smmu_unmap_dup);
DP_PRINT_STATS("Rx ipa smmu unmap no pipes: %d",
pdev->soc->stats.rx.err.ipa_unmap_no_pipe);
DP_PRINT_STATS("PN-in-Dest error frame pn-check fail: %d",
soc->stats.rx.err.pn_in_dest_check_fail);
DP_PRINT_STATS("Reo Statistics");
DP_PRINT_STATS("near_full: %u ", soc->stats.rx.near_full);
@@ -6675,6 +6677,9 @@ dp_print_soc_rx_stats(struct dp_soc *soc)
DP_PRINT_STATS("bar handle update fail count: %d",
soc->stats.rx.err.bar_handle_fail_count);
DP_PRINT_STATS("PN-in-Dest error frame pn-check fail: %d",
soc->stats.rx.err.pn_in_dest_check_fail);
for (i = 0; i < HAL_RXDMA_ERR_MAX; i++) {
index += qdf_snprint(&rxdma_error[index],
DP_RXDMA_ERR_LENGTH - index,

View File

@@ -1084,6 +1084,8 @@ struct dp_soc_stats {
uint32_t bar_handle_fail_count;
/* EAPOL drop count in intrabss scenario */
uint32_t intrabss_eapol_drop;
/* PN check failed for 2K-jump or OOR error */
uint32_t pn_in_dest_check_fail;
/* MSDU len err count */
uint32_t msdu_len_err;
} err;
@@ -1627,6 +1629,14 @@ struct dp_arch_ops {
int *max_reap_limit);
};
/**
* struct dp_soc_features: Data structure holding the SOC level feature flags.
* @pn_in_reo_dest: PN provided by hardware in the REO destination ring.
*/
struct dp_soc_features {
uint8_t pn_in_reo_dest;
};
/* SOC level structure for data path */
struct dp_soc {
/**
@@ -2103,6 +2113,9 @@ struct dp_soc {
uint64_t cmem_base;
/* CMEM size in bytes */
uint64_t cmem_size;
/* SOC level feature flags */
struct dp_soc_features features;
};
#ifdef IPA_OFFLOAD

View File

@@ -2773,6 +2773,25 @@ static inline void hal_reo_set_err_dst_remap(hal_soc_handle_t hal_soc_hdl)
hal_soc->ops->hal_reo_set_err_dst_remap(hal_soc);
}
/**
* hal_reo_enable_pn_in_dest() - Subscribe for previous PN for 2k-jump or
* OOR error frames
* @hal_soc_hdl: Opaque HAL soc handle
*
* Return: true if feature is enabled,
* false, otherwise.
*/
static inline uint8_t
hal_reo_enable_pn_in_dest(hal_soc_handle_t hal_soc_hdl)
{
struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
if (hal_soc->ops->hal_reo_enable_pn_in_dest)
return hal_soc->ops->hal_reo_enable_pn_in_dest(hal_soc);
return 0;
}
#ifdef GENERIC_SHADOW_REGISTER_ACCESS_ENABLE
/**

View File

@@ -716,6 +716,7 @@ struct hal_hw_txrx_ops {
qdf_iomem_t (*hal_get_window_address)(struct hal_soc *hal_soc,
qdf_iomem_t addr);
void (*hal_reo_set_err_dst_remap)(void *hal_soc);
uint8_t (*hal_reo_enable_pn_in_dest)(void *hal_soc);
void (*hal_reo_qdesc_setup)(hal_soc_handle_t hal_soc_hdl, int tid,
uint32_t ba_window_size,
uint32_t start_seq, void *hw_qdesc_vaddr,
@@ -904,6 +905,7 @@ struct hal_hw_txrx_ops {
uint32_t (*hal_rx_tlv_mic_err_get)(uint8_t *buf);
uint32_t (*hal_rx_tlv_get_pkt_type)(uint8_t *buf);
void (*hal_rx_tlv_get_pn_num)(uint8_t *buf, uint64_t *pn_num);
void (*hal_rx_reo_prev_pn_get)(void *ring_desc, uint64_t *prev_pn);
uint8_t * (*hal_rx_pkt_hdr_get)(uint8_t *buf);
uint32_t (*hal_rx_msdu_reo_dst_ind_get)(hal_soc_handle_t hal_soc_hdl,
void *msdu_link_desc);
@@ -958,6 +960,8 @@ struct hal_hw_txrx_ops {
uint8_t *priv_data,
uint32_t len);
void (*hal_rx_tlv_msdu_len_set)(uint8_t *buf, uint32_t len);
void (*hal_rx_tlv_populate_mpdu_desc_info)(uint8_t *buf,
void *mpdu_desc_info_hdl);
/* REO CMD and STATUS */
int (*hal_reo_send_cmd)(hal_soc_handle_t hal_soc_hdl,

View File

@@ -251,6 +251,16 @@ enum hal_rx_mpdu_desc_flags {
#define HAL_RX_BUF_RBM_SW5_BM(sw0_bm_id) (sw0_bm_id + 5)
#define HAL_RX_BUF_RBM_SW6_BM(sw0_bm_id) (sw0_bm_id + 6)
#define HAL_REO_DESTINATION_RING_MSDU_COUNT_OFFSET 0x8
#define HAL_REO_DESTINATION_RING_MSDU_COUNT_LSB 0
#define HAL_REO_DESTINATION_RING_MSDU_COUNT_MASK 0x000000ff
#define HAL_RX_REO_DESC_MSDU_COUNT_GET(reo_desc) \
(_HAL_MS((*_OFFSET_TO_WORD_PTR(reo_desc, \
HAL_REO_DESTINATION_RING_MSDU_COUNT_OFFSET)), \
HAL_REO_DESTINATION_RING_MSDU_COUNT_MASK, \
HAL_REO_DESTINATION_RING_MSDU_COUNT_LSB))
#define HAL_BUFFER_ADDR_INFO_BUFFER_ADDR_31_0_OFFSET 0x0
#define HAL_BUFFER_ADDR_INFO_BUFFER_ADDR_31_0_LSB 0
#define HAL_BUFFER_ADDR_INFO_BUFFER_ADDR_31_0_MASK 0xffffffff
@@ -1323,6 +1333,20 @@ static inline bool hal_rx_reo_is_oor_error(uint32_t error_code)
true : false;
}
/**
* hal_rx_reo_is_bar_oor_2k_jump() - Check if the error is 2k-jump or OOR error
* @error_code: error code obtained from ring descriptor.
*
* Return: true, if the error code is 2k-jump or OOR
* false, for other error codes.
*/
static inline bool hal_rx_reo_is_bar_oor_2k_jump(uint32_t error_code)
{
return ((error_code == HAL_REO_ERR_BAR_FRAME_2K_JUMP) ||
(error_code == HAL_REO_ERR_BAR_FRAME_OOR)) ?
true : false;
}
/**
* hal_dump_wbm_rel_desc() - dump wbm release descriptor
* @hal_desc: hardware descriptor pointer
@@ -1690,6 +1714,27 @@ uint32_t hal_rx_desc_is_first_msdu(hal_soc_handle_t hal_soc_hdl,
return hal_soc->ops->hal_rx_desc_is_first_msdu(hw_desc_addr);
}
/**
* hal_rx_tlv_populate_mpdu_desc_info() - Populate mpdu_desc_info fields from
* the rx tlv fields.
* @hal_soc_hdl: HAL SoC handle
* @buf: rx tlv start address [To be validated by caller]
* @mpdu_desc_info_hdl: Buffer where the mpdu_desc_info is to be populated.
*
* Return: None
*/
static inline void
hal_rx_tlv_populate_mpdu_desc_info(hal_soc_handle_t hal_soc_hdl,
uint8_t *buf,
void *mpdu_desc_info_hdl)
{
struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
if (hal_soc->ops->hal_rx_tlv_populate_mpdu_desc_info)
return hal_soc->ops->hal_rx_tlv_populate_mpdu_desc_info(buf,
mpdu_desc_info_hdl);
}
static inline uint32_t
hal_rx_tlv_decap_format_get(hal_soc_handle_t hal_soc_hdl, void *hw_desc_addr)
{
@@ -2704,6 +2749,24 @@ hal_rx_reo_buf_type_get(hal_soc_handle_t hal_soc_hdl, hal_ring_desc_t rx_desc)
return hal_soc->ops->hal_rx_reo_buf_type_get(rx_desc);
}
/**
* hal_rx_reo_prev_pn_get() - Get the previous pn from ring descriptor.
* @hal_soc_hdl: HAL SoC handle
* @ring_desc: REO ring descriptor
* @prev_pn: Buffer to populate the previos PN
*
* Return: None
*/
static inline void
hal_rx_reo_prev_pn_get(hal_soc_handle_t hal_soc_hdl, hal_ring_desc_t ring_desc,
uint64_t *prev_pn)
{
struct hal_soc *hal_soc = (struct hal_soc *)hal_soc_hdl;
if (hal_soc->ops->hal_rx_reo_prev_pn_get)
return hal_soc->ops->hal_rx_reo_prev_pn_get(ring_desc, prev_pn);
}
/**
* hal_rx_mpdu_info_ampdu_flag_get(): get ampdu flag bit
* from rx mpdu info

View File

@@ -32,6 +32,9 @@
#include "rx_flow_search_entry.h"
#include "hal_rx_flow_info.h"
#include "hal_be_api.h"
#include "reo_destination_ring_with_pn.h"
#include <hal_be_rx.h>
#define UNIFIED_RXPCU_PPDU_END_INFO_8_RX_PPDU_DURATION_OFFSET \
RXPCU_PPDU_END_INFO_RX_PPDU_DURATION_OFFSET
@@ -713,6 +716,33 @@ static void hal_rx_dump_pkt_tlvs_7850(hal_soc_handle_t hal_soc_hdl,
hal_rx_dump_pkt_hdr_tlv_7850(pkt_tlvs, dbg_level);
}
/**
* hal_rx_tlv_populate_mpdu_desc_info_7850() - Populate the local mpdu_desc_info
* elements from the rx tlvs
* @buf: start address of rx tlvs [Validated by caller]
* @mpdu_desc_info_hdl: Buffer to populate the mpdu_dsc_info
* [To be validated by caller]
*
* Return: None
*/
static void
hal_rx_tlv_populate_mpdu_desc_info_7850(uint8_t *buf,
void *mpdu_desc_info_hdl)
{
struct hal_rx_mpdu_desc_info *mpdu_desc_info =
(struct hal_rx_mpdu_desc_info *)mpdu_desc_info_hdl;
struct rx_pkt_tlvs *pkt_tlvs = (struct rx_pkt_tlvs *)buf;
struct rx_mpdu_start *mpdu_start =
&pkt_tlvs->mpdu_start_tlv.rx_mpdu_start;
struct rx_mpdu_info *mpdu_info = &mpdu_start->rx_mpdu_info_details;
mpdu_desc_info->mpdu_seq = mpdu_info->mpdu_sequence_number;
mpdu_desc_info->mpdu_flags = hal_rx_get_mpdu_flags((uint32_t *)
mpdu_info);
mpdu_desc_info->peer_meta_data = mpdu_info->peer_meta_data;
mpdu_desc_info->bar_frame = mpdu_info->bar_frame;
}
/**
* hal_reo_status_get_header_7850 - Process reo desc info
* @d - Pointer to reo descriptior
@@ -999,6 +1029,20 @@ hal_reo_set_err_dst_remap_7850(void *hal_soc)
REO_REG_REG_BASE)));
}
/**
* hal_reo_enable_pn_in_dest_7850() - Set the REO register to enable previous PN
* for OOR and 2K-jump frames
* @hal_soc: HAL SoC handle
*
* Return: 1, since the register is set.
*/
static uint8_t hal_reo_enable_pn_in_dest_7850(void *hal_soc)
{
HAL_REG_WRITE(hal_soc, HWIO_REO_R0_PN_IN_DEST_ADDR(REO_REG_REG_BASE),
1);
return 1;
}
/**
* hal_rx_flow_setup_fse_7850() - Setup a flow search entry in HW FST
* @fst: Pointer to the Rx Flow Search Table
@@ -1223,6 +1267,24 @@ static uint8_t hal_tx_get_num_tcl_banks_7850(void)
return HAL_NUM_TCL_BANKS_7850;
}
/**
* hal_rx_reo_prev_pn_get_7850() - Get the previous PN from the REO ring desc.
* @ring_desc: REO ring descriptor [To be validated by caller ]
* @prev_pn: Buffer where the previous PN is to be populated.
* [To be validated by caller]
*
* Return: None
*/
static void hal_rx_reo_prev_pn_get_7850(void *ring_desc,
uint64_t *prev_pn)
{
struct reo_destination_ring_with_pn *reo_desc =
(struct reo_destination_ring_with_pn *)ring_desc;
*prev_pn = reo_desc->prev_pn_23_0;
*prev_pn |= ((uint64_t)reo_desc->prev_pn_55_24 << 24);
}
static void hal_hw_txrx_ops_attach_wcn7850(struct hal_soc *hal_soc)
{
/* init and setup */
@@ -1233,6 +1295,8 @@ static void hal_hw_txrx_ops_attach_wcn7850(struct hal_soc *hal_soc)
hal_soc->ops->hal_get_window_address = hal_get_window_address_7850;
hal_soc->ops->hal_reo_set_err_dst_remap =
hal_reo_set_err_dst_remap_7850;
hal_soc->ops->hal_reo_enable_pn_in_dest =
hal_reo_enable_pn_in_dest_7850;
/* tx */
hal_soc->ops->hal_tx_set_dscp_tid_map = hal_tx_set_dscp_tid_map_7850;
@@ -1383,6 +1447,7 @@ static void hal_hw_txrx_ops_attach_wcn7850(struct hal_soc *hal_soc)
hal_soc->ops->hal_rx_get_fisa_timeout = hal_rx_get_fisa_timeout_be;
hal_soc->ops->hal_rx_mpdu_start_tlv_tag_valid =
hal_rx_mpdu_start_tlv_tag_valid_be;
hal_soc->ops->hal_rx_reo_prev_pn_get = hal_rx_reo_prev_pn_get_7850;
/* rx - TLV struct offsets */
hal_soc->ops->hal_rx_msdu_end_offset_get =
@@ -1439,6 +1504,8 @@ static void hal_hw_txrx_ops_attach_wcn7850(struct hal_soc *hal_soc)
hal_rx_mpdu_info_ampdu_flag_get_be;
hal_soc->ops->hal_rx_tlv_msdu_len_set =
hal_rx_msdu_start_msdu_len_set_be;
hal_soc->ops->hal_rx_tlv_populate_mpdu_desc_info =
hal_rx_tlv_populate_mpdu_desc_info_7850;
};
struct hal_hw_srng_config hw_srng_table_7850[] = {