Эх сурвалжийг харах

qcacmn: Add APIs to handle the reorder list

Add APIs to create/update/destroy reorder list.

CRs-Fixed: 3017570
Change-Id: I74528a7f13db8f48c0fc5c5516ea754caf4b686a
Edayilliam Jayadev 3 жил өмнө
parent
commit
c85bc308e4

+ 771 - 1
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_rx_reo.c

@@ -21,8 +21,11 @@
 
 #include "wlan_mgmt_txrx_rx_reo_i.h"
 #include <wlan_mgmt_txrx_rx_reo_tgt_api.h>
+#include <qdf_util.h>
 
-struct mgmt_rx_reo_context rx_reo_global;
+static struct mgmt_rx_reo_context g_rx_reo_ctx;
+
+#define mgmt_rx_reo_get_context()        (&g_rx_reo_ctx)
 
 #define MGMT_RX_REO_PKT_CTR_HALF_RANGE (0x8000)
 #define MGMT_RX_REO_PKT_CTR_FULL_RANGE (MGMT_RX_REO_PKT_CTR_HALF_RANGE << 1)
@@ -410,3 +413,770 @@ update_pending_frames:
 
 	return QDF_STATUS_SUCCESS;
 }
+
+/*
+ * struct mgmt_rx_reo_list_entry_debug_info - This structure holds the necessary
+ * information about a reo list entry for debug purposes.
+ * @link_id: link id
+ * @mgmt_pkt_ctr: management packet counter
+ * @global_timestamp: global time stamp
+ * @wait_count: wait count values
+ * @status: status of the entry in the list
+ * @entry: pointer to reo list entry
+ */
+struct mgmt_rx_reo_list_entry_debug_info {
+	uint8_t link_id;
+	uint16_t mgmt_pkt_ctr;
+	uint32_t global_timestamp;
+	struct mgmt_rx_reo_wait_count wait_count;
+	uint32_t status;
+	struct mgmt_rx_reo_list_entry *entry;
+};
+
+/**
+ * mgmt_rx_reo_list_display() - API to print the entries in the reorder list
+ * @reo_list: Pointer to reorder list
+ * @num_mlo_links: Number of MLO HW links
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_list_display(struct mgmt_rx_reo_list *reo_list,
+			 uint8_t num_mlo_links)
+{
+	uint32_t reo_list_size;
+	uint32_t index;
+	struct mgmt_rx_reo_list_entry *cur_entry;
+	struct mgmt_rx_reo_list_entry_debug_info *debug_info;
+
+	if (!reo_list) {
+		mgmt_rx_reo_err("Pointer to reo list is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (num_mlo_links == 0 || num_mlo_links > MGMT_RX_REO_MAX_LINKS) {
+		mgmt_rx_reo_err("Invalid number of links %u", num_mlo_links);
+		return QDF_STATUS_E_INVAL;
+	}
+
+	qdf_spin_lock_bh(&reo_list->list_lock);
+
+	reo_list_size = qdf_list_size(&reo_list->list);
+
+	if (reo_list_size == 0) {
+		qdf_spin_unlock_bh(&reo_list->list_lock);
+		mgmt_rx_reo_debug("Number of entries in the reo list = %u",
+				  reo_list_size);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	debug_info = qdf_mem_malloc_atomic(reo_list_size * sizeof(*debug_info));
+	if (!debug_info) {
+		qdf_spin_unlock_bh(&reo_list->list_lock);
+		mgmt_rx_reo_err("Memory allocation failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	index = 0;
+	qdf_list_for_each(&reo_list->list, cur_entry, node) {
+		debug_info[index].link_id =
+				mgmt_rx_reo_get_link_id(cur_entry->rx_params);
+		debug_info[index].mgmt_pkt_ctr =
+			mgmt_rx_reo_get_pkt_counter(cur_entry->rx_params);
+		debug_info[index].global_timestamp =
+				mgmt_rx_reo_get_global_ts(cur_entry->rx_params);
+		debug_info[index].wait_count = cur_entry->wait_count;
+		debug_info[index].status = cur_entry->status;
+		debug_info[index].entry = cur_entry;
+
+		++index;
+	}
+
+	qdf_spin_unlock_bh(&reo_list->list_lock);
+
+	mgmt_rx_reo_debug("Reorder list");
+	mgmt_rx_reo_debug("##################################################");
+	mgmt_rx_reo_debug("Number of entries in the reo list = %u",
+			  reo_list_size);
+	for (index = 0; index < reo_list_size; index++) {
+		uint8_t link_id;
+
+		mgmt_rx_reo_debug("index = %u: link_id = %u, ts = %u, ctr = %u, status = 0x%x, entry = %pK",
+				  index, debug_info[index].link_id,
+				  debug_info[index].global_timestamp,
+				  debug_info[index].mgmt_pkt_ctr,
+				  debug_info[index].status,
+				  debug_info[index].entry);
+
+		mgmt_rx_reo_debug("Total wait count = 0x%llx",
+				  debug_info[index].wait_count.total_count);
+
+		for (link_id = 0; link_id < num_mlo_links; link_id++)
+			mgmt_rx_reo_debug("Link id = %u, wait_count = 0x%x",
+					  link_id, debug_info[index].wait_count.
+					  per_link_count[link_id]);
+	}
+	mgmt_rx_reo_debug("##################################################");
+
+	qdf_mem_free(debug_info);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mgmt_rx_reo_list_entry_get_release_reason() - Helper API to get the reason
+ * for releasing the reorder list entry to upper layer.
+ * reorder list.
+ * @entry: List entry
+ * @ts_latest_aged_out_frame: Global time stamp of latest aged out frame
+ *
+ * Return: Reason for releasing the frame.
+ */
+static uint8_t
+mgmt_rx_reo_list_entry_get_release_reason(
+		struct mgmt_rx_reo_list_entry *entry,
+		struct mgmt_rx_reo_global_ts_info *ts_latest_aged_out_frame)
+{
+	uint8_t release_reason = 0;
+
+	if (!entry || !ts_latest_aged_out_frame)
+		return 0;
+
+	if (!MGMT_RX_REO_LIST_ENTRY_IS_WAITING_FOR_FRAME_ON_OTHER_LINK(entry))
+		release_reason |=
+			MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_ZERO_WAIT_COUNT;
+
+	if (MGMT_RX_REO_LIST_ENTRY_IS_AGED_OUT(entry))
+		release_reason |=
+				MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_AGED_OUT;
+
+	if (ts_latest_aged_out_frame->valid &&
+	    MGMT_RX_REO_LIST_ENTRY_IS_OLDER_THAN_LATEST_AGED_OUT_FRAME(
+				ts_latest_aged_out_frame, entry))
+		release_reason |=
+		MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_OLDER_THAN_AGED_OUT_FRAME;
+
+	return release_reason;
+}
+
+/**
+ * mgmt_rx_reo_list_entry_send_up() - API to send the frame to the upper layer.
+ * @reo_list: Pointer to reorder list
+ * @entry: List entry
+ *
+ * API to send the frame to the upper layer. This API has to be called only
+ * for entries which can be released to upper layer. It is the caller's
+ * responsibility to ensure that entry can be released (by using API
+ * mgmt_rx_reo_list_is_ready_to_send_up_entry). This API is called after
+ * acquiring the lock which protects the reorder list.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_list_entry_send_up(struct mgmt_rx_reo_list *reo_list,
+			       struct mgmt_rx_reo_list_entry *entry)
+{
+	uint8_t release_reason;
+	QDF_STATUS status;
+	uint8_t link_id;
+	struct wlan_objmgr_pdev *pdev;
+
+	qdf_assert_always(reo_list);
+	qdf_assert_always(entry);
+
+	release_reason = mgmt_rx_reo_list_entry_get_release_reason(
+				entry, &reo_list->ts_latest_aged_out_frame);
+
+	qdf_assert_always(release_reason != 0);
+
+	status = qdf_list_remove_node(&reo_list->list, &entry->node);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to remove entry %pK from list", entry);
+		qdf_assert_always(0);
+	}
+
+	link_id = mgmt_rx_reo_get_link_id(entry->rx_params);
+
+	pdev = wlan_get_pdev_from_mlo_link_id(link_id);
+
+	qdf_assert_always(pdev);
+
+	qdf_assert_always(QDF_IS_STATUS_SUCCESS(status));
+
+	free_mgmt_rx_event_params(entry->rx_params);
+
+	/**
+	 * Release the reference taken when the entry is inserted into
+	 * the reorder list
+	 */
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_RX_REO_ID);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mgmt_rx_reo_list_is_ready_to_send_up_entry() - API to check whether the
+ * list entry can be send to upper layers.
+ * @reo_list: Pointer to reorder list
+ * @entry: List entry
+ *
+ * Return: QDF_STATUS
+ */
+static bool
+mgmt_rx_reo_list_is_ready_to_send_up_entry(struct mgmt_rx_reo_list *reo_list,
+					   struct mgmt_rx_reo_list_entry *entry)
+{
+	if (!reo_list || !entry)
+		return false;
+
+	return !MGMT_RX_REO_LIST_ENTRY_IS_WAITING_FOR_FRAME_ON_OTHER_LINK(
+	       entry) || MGMT_RX_REO_LIST_ENTRY_IS_AGED_OUT(entry) ||
+	       (reo_list->ts_latest_aged_out_frame.valid &&
+		MGMT_RX_REO_LIST_ENTRY_IS_OLDER_THAN_LATEST_AGED_OUT_FRAME(
+				&reo_list->ts_latest_aged_out_frame, entry));
+}
+
+/**
+ * mgmt_rx_reo_list_release_entries() - Release entries from the reorder list
+ * @reo_list: Pointer to reorder list
+ *
+ * This API releases the entries from the reorder list based on the following
+ * conditions.
+ *   a) Entries with total wait count equal to 0
+ *   b) Entries which are timed out or entries with global time stamp <= global
+ *      time stamp of the latest frame which is timed out. We can only release
+ *      the entries in the increasing order of the global time stamp.
+ *      So all the entries with global time stamp <= global time stamp of the
+ *      latest timed out frame has to be released.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_list_release_entries(struct mgmt_rx_reo_list *reo_list)
+{
+	struct mgmt_rx_reo_list_entry *cur_entry;
+	struct mgmt_rx_reo_list_entry *temp;
+	/* TODO yield if release_count > THRESHOLD */
+	uint16_t release_count = 0;
+	QDF_STATUS status;
+
+	if (!reo_list) {
+		mgmt_rx_reo_err("reo list is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	qdf_spin_lock_bh(&reo_list->list_lock);
+
+	qdf_list_for_each_del(&reo_list->list, cur_entry, temp, node) {
+		if (mgmt_rx_reo_list_is_ready_to_send_up_entry(reo_list,
+							       cur_entry)) {
+			mgmt_rx_reo_debug("Freeing up entry %pK", cur_entry);
+			status = mgmt_rx_reo_list_entry_send_up(reo_list,
+								cur_entry);
+			if (QDF_IS_STATUS_ERROR(status))
+				goto error;
+
+			release_count++;
+		} else {
+			break;
+		}
+
+		qdf_mem_free(cur_entry);
+	}
+
+	status = QDF_STATUS_SUCCESS;
+error:
+	qdf_spin_unlock_bh(&reo_list->list_lock);
+	return status;
+}
+
+/**
+ * mgmt_rx_reo_list_ageout_timer_handler() - Periodic ageout timer handler
+ * @arg: Argument to timer handler
+ *
+ * This is the handler for periodic ageout timer used to timeout entries in the
+ * reorder list.
+ *
+ * Return: void
+ */
+static void
+mgmt_rx_reo_list_ageout_timer_handler(void *arg)
+{
+	struct mgmt_rx_reo_list *reo_list = arg;
+	struct mgmt_rx_reo_list_entry *cur_entry;
+	uint64_t cur_ts;
+	QDF_STATUS status;
+
+	if (!reo_list)
+		return;
+
+	qdf_spin_lock_bh(&reo_list->list_lock);
+
+	cur_ts = qdf_get_log_timestamp();
+
+	qdf_list_for_each(&reo_list->list, cur_entry, node) {
+		if (cur_ts - cur_entry->insertion_ts >=
+		    MGMT_RX_REO_LIST_TIMEOUT) {
+			uint32_t cur_entry_global_ts;
+			struct mgmt_rx_reo_global_ts_info *ts_ageout;
+
+			ts_ageout = &reo_list->ts_latest_aged_out_frame;
+			cur_entry_global_ts = mgmt_rx_reo_get_global_ts(
+					      cur_entry->rx_params);
+
+			if (!ts_ageout->valid ||
+			    mgmt_rx_reo_compare_global_timestamps_gte(
+			    cur_entry_global_ts, ts_ageout->global_ts)) {
+				ts_ageout->global_ts = cur_entry_global_ts;
+				ts_ageout->valid = true;
+			}
+
+			cur_entry->status |= MGMT_RX_REO_STATUS_AGED_OUT;
+		}
+	}
+
+	qdf_spin_unlock_bh(&reo_list->list_lock);
+
+	status = mgmt_rx_reo_list_release_entries(reo_list);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to release list entries, status = %d",
+				status);
+		return;
+	}
+}
+
+/**
+ * mgmt_rx_reo_prepare_list_entry() - Prepare a list entry from the management
+ * frame received.
+ * @frame_desc: Pointer to the frame descriptor
+ * @entry: Pointer to the list entry
+ *
+ * This API prepares the reorder list entry corresponding to a management frame
+ * to be consumed by host. This entry would be inserted at the appropriate
+ * position in the reorder list.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_prepare_list_entry(
+		const struct mgmt_rx_reo_frame_descriptor *frame_desc,
+		struct mgmt_rx_reo_list_entry **entry)
+{
+	struct mgmt_rx_reo_list_entry *list_entry;
+	struct wlan_objmgr_pdev *pdev;
+	QDF_STATUS status;
+	uint8_t link_id;
+
+	if (!frame_desc) {
+		mgmt_rx_reo_err("frame descriptor is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!entry) {
+		mgmt_rx_reo_err("Pointer to list entry is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	link_id = mgmt_rx_reo_get_link_id(frame_desc->rx_params);
+
+	pdev = wlan_get_pdev_from_mlo_link_id(link_id);
+	if (!pdev) {
+		mgmt_rx_reo_err("pdev corresponding to link %u is null",
+				link_id);
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	/* Take the reference when the entry is created for insertion */
+	status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_MGMT_RX_REO_ID);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to get ref to pdev");
+		return QDF_STATUS_E_FAILURE;
+	}
+
+	list_entry =  qdf_mem_malloc(sizeof(*list_entry));
+	if (!list_entry) {
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_RX_REO_ID);
+		mgmt_rx_reo_err("List entry allocation failed");
+		return QDF_STATUS_E_NOMEM;
+	}
+
+	list_entry->nbuf = frame_desc->nbuf;
+	list_entry->rx_params = frame_desc->rx_params;
+	list_entry->wait_count = frame_desc->wait_count;
+	list_entry->status = 0;
+	if (list_entry->wait_count.total_count)
+		list_entry->status |=
+			MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS;
+
+	*entry = list_entry;
+
+	mgmt_rx_reo_debug("New entry to be inserted is %pK", list_entry);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mgmt_rx_reo_update_wait_count() - Update the wait count for a frame based
+ * on the wait count of a frame received after that on air.
+ * @num_mlo_links: Number of MLO links
+ * @wait_count_old_frame: Pointer to the wait count structure for the old frame.
+ * @wait_count_new_frame: Pointer to the wait count structure for the new frame.
+ *
+ * This API optimizes the wait count of a frame based on the wait count of
+ * a frame received after that on air. Old frame refers to the frame received
+ * first on the air and new frame refers to the frame received after that.
+ * We use the following fundamental idea. Wait counts for old frames can't be
+ * more than wait counts for the new frame. Use this to optimize the wait count
+ * for the old frames. Per link wait count of an old frame is minimum of the
+ * per link wait count of the old frame and new frame.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_update_wait_count(
+		uint8_t num_mlo_links,
+		struct mgmt_rx_reo_wait_count *wait_count_old_frame,
+		const struct mgmt_rx_reo_wait_count *wait_count_new_frame)
+{
+	uint8_t link_id;
+
+	qdf_assert_always(wait_count_old_frame);
+	qdf_assert_always(wait_count_new_frame);
+
+	qdf_assert_always(num_mlo_links >= 1);
+	qdf_assert_always(num_mlo_links <= MGMT_RX_REO_MAX_LINKS);
+
+	for (link_id = 0; link_id < num_mlo_links; link_id++) {
+		if (wait_count_old_frame->per_link_count[link_id]) {
+			uint32_t temp_wait_count;
+			uint32_t wait_count_diff;
+
+			temp_wait_count =
+				wait_count_old_frame->per_link_count[link_id];
+			wait_count_old_frame->per_link_count[link_id] =
+				qdf_min(wait_count_old_frame->
+					per_link_count[link_id],
+					wait_count_new_frame->
+					per_link_count[link_id]);
+			wait_count_diff = temp_wait_count -
+				wait_count_old_frame->per_link_count[link_id];
+
+			wait_count_old_frame->total_count -= wait_count_diff;
+		}
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mgmt_rx_reo_update_list() - Modify the reorder list when a frame is received
+ * @reo_list: Pointer to reorder list
+ * @num_mlo_links: Number of MLO HW links
+ * @frame_desc: Pointer to frame descriptor
+ *
+ * API to update the reorder list on every management frame reception.
+ * This API does the following things.
+ *   a) Update the wait counts for all the frames in the reorder list with
+ *      global time stamp <= current frame's global time stamp. We use the
+ *      following principle for updating the wait count in this case.
+ *      Let A and B be two management frames with global time stamp of A <=
+ *      global time stamp of B. Let WAi and WBi be the wait count of A and B
+ *      for link i, then WAi <= WBi. Hence we can optimize WAi as
+ *      min(WAi, WBi).
+ *   b) If the current frame is to be consumed by host, insert it in the
+ *      reorder list such that the list is always sorted in the increasing order
+ *      of global time stamp. Update the wait count of the current frame based
+ *      on the frame next to it in the reorder list (if any).
+ *   c) Update the wait count of the frames in the reorder list with global
+ *      time stamp > current frame's global time stamp. Let the current frame
+ *      belong to link "l". Then link "l"'s wait count can be reduced by one for
+ *      all the frames in the reorder list with global time stamp > current
+ *      frame's global time stamp.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_update_list(struct mgmt_rx_reo_list *reo_list,
+			uint8_t num_mlo_links,
+			struct mgmt_rx_reo_frame_descriptor *frame_desc)
+{
+	struct mgmt_rx_reo_list_entry *cur_entry;
+	struct mgmt_rx_reo_list_entry *least_greater_entry;
+	bool least_greater_entry_found = false;
+	QDF_STATUS status;
+	uint32_t new_frame_global_ts;
+	struct mgmt_rx_reo_list_entry *new_entry = NULL;
+
+	if (!reo_list) {
+		mgmt_rx_reo_err("Mgmt Rx reo list is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	if (!frame_desc) {
+		mgmt_rx_reo_err("Mgmt frame descriptor is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	new_frame_global_ts = mgmt_rx_reo_get_global_ts(frame_desc->rx_params);
+
+	/* Prepare the list entry before acquiring lock */
+	if (frame_desc->type == MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME) {
+		status = mgmt_rx_reo_prepare_list_entry(frame_desc, &new_entry);
+		if (QDF_IS_STATUS_ERROR(status)) {
+			mgmt_rx_reo_err("Failed to prepare list entry");
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+
+	qdf_spin_lock_bh(&reo_list->list_lock);
+
+	qdf_list_for_each(&reo_list->list, cur_entry, node) {
+		uint32_t cur_entry_global_ts;
+
+		cur_entry_global_ts = mgmt_rx_reo_get_global_ts(
+					cur_entry->rx_params);
+
+		if (!mgmt_rx_reo_compare_global_timestamps_gte(
+		    new_frame_global_ts, cur_entry_global_ts)) {
+			least_greater_entry = cur_entry;
+			least_greater_entry_found = true;
+			break;
+		}
+
+		status = mgmt_rx_reo_update_wait_count(
+					num_mlo_links,
+					&cur_entry->wait_count,
+					&frame_desc->wait_count);
+		if (QDF_IS_STATUS_ERROR(status))
+			goto error;
+
+		if (cur_entry->wait_count.total_count == 0)
+			cur_entry->status &=
+			      ~MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS;
+	}
+
+	if (frame_desc->type == MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME) {
+		if (least_greater_entry_found) {
+			status = mgmt_rx_reo_update_wait_count(
+					num_mlo_links,
+					&new_entry->wait_count,
+					&least_greater_entry->wait_count);
+
+			if (QDF_IS_STATUS_ERROR(status))
+				goto error;
+
+			if (new_entry->wait_count.total_count == 0)
+				new_entry->status &=
+					~MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS;
+		}
+
+		new_entry->insertion_ts = qdf_get_log_timestamp();
+
+		status = qdf_list_insert_before(&reo_list->list,
+						&new_entry->node,
+						&least_greater_entry->node);
+		if (QDF_IS_STATUS_ERROR(status))
+			goto error;
+	}
+
+	cur_entry = least_greater_entry;
+	qdf_list_for_each_from(&reo_list->list, cur_entry, node) {
+		uint8_t frame_link_id;
+
+		frame_link_id = mgmt_rx_reo_get_link_id(frame_desc->rx_params);
+		if (cur_entry->wait_count.per_link_count[frame_link_id]) {
+			cur_entry->wait_count.per_link_count[frame_link_id]--;
+			cur_entry->wait_count.total_count--;
+			if (cur_entry->wait_count.total_count == 0)
+				cur_entry->status &=
+					~MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS;
+		}
+	}
+
+	status = QDF_STATUS_SUCCESS;
+	goto exit;
+
+error:
+	/* TODO check whether frame is not queued and then do the cleanup */
+	if (new_entry) {
+		struct wlan_objmgr_pdev *pdev;
+		uint8_t link_id;
+
+		link_id = mgmt_rx_reo_get_link_id(new_entry->rx_params);
+
+		pdev = wlan_get_pdev_from_mlo_link_id(link_id);
+		qdf_assert_always(pdev);
+
+		/**
+		 * New entry created is not inserted to reorder list, free
+		 * the entry and release the reference
+		 */
+		qdf_mem_free(new_entry);
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_RX_REO_ID);
+	}
+
+exit:
+	qdf_spin_unlock_bh(&reo_list->list_lock);
+
+	/* TODO check whether frame is queued and then print */
+	if (frame_desc->type == MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME) {
+		if (least_greater_entry_found)
+			mgmt_rx_reo_debug("Inserting new entry %pK before %pK",
+					  new_entry, least_greater_entry);
+		else
+			mgmt_rx_reo_debug("Inserting new entry %pK at the tail",
+					  new_entry);
+	}
+
+	return status;
+}
+
+/**
+ * mgmt_rx_reo_list_init() - Initialize the management rx-reorder list
+ * @reo_list: Pointer to reorder list
+ *
+ * API to initialize the management rx-reorder list.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_list_init(struct mgmt_rx_reo_list *reo_list)
+{
+	QDF_STATUS status;
+
+	reo_list->max_list_size = MGMT_RX_REO_MAX_LIST_SIZE;
+	qdf_list_create(&reo_list->list, reo_list->max_list_size);
+	qdf_spinlock_create(&reo_list->list_lock);
+
+	status = qdf_timer_init(NULL, &reo_list->ageout_timer,
+				mgmt_rx_reo_list_ageout_timer_handler, reo_list,
+				QDF_TIMER_TYPE_WAKE_APPS);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to initialize reo list ageout timer");
+		return status;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+mgmt_rx_reo_init_context(void)
+{
+	QDF_STATUS status;
+	struct mgmt_rx_reo_context *reo_context;
+
+	reo_context = mgmt_rx_reo_get_context();
+	if (!reo_context) {
+		mgmt_rx_reo_err("reo context is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+	qdf_mem_zero(reo_context, sizeof(*reo_context));
+
+	status = mgmt_rx_reo_list_init(&reo_context->reo_list);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to initialize mgmt Rx reo list");
+		return status;
+	}
+
+	reo_context->ts_last_delivered_frame.valid = false;
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mgmt_rx_reo_flush_reorder_list() - flush all entries in the reorder list
+ * @reo_list: pointer to reorder list
+ *
+ * api to flush all the entries of the reorder list. this api would acquire
+ * the lock protecting the list.
+ *
+ * return: qdf_status
+ */
+static QDF_STATUS
+mgmt_rx_reo_flush_reorder_list(struct mgmt_rx_reo_list *reo_list)
+{
+	struct mgmt_rx_reo_list_entry *cur_entry;
+	struct mgmt_rx_reo_list_entry *temp;
+
+	if (!reo_list) {
+		mgmt_rx_reo_err("reorder list is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	qdf_spin_lock_bh(&reo_list->list_lock);
+
+	qdf_list_for_each_del(&reo_list->list, cur_entry, temp, node) {
+		uint8_t link_id;
+		struct wlan_objmgr_pdev *pdev = NULL;
+
+		free_mgmt_rx_event_params(cur_entry->rx_params);
+
+		link_id = mgmt_rx_reo_get_link_id(cur_entry->rx_params);
+
+		pdev = wlan_get_pdev_from_mlo_link_id(link_id);
+		if (!pdev) {
+			qdf_spin_unlock_bh(&reo_list->list_lock);
+			mgmt_rx_reo_err("pdev for link_id %u is null", link_id);
+			return QDF_STATUS_E_NULL_VALUE;
+		}
+
+		/**
+		 * Release the reference taken when the entry is inserted into
+		 * the reorder list
+		 */
+		wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_RX_REO_ID);
+
+		qdf_mem_free(cur_entry);
+	}
+
+	qdf_spin_unlock_bh(&reo_list->list_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * mgmt_rx_reo_list_deinit() - De initialize the management rx-reorder list
+ * @reo_list: Pointer to reorder list
+ *
+ * API to de initialize the management rx-reorder list.
+ *
+ * Return: QDF_STATUS
+ */
+static QDF_STATUS
+mgmt_rx_reo_list_deinit(struct mgmt_rx_reo_list *reo_list)
+{
+	QDF_STATUS status;
+
+	qdf_timer_free(&reo_list->ageout_timer);
+
+	status = mgmt_rx_reo_flush_reorder_list(reo_list);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to flush the reorder list");
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spinlock_destroy(&reo_list->list_lock);
+	qdf_list_destroy(&reo_list->list);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+mgmt_rx_reo_deinit_context(void)
+{
+	QDF_STATUS status;
+	struct mgmt_rx_reo_context *reo_context;
+
+	reo_context = mgmt_rx_reo_get_context();
+	if (!reo_context) {
+		mgmt_rx_reo_err("reo context is null");
+		return QDF_STATUS_E_NULL_VALUE;
+	}
+
+	status = mgmt_rx_reo_list_deinit(&reo_context->reo_list);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		mgmt_rx_reo_err("Failed to de-initialize mgmt Rx reo list");
+		return status;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}

+ 170 - 17
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_rx_reo_i.h

@@ -22,6 +22,7 @@
 #ifndef _WLAN_MGMT_TXRX_RX_REO_I_H
 #define _WLAN_MGMT_TXRX_RX_REO_I_H
 
+#ifdef WLAN_MGMT_RX_REO_SUPPORT
 #include <qdf_list.h>
 #include <qdf_timer.h>
 #include <qdf_lock.h>
@@ -31,6 +32,55 @@
 #include <wlan_objmgr_pdev_obj.h>
 #include <wlan_objmgr_psoc_obj.h>
 
+#define MGMT_RX_REO_MAX_LIST_SIZE        (100)
+#define MGMT_RX_REO_LIST_TIMEOUT         (10 * USEC_PER_MSEC)
+#define MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS  (BIT(0))
+#define MGMT_RX_REO_STATUS_AGED_OUT                       (BIT(1))
+/**
+ * TODO: Dummy macro for Maximum MLO links on the system
+ * This is added only as a place holder for the time being.
+ * Remove this once the actual one is implemented.
+ */
+#define MGMT_RX_REO_MAX_LINKS (16)
+/* Reason to release an entry from the reorder list */
+#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_ZERO_WAIT_COUNT           (BIT(0))
+#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_AGED_OUT                  (BIT(1))
+#define MGMT_RX_REO_LIST_ENTRY_RELEASE_REASON_OLDER_THAN_AGED_OUT_FRAME (BIT(2))
+
+#define MGMT_RX_REO_LIST_ENTRY_IS_WAITING_FOR_FRAME_ON_OTHER_LINK(entry)   \
+	((entry)->status & MGMT_RX_REO_STATUS_WAIT_FOR_FRAME_ON_OTHER_LINKS)
+#define MGMT_RX_REO_LIST_ENTRY_IS_AGED_OUT(entry)   \
+	((entry)->status & MGMT_RX_REO_STATUS_AGED_OUT)
+#define MGMT_RX_REO_LIST_ENTRY_IS_OLDER_THAN_LATEST_AGED_OUT_FRAME(ts, entry)  \
+	(mgmt_rx_reo_compare_global_timestamps_gte(                            \
+	 (ts)->global_ts, mgmt_rx_reo_get_global_ts((entry)->rx_params)))
+
+/**
+ * enum mgmt_rx_reo_frame_descriptor_type - Enumeration for management frame
+ * descriptor type.
+ * @MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME: Management frame to be consumed
+ * by host.
+ * @MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME: Management frame consumed by FW
+ * @MGMT_RX_REO_FRAME_DESC_ERROR_FRAME: Management frame which got dropped
+ * at host due to any error
+ */
+enum mgmt_rx_reo_frame_descriptor_type {
+	MGMT_RX_REO_FRAME_DESC_HOST_CONSUMED_FRAME,
+	MGMT_RX_REO_FRAME_DESC_FW_CONSUMED_FRAME,
+	MGMT_RX_REO_FRAME_DESC_ERROR_FRAME,
+};
+
+/**
+ * struct mgmt_rx_reo_global_ts_info - This structure holds the global time
+ * stamp information of a frame.
+ * @global_ts: Global time stamp value
+ * @valid: Indicates whether global time stamp is valid
+ */
+struct mgmt_rx_reo_global_ts_info {
+	bool valid;
+	uint32_t global_ts;
+};
+
 /**
  * struct mgmt_rx_reo_list – Linked list used to reorder the management frames
  * received. Each list entry would correspond to a management frame. List
@@ -38,22 +88,20 @@
  * HW.
  * @list: List used for reordering
  * @list_lock: Lock to protect the list
- * @num_entries: Number of entries in the list
+ * @max_list_size: Maximum size of the reorder list
  * @ageout_timer: Periodic timer to age-out the list entries
+ * @ts_latest_aged_out_frame: Stores the global time stamp for the latest aged
+ * out frame. Latest aged out frame is the aged out frame in reorder list which
+ * has the largest global time stamp value.
  */
 struct mgmt_rx_reo_list {
 	qdf_list_t list;
 	qdf_spinlock_t list_lock;
-	uint32_t num_entries;
+	uint32_t max_list_size;
 	qdf_timer_t ageout_timer;
+	struct mgmt_rx_reo_global_ts_info ts_latest_aged_out_frame;
 };
 
-/**
- * TODO: Dummy macro for Maximum MLO links on the system
- * This is added only as a place holder for the time being.
- * Remove this once the actual one is implemented.
- */
-#define MGMT_RX_REO_MAX_LINKS (16)
 /*
  * struct mgmt_rx_reo_wait_count - Wait count for a mgmt frame
  * @per_link_count: Array of wait counts for all MLO links. Each array entry
@@ -63,22 +111,26 @@ struct mgmt_rx_reo_list {
  */
 struct mgmt_rx_reo_wait_count {
 	unsigned int per_link_count[MGMT_RX_REO_MAX_LINKS];
-	unsigned int total_count;
+	unsigned long long int total_count;
 };
 
 /**
  * struct mgmt_rx_reo_list_entry - Entry in the Management reorder list
- * @node: list node
- * @wbuf: nbuf corresponding to this frame.
+ * @node: List node
+ * @nbuf: nbuf corresponding to this frame
  * @rx_params: Management rx event parameters
- * @insertion_timestamp: Host time stamp when this entry is inserted to
+ * @wait_count: Wait counts for the frame
+ * @insertion_ts: Host time stamp when this entry is inserted to
  * the list.
+ * @status: Status for this entry
  */
 struct mgmt_rx_reo_list_entry {
 	qdf_list_node_t node;
-	qdf_nbuf_t wbuf;
-	struct mgmt_rx_event_params rx_params;
-	uint32_t insertion_timestamp;
+	qdf_nbuf_t nbuf;
+	struct mgmt_rx_event_params *rx_params;
+	struct mgmt_rx_reo_wait_count wait_count;
+	uint64_t insertion_ts;
+	uint32_t status;
 };
 
 /**
@@ -86,11 +138,112 @@ struct mgmt_rx_reo_list_entry {
  * management rx-reordering. Reordering is done across all the psocs.
  * So there should be only one instance of this structure defined.
  * @reo_list: Linked list used for reordering
- * @global_ts_last_delivered_frame: HW time stamp of the last frame
+ * @ts_last_delivered_frame: Stores the global time stamp for the last frame
  * delivered to the upper layer
  */
 struct mgmt_rx_reo_context {
 	struct mgmt_rx_reo_list reo_list;
-	uint32_t global_ts_last_delivered_frame;
+	struct mgmt_rx_reo_global_ts_info ts_last_delivered_frame;
 };
+
+/**
+ * struct mgmt_rx_reo_frame_descriptor - Frame Descriptor used to describe
+ * a management frame in mgmt rx reo module.
+ * @type: Frame descriptor type
+ * @nbuf: nbuf corresponding to this frame
+ * @rx_params: Management rx event parameters
+ * @wait_count: Wait counts for the frame
+ */
+struct mgmt_rx_reo_frame_descriptor {
+	enum mgmt_rx_reo_frame_descriptor_type type;
+	qdf_nbuf_t nbuf;
+	struct mgmt_rx_event_params *rx_params;
+	struct mgmt_rx_reo_wait_count wait_count;
+};
+
+/**
+ * mgmt_rx_reo_get_global_ts() - Helper API to get global time stamp
+ * corresponding to the mgmt rx event
+ * @rx_params: Management rx event params
+ *
+ * Return: global time stamp corresponding to the mgmt rx event
+ */
+static inline uint32_t
+mgmt_rx_reo_get_global_ts(struct mgmt_rx_event_params *rx_params)
+{
+	qdf_assert_always(rx_params);
+	qdf_assert_always(rx_params->reo_params);
+
+	return rx_params->reo_params->global_timestamp;
+}
+
+/**
+ * mgmt_rx_reo_get_pkt_counter() - Helper API to get packet counter
+ * corresponding to the mgmt rx event
+ * @rx_params: Management rx event params
+ *
+ * Return: Management packet counter corresponding to the mgmt rx event
+ */
+static inline uint16_t
+mgmt_rx_reo_get_pkt_counter(struct mgmt_rx_event_params *rx_params)
+{
+	qdf_assert_always(rx_params);
+	qdf_assert_always(rx_params->reo_params);
+
+	return rx_params->reo_params->mgmt_pkt_ctr;
+}
+
+/**
+ * mgmt_rx_reo_get_link_id() - Helper API to get link id corresponding to the
+ * mgmt rx event
+ * @rx_params: Management rx event params
+ *
+ * Return: link id corresponding to the mgmt rx event
+ */
+static inline uint8_t
+mgmt_rx_reo_get_link_id(struct mgmt_rx_event_params *rx_params)
+{
+	qdf_assert_always(rx_params);
+	qdf_assert_always(rx_params->reo_params);
+
+	return rx_params->reo_params->link_id;
+}
+
+/**
+ * mgmt_rx_reo_get_pdev_id() - Helper API to get pdev id corresponding to the
+ * mgmt rx event
+ * @rx_params: Management rx event params
+ *
+ * Return: pdev id corresponding to the mgmt rx event
+ */
+static inline uint8_t
+mgmt_rx_reo_get_pdev_id(struct mgmt_rx_event_params *rx_params)
+{
+	qdf_assert_always(rx_params);
+	qdf_assert_always(rx_params->reo_params);
+
+	return rx_params->reo_params->pdev_id;
+}
+
+/**
+ * mgmt_rx_reo_init_context() - Initialize the management rx-reorder context
+ *
+ * API to initialize the global management rx-reorder context object.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+mgmt_rx_reo_init_context(void);
+
+/**
+ * mgmt_rx_reo_deinit_context() - De initialize the management rx-reorder
+ * context
+ *
+ * API to de initialize the global management rx-reorder context object.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+mgmt_rx_reo_deinit_context(void);
+#endif /* WLAN_MGMT_RX_REO_SUPPORT */
 #endif /* _WLAN_MGMT_TXRX_RX_REO_I_H */

+ 3 - 1
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_rx_reo_public_structs.h

@@ -70,12 +70,14 @@ struct mgmt_rx_reo_snapshot {
  * struct mgmt_rx_reo_params - MGMT Rx REO parameters
  * @valid: Whether these params are valid
  * @pdev_id: pdev ID for which FW consumed event is received
+ * @link_id: link ID for which FW consumed event is received
  * @mgmt_pkt_ctr: MGMT packet counter of the frame that is consumed
  * @global_timestamp: Global timestamp of the frame that is consumed
  */
 struct mgmt_rx_reo_params {
 	bool valid;
-	uint8_t  pdev_id;
+	uint8_t pdev_id;
+	uint8_t link_id;
 	uint16_t mgmt_pkt_ctr;
 	uint32_t global_timestamp;
 };

+ 50 - 0
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_rx_reo_utils_api.h

@@ -37,6 +37,28 @@ struct mgmt_txrx_priv_pdev_context;
 #define mgmt_rx_reo_info mgmt_txrx_info
 #define mgmt_rx_reo_debug mgmt_txrx_debug
 
+/**
+ * wlan_mgmt_rx_reo_init() - Initializes the management rx-reorder module
+ *
+ * This function gets called from dispatcher init and initializes the management
+ * rx-reorder module.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_mgmt_rx_reo_init(void);
+
+/**
+ * wlan_mgmt_rx_reo_deinit() - De initializes the management rx-reorder module
+ *
+ * This function gets called from dispatcher deinit and de initializes the
+ * management rx-reorder module.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_mgmt_rx_reo_deinit(void);
+
 /**
  * wlan_mgmt_rx_reo_pdev_obj_create_notification() - pdev create handler for
  * management rx-reorder module
@@ -112,5 +134,33 @@ wlan_mgmt_rx_reo_pdev_obj_destroy_notification(
 {
 	return QDF_STATUS_SUCCESS;
 }
+
+/**
+ * wlan_mgmt_rx_reo_init() - Initializes the management rx-reorder module
+ *
+ * This function gets called from dispatcher init and initializes the management
+ * rx-reorder module.
+ *
+ * Return: QDF_STATUS
+ */
+static inline QDF_STATUS
+wlan_mgmt_rx_reo_init(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * wlan_mgmt_rx_reo_deinit() - De initializes the management rx-reorder module
+ *
+ * This function gets called from dispatcher deinit and de initializes the
+ * management rx-reorder module.
+ *
+ * Return: QDF_STATUS
+ */
+static inline QDF_STATUS
+wlan_mgmt_rx_reo_deinit(void)
+{
+	return QDF_STATUS_SUCCESS;
+}
 #endif /* WLAN_MGMT_RX_REO_SUPPORT */
 #endif /* _WLAN_MGMT_TXRX_RX_REO_UTILS_API_H_ */

+ 45 - 0
umac/cmn_services/mgmt_txrx/dispatcher/inc/wlan_mgmt_txrx_utils_api.h

@@ -796,6 +796,51 @@ struct mgmt_rx_event_params {
 #endif
 };
 
+#ifdef WLAN_MGMT_RX_REO_SUPPORT
+static inline
+struct mgmt_rx_event_params *alloc_mgmt_rx_event_params(void)
+{
+	struct mgmt_rx_event_params *rx_params;
+
+	rx_params = qdf_mem_malloc(sizeof(struct mgmt_rx_event_params));
+	if (!rx_params)
+		return NULL;
+
+	rx_params->reo_params =
+		qdf_mem_malloc(sizeof(struct mgmt_rx_reo_params));
+
+	if (!rx_params->reo_params) {
+		qdf_mem_free(rx_params);
+		return NULL;
+	}
+
+	return rx_params;
+}
+
+static inline void
+free_mgmt_rx_event_params(struct mgmt_rx_event_params *rx_params)
+{
+	if (rx_params)
+		qdf_mem_free(rx_params->reo_params);
+
+	qdf_mem_free(rx_params);
+}
+#else
+static inline
+struct mgmt_rx_event_params *alloc_mgmt_rx_event_params(void)
+{
+	struct mgmt_rx_event_params *rx_params;
+
+	rx_params = qdf_mem_malloc(sizeof(struct mgmt_rx_event_params));
+	if (!rx_params)
+		return NULL;
+
+	return rx_params;
+}
+
+#define free_mgmt_rx_event_params(rx_params) qdf_mem_free((rx_params))
+#endif
+
 /**
  * mgmt_tx_download_comp_cb - function pointer for tx download completions.
  * @context: caller component specific context

+ 12 - 0
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_rx_reo_utils_api.c

@@ -158,3 +158,15 @@ wlan_mgmt_rx_reo_pdev_obj_destroy_notification(
 
 	return QDF_STATUS_SUCCESS;
 }
+
+QDF_STATUS
+wlan_mgmt_rx_reo_deinit(void)
+{
+	return mgmt_rx_reo_deinit_context();
+}
+
+QDF_STATUS
+wlan_mgmt_rx_reo_init(void)
+{
+	return mgmt_rx_reo_init_context();
+}

+ 15 - 1
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_utils_api.c

@@ -324,9 +324,19 @@ QDF_STATUS wlan_mgmt_txrx_init(void)
 		goto err_pdev_delete;
 	}
 
+	status = wlan_mgmt_rx_reo_init();
+	if (status != QDF_STATUS_SUCCESS) {
+		mgmt_txrx_err("Failed to initialize mgmt Rx reo module");
+		goto err_reo_init;
+	}
+
 	mgmt_txrx_debug("Successfully registered create and destroy handlers with objmgr");
 	return QDF_STATUS_SUCCESS;
 
+err_reo_init:
+	wlan_objmgr_unregister_pdev_destroy_handler(
+			WLAN_UMAC_COMP_MGMT_TXRX,
+			wlan_mgmt_txrx_pdev_obj_destroy_notification, NULL);
 err_pdev_delete:
 	wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
 			wlan_mgmt_txrx_pdev_obj_create_notification, NULL);
@@ -342,6 +352,11 @@ err_psoc_create:
 
 QDF_STATUS wlan_mgmt_txrx_deinit(void)
 {
+	if (QDF_IS_STATUS_ERROR(wlan_mgmt_rx_reo_deinit())) {
+		mgmt_txrx_err("Failed to de-initialize mgmt Rx reo module");
+		return QDF_STATUS_E_FAILURE;
+	}
+
 	if (wlan_objmgr_unregister_psoc_create_handler(WLAN_UMAC_COMP_MGMT_TXRX,
 				wlan_mgmt_txrx_psoc_obj_create_notification,
 				NULL)
@@ -372,7 +387,6 @@ QDF_STATUS wlan_mgmt_txrx_deinit(void)
 		return QDF_STATUS_E_FAILURE;
 	}
 
-
 	mgmt_txrx_debug("Successfully unregistered create and destroy handlers with objmgr");
 	return QDF_STATUS_SUCCESS;
 }

+ 4 - 1
umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h

@@ -282,6 +282,7 @@ typedef void (*wlan_objmgr_peer_status_handler)(
  * @WLAN_OSIF_CM_ID:            Connection manager osif reference id
  * @WLAN_TXRX_STREAMS_ID:       Preferred TX & RX streams operations
  * @WLAN_MLO_MGR_ID:            MLO manager reference id
+ * @WLAN_MGMT_RX_REO_ID:        Management rx reorder reference id
  * @WLAN_REF_ID_MAX:            Max id used to generate ref count tracking array
  */
  /* New value added to the enum must also be reflected in function
@@ -381,6 +382,7 @@ typedef enum {
 	WLAN_TXRX_STREAMS_ID  = 89,
 	WLAN_MLO_MGR_ID       = 90,
 	WLAN_MBSS_ID          = 91,
+	WLAN_MGMT_RX_REO_ID   = 92,
 	WLAN_REF_ID_MAX,
 } wlan_objmgr_ref_dbgid;
 
@@ -485,7 +487,8 @@ static inline const char *string_from_dbgid(wlan_objmgr_ref_dbgid id)
 					"WLAN_OSIF_CM_ID",
 					"WLAN_TXRX_STREAMS_ID",
 					"WLAN_MLO_MGR_ID",
-					"WLAN_MBSS_ID"
+					"WLAN_MBSS_ID",
+					"WLAN_MGMT_RX_REO_ID"
 					};
 
 	if (id >= WLAN_REF_ID_MAX)