Przeglądaj źródła

qcacmn: Parsing logic for MLO global shared memory arena

MLO global shared memory arena contains MGMT Rx REO snapshots in the
form of TLVs. Parse the shared memory and store the address of these
snapshots. These addresses will be required by the MGMT Rx REO algorithm.

CRs-Fixed: 3035491
Change-Id: Ica1b72cd8cf4083acdeefaee41df0da4a1f57f4f
Shiva Krishna Pittala 4 lat temu
rodzic
commit
97fe9889b6

+ 97 - 0
target_if/init_deinit/inc/mlo_global_h_shmem_arena.h

@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ *  DOC: mlo_global_h_shmem_arena.h
+ *  This file contains APIs and data structures that are used to parse the MLO
+ *  global shared memory arena.
+ */
+
+#ifndef _MLO_GLOBAL_H_SHMEM_ARENA_H_
+#define _MLO_GLOBAL_H_SHMEM_ARENA_H_
+
+#include <qdf_types.h>
+#include <target_if.h>
+#include "wmi.h"
+#include <osdep.h>
+
+/**
+ * wlan_host_mlo_glb_h_shmem_params - MLO global shared memory parameters
+ * @major_version: Major version
+ * @minor_version: Minor version
+ */
+struct wlan_host_mlo_glb_h_shmem_params {
+	uint16_t major_version;
+	uint16_t minor_version;
+};
+
+/**
+ * wlan_host_mlo_glb_rx_reo_per_link_info - MGMT Rx REO information of a link in
+ * MLO global shared memory
+ * @link_id: Hardware link ID
+ * @fw_consumed: Address of FW consumed snapshot
+ * @fw_forwarded: Address of FW forwarded snapshot
+ * @hw_forwarded: Address of HW forwarded snapshot
+ */
+struct wlan_host_mlo_glb_rx_reo_per_link_info {
+	uint8_t link_id;
+	void *fw_consumed;
+	void *fw_forwarded;
+	void *hw_forwarded;
+};
+
+/**
+ * wlan_host_mlo_glb_rx_reo_snapshot_info - MGMT Rx REO information in MLO
+ * global shared memory
+ * @num_links: Number of valid links
+ * @valid_link_bmap: Valid link bitmap
+ * @link_info: pointer to an array of Rx REO per-link information
+ */
+struct wlan_host_mlo_glb_rx_reo_snapshot_info {
+	uint8_t num_links;
+	uint16_t valid_link_bmap;
+	struct wlan_host_mlo_glb_rx_reo_per_link_info *link_info;
+};
+
+/**
+ * wlan_host_mlo_glb_h_shmem_arena_ctx - MLO Global shared memory arena context
+ * @shmem_params: shared memory parameters
+ * @rx_reo_snapshot_info: MGMT Rx REO snapshot information
+ */
+struct wlan_host_mlo_glb_h_shmem_arena_ctx {
+	struct wlan_host_mlo_glb_h_shmem_params shmem_params;
+	struct wlan_host_mlo_glb_rx_reo_snapshot_info rx_reo_snapshot_info;
+};
+
+/**
+ * mlo_glb_h_shmem_arena_ctx_init() - Initialize MLO Global shared memory arena
+ * context on Host
+ * @arena_vaddr: Virtual address of the MLO Global shared memory arena
+ * @arena_len: Length (in bytes) of the MLO Global shared memory arena
+ *
+ * Return: QDF_STATUS of operation
+ */
+QDF_STATUS mlo_glb_h_shmem_arena_ctx_init(void *arena_vaddr,
+					  size_t arena_len);
+
+/**
+ * mlo_glb_h_shmem_arena_ctx_deinit() - De-initialize MLO Global shared memory
+ * arena context on Host
+ *
+ * Return: QDF_STATUS of operation
+ */
+QDF_STATUS mlo_glb_h_shmem_arena_ctx_deinit(void);
+#endif

+ 46 - 0
target_if/init_deinit/inc/mlo_global_h_shmem_arena_api.h

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ *  DOC: mlo_global_h_shmem_arena.h
+ *  This file contains APIs that are exposed by the the MLO
+ *  global shared memory arena.
+ */
+
+#include<qdf_types.h>
+
+#ifndef _MLO_GLOBAL_H_SHMEM_ARENA_API_H_
+#define _MLO_GLOBAL_H_SHMEM_ARENA_API_H_
+/**
+ * wlan_host_mlo_glb_h_shmem_arena_ctx_init() - Initialize MLO Global shared
+ * memory arena context on Host
+ * @arena_vaddr: Virtual address of the MLO Global shared memory arena
+ * @arena_len: Length (in bytes) of the MLO Global shared memory arena
+ *
+ * Return: QDF_STATUS of operation
+ */
+QDF_STATUS
+wlan_host_mlo_glb_h_shmem_arena_ctx_init(void *arena_vaddr,
+					 size_t arena_len);
+
+/**
+ * wlan_host_mlo_glb_h_shmem_arena_deinit() - De-initialize MLO Global shared
+ * memory arena context on Host
+ *
+ * Return: QDF_STATUS of operation
+ */
+QDF_STATUS wlan_host_mlo_glb_h_shmem_arena_ctx_deinit(void);
+#endif

+ 474 - 0
target_if/init_deinit/src/mlo_global_h_shmem_arena.c

@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ *  DOC: mlo_global_h_shmem_arena.c
+ *  This file contains definition of functions that parse the MLO global
+ *  shared memory arena.
+ */
+
+#include<mlo_global_h_shmem_arena.h>
+
+static struct wlan_host_mlo_glb_h_shmem_arena_ctx g_shmem_arena_ctx;
+
+#define get_shmem_arena_ctx() (&g_shmem_arena_ctx)
+
+/**
+ * get_field_value_in_tlv() - Get the value of a given field in a given TLV
+ * @ptlv: Pointer to start of the TLV
+ * @field_name: name of the field in the TLV structure
+ * @tlv_len: Length of the TLV
+ *
+ * Return: Value of the given field if the offset of the field with in the TLV
+ * structure is less than the TLV length, else 0.
+ */
+#define get_field_value_in_tlv(ptlv, field_name, tlv_len) \
+	(qdf_offsetof(typeof(*(ptlv)), field_name) < (tlv_len) ? \
+		(ptlv)->field_name : 0)
+
+/**
+ * get_field_pointer_in_tlv() - Get the address of a given field in a given TLV
+ * @ptlv: Pointer to start of the TLV
+ * @field_name: name of the field in the TLV structure
+ * @tlv_len: Length of the TLV
+ *
+ * Return: Address of the given field if the offset of the field with in the
+ * TLV structure is less than the TLV length, else NULL.
+ */
+#define get_field_pointer_in_tlv(ptlv, field_name, tlv_len) \
+	(qdf_offsetof(typeof(*(ptlv)), field_name) < (tlv_len) ? \
+		&(ptlv)->field_name : NULL)
+
+/**
+ * process_tlv_header() - Process a given TLV header
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @expected_tag: Expected TLV tag
+ * @tlv_len: Address of TLV length variable to be populated. This API populates
+ * the entire length(payload + header) of the TLV into @tlv_len
+ * @tlv_tag: Address of TLV Tag variable to be populated.
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static int
+process_tlv_header(const uint8_t *data, size_t remaining_len,
+		   uint32_t expected_tag, uint32_t *tlv_len,
+		   uint32_t *tlv_tag)
+{
+	if (remaining_len < MLO_SHMEM_TLV_HDR_SIZE) {
+		target_if_err("Not enough space(%zu) to read TLV header(%u)",
+			      remaining_len, (uint32_t)MLO_SHMEM_TLV_HDR_SIZE);
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	*tlv_len = MLO_SHMEMTLV_GET_TLVLEN(MLO_SHMEMTLV_GET_HDR(data));
+	*tlv_len += MLO_SHMEM_TLV_HDR_SIZE;
+	if (remaining_len < *tlv_len) {
+		target_if_err("Not enough space(%zu) to read TLV payload(%u)",
+			      remaining_len, *tlv_len);
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	*tlv_tag = MLO_SHMEMTLV_GET_TLVTAG(MLO_SHMEMTLV_GET_HDR(data));
+	if (*tlv_tag != expected_tag) {
+		target_if_err("Unexpected TLV tag: %u is seen. Expected: %u",
+			      *tlv_tag,
+			      expected_tag);
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	return 0;
+}
+
+#define validate_parsed_bytes_advance_data_pointer(parsed_bytes, data, \
+						   remaining_len) \
+do { \
+	if ((parsed_bytes) < 0) { \
+		target_if_err("TLV extraction failed"); \
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE); \
+	} \
+	(data) += (parsed_bytes); \
+	(remaining_len) -= (parsed_bytes); \
+} while (0)
+
+/**
+ * extract_mgmt_rx_reo_snapshot_tlv() - extract MGMT_RX_REO_SNAPSHOT TLV
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @address_ptr: Pointer to the snapshot address. This API will populate the
+ * snapshot address into the variable pointed by @address_ptr
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+extract_mgmt_rx_reo_snapshot_tlv(uint8_t *data, size_t remaining_len,
+				 void **address_ptr)
+{
+	mgmt_rx_reo_snapshot *ptlv;
+	uint32_t tlv_len, tlv_tag;
+
+	qdf_assert_always(data);
+	qdf_assert_always(address_ptr);
+
+	/* process MLO_SHMEM_TLV_STRUCT_MGMT_RX_REO_SNAPSHOT TLV */
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MGMT_RX_REO_SNAPSHOT,
+			       &tlv_len, &tlv_tag) != 0) {
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	ptlv = (mgmt_rx_reo_snapshot *)data;
+	*address_ptr = get_field_pointer_in_tlv(ptlv, mgmt_rx_reo_snapshot_low,
+						tlv_len);
+
+	return tlv_len;
+}
+
+/**
+ * extract_mlo_glb_rx_reo_per_link_info_tlv() - extract
+ * RX_REO_PER_LINK_SNAPSHOT_INFO TLV
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @link_info: Pointer to MGMT Rx REO per link info. Extracted information
+ * will be populated in this data structure.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+extract_mlo_glb_rx_reo_per_link_info_tlv(
+	uint8_t *data, size_t remaining_len, uint8_t link_id,
+	struct wlan_host_mlo_glb_rx_reo_per_link_info *link_info)
+{
+	mlo_glb_rx_reo_per_link_snapshot_info *ptlv;
+	uint32_t tlv_len, tlv_tag;
+	int len;
+	uint8_t *fw_consumed;
+
+	qdf_assert_always(data);
+	qdf_assert_always(link_info);
+
+	/* process MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_PER_LINK_SNAPSHOT_INFO TLV */
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_PER_LINK_SNAPSHOT_INFO,
+			       &tlv_len, &tlv_tag) != 0) {
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	ptlv = (mlo_glb_rx_reo_per_link_snapshot_info *)data;
+
+	link_info->link_id = link_id;
+
+	/**
+	 * Get the pointer to the fw_consumed snapshot with in the TLV.
+	 * Note that snapshots are nested TLVs within link_sanpshot_info TLV.
+	 */
+	fw_consumed = (uint8_t *)get_field_pointer_in_tlv(ptlv, fw_consumed,
+							  tlv_len);
+	remaining_len -= qdf_offsetof(mlo_glb_rx_reo_per_link_snapshot_info,
+				      fw_consumed);
+
+	/* extract fw_consumed snapshot */
+	len = extract_mgmt_rx_reo_snapshot_tlv(fw_consumed, remaining_len,
+					       &link_info->fw_consumed);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+
+	/* extract fw_forwarded snapshot */
+	len = extract_mgmt_rx_reo_snapshot_tlv(fw_consumed, remaining_len,
+					       &link_info->fw_forwarded);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+
+	/* extract hw_forwarded snapshot */
+	len = extract_mgmt_rx_reo_snapshot_tlv(fw_consumed, remaining_len,
+					       &link_info->hw_forwarded);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+
+	/**
+	 * Return the length of link_sanpshot_info TLV itself as the snapshots
+	 * are nested inside link_sanpshot_info TLV and hence no need to add
+	 * their lengths separately.
+	 */
+	return tlv_len;
+}
+
+/**
+ * get_num_links_from_valid_link_bitmap() - Get the number of valid links
+ * @valid_link_bmap: Link bit map where the valid links are set to 1
+ *
+ * Return: Number of valid links
+ */
+static uint8_t
+get_num_links_from_valid_link_bitmap(uint16_t valid_link_bmap)
+{
+	uint8_t num_links = 0;
+
+	/* Find the number of set bits */
+	while (valid_link_bmap) {
+		num_links++;
+		valid_link_bmap &= (valid_link_bmap - 1);
+	}
+
+	return num_links;
+}
+
+/**
+ * extract_mlo_glb_rx_reo_snapshot_info_tlv() - extract
+ * MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @snapshot_info: Pointer to MGMT Rx REO snapshot info. Extracted information
+ * will be populated in this data structure.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+extract_mlo_glb_rx_reo_snapshot_info_tlv(
+	uint8_t *data, size_t remaining_len,
+	struct wlan_host_mlo_glb_rx_reo_snapshot_info *snapshot_info)
+{
+	mlo_glb_rx_reo_snapshot_info *ptlv;
+	uint32_t tlv_len, tlv_tag;
+	uint32_t link_info;
+	uint16_t valid_link_bmap;
+
+	qdf_assert_always(data);
+	qdf_assert_always(snapshot_info);
+
+	/* process MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV */
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO,
+			       &tlv_len, &tlv_tag) != 0) {
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	ptlv = (mlo_glb_rx_reo_snapshot_info *)data;
+	link_info = get_field_value_in_tlv(ptlv, link_info, tlv_len);
+	valid_link_bmap =
+		MLO_SHMEM_GLB_LINK_INFO_PARAM_VALID_LINK_BMAP_GET(link_info);
+
+	snapshot_info->valid_link_bmap = valid_link_bmap;
+	snapshot_info->num_links =
+			get_num_links_from_valid_link_bitmap(valid_link_bmap);
+	snapshot_info->link_info = qdf_mem_malloc(
+					sizeof(*snapshot_info->link_info) *
+					snapshot_info->num_links);
+	if (!snapshot_info->link_info) {
+		target_if_err("Couldn't allocate memory for rx_reo_per_link_info");
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	return tlv_len;
+}
+
+/**
+ * free_mlo_glb_rx_reo_per_link_info() - Free Rx REO per-link info
+ * @snapshot_info: Pointer to MGMT Rx REO snapshot info
+ *
+ * Return: None
+ */
+static void free_mlo_glb_rx_reo_per_link_info(
+	struct wlan_host_mlo_glb_rx_reo_snapshot_info *snapshot_info)
+{
+	if (snapshot_info && snapshot_info->link_info) {
+		qdf_mem_free(snapshot_info->link_info);
+		snapshot_info->link_info =  NULL;
+	}
+}
+
+/**
+ * get_next_valid_link_id() - Get next valid link ID
+ * @valid_link_bmap: Link bit map where the valid links are set to 1
+ * @prev_link_id: Previous link ID
+ *
+ * Return: Next valid link ID if there are valid links after @prev_link_id,
+ * else -1
+ */
+static int
+get_next_valid_link_id(uint16_t valid_link_bmap, int prev_link_id)
+{
+	int cur_link_id;
+	uint16_t mask;
+	uint8_t maxbits = sizeof(valid_link_bmap) * QDF_CHAR_BIT;
+
+	cur_link_id = prev_link_id + 1;
+	mask = 1 << cur_link_id;
+
+	while (!(valid_link_bmap & mask)) {
+		cur_link_id++;
+		if (cur_link_id == maxbits)
+			return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+		mask = mask << 1;
+	}
+
+	return cur_link_id;
+}
+
+/**
+ * extract_mlo_glb_rx_reo_snapshot_info() - extract MGMT Rx REO snapshot info
+ * @data: Pointer to start of MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO
+ * TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @snapshot_info: Pointer to MGMT Rx REO snapshot info. Extracted information
+ * will be populated in this data structure.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+extract_mlo_glb_rx_reo_snapshot_info(
+	uint8_t *data, size_t remaining_len,
+	struct wlan_host_mlo_glb_rx_reo_snapshot_info *snapshot_info)
+{
+	int parsed_bytes, len;
+	uint8_t link;
+	int cur_link_id, prev_link_id = -1;
+	uint16_t valid_link_bmap;
+
+	qdf_assert_always(data);
+	qdf_assert_always(snapshot_info);
+
+	/* Extract MLO_SHMEM_TLV_STRUCT_MLO_GLB_RX_REO_SNAPSHOT_INFO TLV */
+	len = extract_mlo_glb_rx_reo_snapshot_info_tlv(data, remaining_len,
+						       snapshot_info);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+	parsed_bytes = len;
+
+	valid_link_bmap = snapshot_info->valid_link_bmap;
+	/* Foreach valid link */
+	for (link = 0; link < snapshot_info->num_links; ++link) {
+		cur_link_id = get_next_valid_link_id(valid_link_bmap,
+						     prev_link_id);
+
+		qdf_assert_always(cur_link_id >= 0);
+
+		/* Extract per_link_info */
+		len  = extract_mlo_glb_rx_reo_per_link_info_tlv(
+					data, remaining_len, cur_link_id,
+					&snapshot_info->link_info[link]);
+		validate_parsed_bytes_advance_data_pointer(len, data,
+							   remaining_len);
+		parsed_bytes += len;
+		prev_link_id = cur_link_id;
+	}
+
+	return parsed_bytes;
+}
+
+/**
+ * extract_mlo_glb_h_shmem_tlv() - extract MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM
+ * TLV
+ * @data: Pointer to start of the TLV
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @shmem_params: Pointer to MLO Global shared memory parameters. Extracted
+ * information will be populated in this data structure.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int
+extract_mlo_glb_h_shmem_tlv(
+		uint8_t *data, size_t remaining_len,
+		struct wlan_host_mlo_glb_h_shmem_params *shmem_params)
+{
+	mlo_glb_h_shmem *ptlv;
+	uint32_t tlv_len, tlv_tag;
+	uint32_t major_minor_version;
+
+	qdf_assert_always(data);
+	qdf_assert_always(shmem_params);
+	if (process_tlv_header(data, remaining_len,
+			       MLO_SHMEM_TLV_STRUCT_MLO_GLB_H_SHMEM,
+			       &tlv_len, &tlv_tag) != 0) {
+		return qdf_status_to_os_return(QDF_STATUS_E_FAILURE);
+	}
+
+	ptlv = (mlo_glb_h_shmem *)data;
+	major_minor_version = get_field_value_in_tlv(ptlv, major_minor_version,
+						     tlv_len);
+	shmem_params->major_version =
+			MLO_SHMEM_GLB_H_SHMEM_PARAM_MAJOR_VERSION_GET(
+				major_minor_version);
+	shmem_params->minor_version =
+			MLO_SHMEM_GLB_H_SHMEM_PARAM_MINOR_VERSION_GET(
+				major_minor_version);
+
+	return tlv_len;
+}
+
+/**
+ * parse_mlo_glb_h_shmem_arena() - Parse MLO Global shared memory arena
+ * @data: Pointer to the first TLV in the arena
+ * @remaining_len: Length (in bytes) remaining in the arena from @data pointer
+ * @shmem_arena_ctx: Pointer to MLO Global shared memory arena context.
+ * Extracted information will be populated in this data structure.
+ *
+ * Return: On success, the number of bytes parsed. On failure, -1.
+ */
+static int parse_mlo_glb_h_shmem_arena(
+	uint8_t *data, size_t remaining_len,
+	struct wlan_host_mlo_glb_h_shmem_arena_ctx *shmem_arena_ctx)
+{
+	int parsed_bytes, len;
+
+	qdf_assert_always(data);
+	qdf_assert_always(shmem_arena_ctx);
+
+	len = extract_mlo_glb_h_shmem_tlv(data, remaining_len,
+					  &shmem_arena_ctx->shmem_params);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+	parsed_bytes += len;
+
+	len = extract_mlo_glb_rx_reo_snapshot_info(
+		data, remaining_len, &shmem_arena_ctx->rx_reo_snapshot_info);
+	validate_parsed_bytes_advance_data_pointer(len, data, remaining_len);
+	parsed_bytes += len;
+
+	return parsed_bytes;
+}
+
+QDF_STATUS mlo_glb_h_shmem_arena_ctx_init(uint8_t *arena_vaddr,
+					  size_t arena_len)
+{
+	struct wlan_host_mlo_glb_h_shmem_arena_ctx *shmem_arena_ctx;
+
+	shmem_arena_ctx = get_shmem_arena_ctx();
+	if (!shmem_arena_ctx) {
+		target_if_err("mlo_glb_h_shmem_arena context is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (parse_mlo_glb_h_shmem_arena(arena_vaddr, arena_len,
+					shmem_arena_ctx) < 0) {
+		free_mlo_glb_rx_reo_per_link_info(
+			&shmem_arena_ctx->rx_reo_snapshot_info);
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS mlo_glb_h_shmem_arena_deinit(void)
+{
+	struct wlan_host_mlo_glb_h_shmem_arena_ctx *shmem_arena_ctx;
+
+	shmem_arena_ctx = get_shmem_arena_ctx();
+	if (!shmem_arena_ctx) {
+		target_if_err("mlo_glb_h_shmem_arena context is NULL");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	free_mlo_glb_rx_reo_per_link_info(
+		&shmem_arena_ctx->rx_reo_snapshot_info);
+
+	return QDF_STATUS_SUCCESS;
+}

+ 34 - 0
target_if/init_deinit/src/mlo_global_h_shmem_arena_api.c

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021, The Linux Foundation. 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 above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**
+ *  DOC: mlo_global_h_shmem_arena_api.c
+ *  This file contains definition of functions that MLO global
+ *  shared memory arena exposes.
+ */
+#include <mlo_global_h_shmem_arena.h>
+
+QDF_STATUS
+wlan_host_mlo_glb_h_shmem_arena_ctx_init(uint8_t *arena_vaddr,
+					 size_t arena_len)
+{
+	return mlo_glb_h_shmem_arena_ctx_init(arena_vaddr, arena_len);
+}
+
+QDF_STATUS wlan_host_mlo_glb_h_shmem_arena_ctx_deinit(void)
+{
+	return mlo_glb_h_shmem_arena_ctx_deinit();
+}