qcacmn: Add support to parse and aggregate split TLVs

For KIWI, when operating monitor mode in 802.11BE,
there can be certain header fields which can be received
as split across multiple TLVs.

Add support to aggregate such split TLVs and decode them
after agregation.

Change-Id: Ia00323a8f9fbe39306b1bbab4afefaa937befdae
CRs-Fixed: 3092820
This commit is contained in:
Rakesh Pillai
2021-12-10 02:05:16 -08:00
committed by Madan Koyyalamudi
parent 1c6617edf5
commit dad3ff5afa
3 changed files with 136 additions and 2 deletions

View File

@@ -1524,6 +1524,121 @@ hal_rx_status_get_tlv_info_generic_be(void *rx_tlv_hdr, void *ppduinfo,
return HAL_TLV_STATUS_PPDU_NOT_DONE;
}
static uint32_t
hal_rx_status_process_aggr_tlv(struct hal_soc *hal_soc,
struct hal_rx_ppdu_info *ppdu_info)
{
uint32_t aggr_tlv_tag = ppdu_info->tlv_aggr.tlv_tag;
switch (aggr_tlv_tag) {
case WIFIPHYRX_GENERIC_EHT_SIG_E:
break;
default:
/* Aggregated TLV cannot be handled */
qdf_assert(0);
break;
}
ppdu_info->tlv_aggr.in_progress = 0;
ppdu_info->tlv_aggr.cur_len = 0;
return HAL_TLV_STATUS_PPDU_NOT_DONE;
}
static inline bool
hal_rx_status_tlv_should_aggregate(struct hal_soc *hal_soc, uint32_t tlv_tag)
{
switch (tlv_tag) {
case WIFIPHYRX_GENERIC_EHT_SIG_E:
return true;
}
return false;
}
static inline uint32_t
hal_rx_status_aggr_tlv(struct hal_soc *hal_soc, void *rx_tlv_hdr,
struct hal_rx_ppdu_info *ppdu_info,
qdf_nbuf_t nbuf)
{
uint32_t tlv_tag, user_id, tlv_len;
void *rx_tlv;
tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(rx_tlv_hdr);
user_id = HAL_RX_GET_USER_TLV64_USERID(rx_tlv_hdr);
tlv_len = HAL_RX_GET_USER_TLV64_LEN(rx_tlv_hdr);
rx_tlv = (uint8_t *)rx_tlv_hdr + HAL_RX_TLV64_HDR_SIZE;
if (tlv_len <= HAL_RX_MON_MAX_AGGR_SIZE - ppdu_info->tlv_aggr.cur_len) {
qdf_mem_copy(ppdu_info->tlv_aggr.buf +
ppdu_info->tlv_aggr.cur_len,
rx_tlv, tlv_len);
ppdu_info->tlv_aggr.cur_len += tlv_len;
} else {
dp_err("Length of TLV exceeds max aggregation length");
qdf_assert(0);
}
return HAL_TLV_STATUS_PPDU_NOT_DONE;
}
static inline uint32_t
hal_rx_status_start_new_aggr_tlv(struct hal_soc *hal_soc, void *rx_tlv_hdr,
struct hal_rx_ppdu_info *ppdu_info,
qdf_nbuf_t nbuf)
{
uint32_t tlv_tag, user_id, tlv_len;
tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(rx_tlv_hdr);
user_id = HAL_RX_GET_USER_TLV64_USERID(rx_tlv_hdr);
tlv_len = HAL_RX_GET_USER_TLV64_LEN(rx_tlv_hdr);
ppdu_info->tlv_aggr.in_progress = 1;
ppdu_info->tlv_aggr.tlv_tag = tlv_tag;
ppdu_info->tlv_aggr.cur_len = 0;
return hal_rx_status_aggr_tlv(hal_soc, rx_tlv_hdr, ppdu_info, nbuf);
}
static inline uint32_t
hal_rx_status_get_tlv_info_wrapper_be(void *rx_tlv_hdr, void *ppduinfo,
hal_soc_handle_t hal_soc_hdl,
qdf_nbuf_t nbuf)
{
struct hal_soc *hal = (struct hal_soc *)hal_soc_hdl;
uint32_t tlv_tag, user_id, tlv_len;
struct hal_rx_ppdu_info *ppdu_info =
(struct hal_rx_ppdu_info *)ppduinfo;
tlv_tag = HAL_RX_GET_USER_TLV64_TYPE(rx_tlv_hdr);
user_id = HAL_RX_GET_USER_TLV64_USERID(rx_tlv_hdr);
tlv_len = HAL_RX_GET_USER_TLV64_LEN(rx_tlv_hdr);
/*
* Handle the case where aggregation is in progress
* or the current TLV is one of the TLVs which should be
* aggregated
*/
if (ppdu_info->tlv_aggr.in_progress) {
if (ppdu_info->tlv_aggr.tlv_tag == tlv_tag) {
return hal_rx_status_aggr_tlv(hal, rx_tlv_hdr,
ppdu_info, nbuf);
} else {
/* Finish aggregation of current TLV */
hal_rx_status_process_aggr_tlv(hal, ppdu_info);
}
}
if (hal_rx_status_tlv_should_aggregate(hal, tlv_tag)) {
return hal_rx_status_start_new_aggr_tlv(hal, rx_tlv_hdr,
ppduinfo, nbuf);
}
return hal_rx_status_get_tlv_info_generic_be(rx_tlv_hdr, ppduinfo,
hal_soc_hdl, nbuf);
}
/**
* hal_tx_set_pcp_tid_map_generic_be() - Configure default PCP to TID map table
* @soc: HAL SoC context