瀏覽代碼

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
Rakesh Pillai 3 年之前
父節點
當前提交
dad3ff5afa
共有 3 個文件被更改,包括 136 次插入2 次删除
  1. 115 0
      hal/wifi3.0/be/hal_be_generic_api.h
  2. 20 1
      hal/wifi3.0/hal_api_mon.h
  3. 1 1
      hal/wifi3.0/kiwi/hal_kiwi.c

+ 115 - 0
hal/wifi3.0/be/hal_be_generic_api.h

@@ -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

+ 20 - 1
hal/wifi3.0/hal_api_mon.h

@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -691,6 +691,23 @@ struct hal_rx_frm_type_info {
 struct hal_rx_frm_type_info {};
 #endif
 
+#define HAL_RX_MON_MAX_AGGR_SIZE	128
+
+/**
+ * struct hal_rx_tlv_aggr_info - Data structure to hold
+ *		metadata for aggregatng repeated TLVs
+ * @in_progress: Flag to indicate if TLV aggregation is in progress
+ * @cur_len: Total length of currently aggregated TLV
+ * @tlv_tag: TLV tag which is currently being aggregated
+ * @buf: Buffer containing aggregated TLV data
+ */
+struct hal_rx_tlv_aggr_info {
+	uint8_t in_progress;
+	uint16_t cur_len;
+	uint32_t tlv_tag;
+	uint8_t buf[HAL_RX_MON_MAX_AGGR_SIZE];
+};
+
 struct hal_rx_ppdu_info {
 	struct hal_rx_ppdu_common_info com_info;
 	struct mon_rx_status rx_status;
@@ -730,6 +747,8 @@ struct hal_rx_ppdu_info {
 	struct hal_rx_ppdu_cfr_info cfr_info;
 	/* per frame type counts */
 	struct hal_rx_frm_type_info frm_type_info;
+	/* TLV aggregation metadata context */
+	struct hal_rx_tlv_aggr_info tlv_aggr;
 };
 
 static inline uint32_t

+ 1 - 1
hal/wifi3.0/kiwi/hal_kiwi.c

@@ -1678,7 +1678,7 @@ static void hal_hw_txrx_ops_attach_kiwi(struct hal_soc *hal_soc)
 	hal_soc->ops->hal_reo_status_get_header =
 					hal_reo_status_get_header_kiwi;
 	hal_soc->ops->hal_rx_status_get_tlv_info =
-					hal_rx_status_get_tlv_info_generic_be;
+					hal_rx_status_get_tlv_info_wrapper_be;
 	hal_soc->ops->hal_rx_wbm_err_info_get =
 					hal_rx_wbm_err_info_get_generic_be;
 	hal_soc->ops->hal_rx_priv_info_set_in_tlv =