Browse Source

qcacmn: Enhancements to the serialization component

1. Split the serialization API's into the following files
  1. serialization_api.c	: Serialization public API's.
  2. serialization_internal.c	: Serialization internal API's.
  3. serialization_queue.c	: Serialization pdev/vdev queues API's.
  4. serialization_main.c	: Serialization object manager related API's.
  5. serialization_utils.c 	: Serialization low level primitive API's.

2. Following files are not not used with new serialization
  1. serialization_enqueue.c
  2. serialization_dequeue.c

3. Using the new queue objects for pdev/vdev and component specific.

4. Implemented Locks for request, release and cancel APIs.

5. Removed locks for the lowest primitive queue API's

6. Timers executed in mc thread from MCL and timer context for WIN.

7. Allow cmds from multiple vdevs in parallel in non blocking mode.

Change-Id: I3cabcf512225331db46956ffad4ddab581c7e52b
CRs-Fixed: 2304513
Vivek 6 years ago
parent
commit
277ac5d63e

+ 492 - 0
umac/cmn_services/serialization/inc/wlan_serialization_api.h

@@ -27,6 +27,7 @@
 #ifndef __WLAN_SERIALIZATION_API_H
 #define __WLAN_SERIALIZATION_API_H
 
+#ifdef CONFIG_SERIALIZATION_V1
 #include "qdf_status.h"
 #include "wlan_objmgr_cmn.h"
 
@@ -504,4 +505,495 @@ wlan_serialization_get_scan_cmd_using_scan_id(
 void *wlan_serialization_get_active_cmd(struct wlan_objmgr_psoc *psoc,
 				     uint8_t vdev_id,
 				     enum wlan_serialization_cmd_type cmd_type);
+#else /* New serialization code*/
+#include <qdf_status.h>
+#include <wlan_objmgr_cmn.h>
+
+/* Preprocessor Definitions and Constants */
+
+/*
+ * struct wlan_serialization_queued_cmd_info member queue_type specifies the
+ * below values to cancel the commands in these queues. Setting both the
+ * bits will cancel the commands in both the queues.
+ */
+#define WLAN_SERIALIZATION_ACTIVE_QUEUE  0x1
+#define WLAN_SERIALIZATION_PENDING_QUEUE 0x2
+
+/**
+ * enum wlan_serialization_cb_reason - reason for calling the callback
+ * @WLAN_SERIALIZATION_REASON_ACTIVATE_CMD: activate the cmd by sending it to FW
+ * @WLAN_SERIALIZATION_REASON_CANCEL_CMD: Cancel the cmd in the pending list
+ * @WLAN_SERIALIZATION_REASON_RELEASE_MEM_CMD:cmd execution complete. Release
+ *                                           the memory allocated while
+ *                                           building the command
+ * @WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: active cmd has been timeout.
+ */
+enum wlan_serialization_cb_reason {
+	WLAN_SER_CB_ACTIVATE_CMD,
+	WLAN_SER_CB_CANCEL_CMD,
+	WLAN_SER_CB_RELEASE_MEM_CMD,
+	WLAN_SER_CB_ACTIVE_CMD_TIMEOUT,
+};
+
+/**
+ * struct wlan_serialization_scan_info - Information needed for scan cmd
+ * @is_cac_in_progress: boolean to check the cac status
+ * @is_tdls_in_progress: boolean to check the tdls status
+ *
+ * This information is needed for scan command from other components
+ * to apply the rules and check whether the cmd is allowed or not
+ */
+struct wlan_serialization_scan_info {
+	bool is_cac_in_progress;
+	bool is_tdls_in_progress;
+};
+
+/**
+ * union wlan_serialization_rules_info - union of all rules info structures
+ * @scan_info: information needed to apply rules on scan command
+ */
+union wlan_serialization_rules_info {
+	struct wlan_serialization_scan_info scan_info;
+};
+
+/**
+ * wlan_serialization_cmd_callback() - Callback registered by the component
+ * @wlan_cmd: Command passed by the component for serialization
+ * @reason: Reason code for which the callback is being called
+ *
+ * Reason specifies the reason for which the callback is being called. callback
+ * should return success or failure based up on overall success of callback.
+ * if callback returns failure then serialization will remove the command from
+ * active queue and proceed for next pending command.
+ *
+ * Return: QDF_STATUS_SUCCESS or QDF_STATUS_E_FAILURE
+ */
+typedef QDF_STATUS (*wlan_serialization_cmd_callback)(void *wlan_cmd,
+				 enum wlan_serialization_cb_reason reason);
+
+/**
+ * wlan_serialization_comp_info_cb() - callback to fill the rules information
+ * @vdev: VDEV object for which the command has been received
+ * @comp_info: Information filled by the component
+ *
+ * This callback is registered dynamically by the component with the
+ * serialization component. Serialization component invokes the callback
+ * while applying the rules for a particular command and the component
+ * fills in the required information to apply the rules
+ *
+ * Return: None
+ */
+typedef void (*wlan_serialization_comp_info_cb)(struct wlan_objmgr_vdev *vdev,
+		union wlan_serialization_rules_info *comp_info);
+
+/**
+ * wlan_serialization_apply_rules_cb() - callback per command to apply rules
+ * @comp_info: information needed to apply the rules
+ *
+ * The rules are applied using this callback and decided whether to
+ * allow or deny the command
+ *
+ * Return: true, if rules are successful and cmd can be queued
+ *         false, if rules failed and cmd should not be queued
+ */
+typedef bool (*wlan_serialization_apply_rules_cb)(
+		union wlan_serialization_rules_info *comp_info,
+		uint8_t comp_id);
+
+/**
+ * enum wlan_umac_cmd_id - Command Type
+ * @WLAN_SER_CMD_SCAN:     Scan command
+ */
+enum wlan_serialization_cmd_type {
+	/* all scan command before non-scan */
+	WLAN_SER_CMD_SCAN,
+	/* all non-scan command below */
+	WLAN_SER_CMD_NONSCAN,
+	WLAN_SER_CMD_FORCE_DISASSOC,
+	WLAN_SER_CMD_HDD_ISSUED,
+	WLAN_SER_CMD_LOST_LINK1,
+	WLAN_SER_CMD_LOST_LINK2,
+	WLAN_SER_CMD_LOST_LINK3,
+	WLAN_SER_CMD_FORCE_DISASSOC_MIC_FAIL,
+	WLAN_SER_CMD_HDD_ISSUE_REASSOC_SAME_AP,
+	WLAN_SER_CMD_SME_ISSUE_REASSOC_SAME_AP,
+	WLAN_SER_CMD_FORCE_DEAUTH,
+	WLAN_SER_CMD_SME_ISSUE_DISASSOC_FOR_HANDOFF,
+	WLAN_SER_CMD_SME_ISSUE_ASSOC_TO_SIMILAR_AP,
+	WLAN_SER_CMD_SME_ISSUE_IBSS_JOIN_FAIL,
+	WLAN_SER_CMD_FORCE_IBSS_LEAVE,
+	WLAN_SER_CMD_SME_ISSUE_FT_REASSOC,
+	WLAN_SER_CMD_FORCE_DISASSOC_STA,
+	WLAN_SER_CMD_FORCE_DEAUTH_STA,
+	WLAN_SER_CMD_PERFORM_PRE_AUTH,
+	WLAN_SER_CMD_WM_STATUS_CHANGE,
+	WLAN_SER_CMD_SET_KEY,
+	WLAN_SER_CMD_NDP_INIT_REQ,
+	WLAN_SER_CMD_NDP_RESP_REQ,
+	WLAN_SER_CMD_NDP_DATA_END_INIT_REQ,
+	WLAN_SER_CMD_ADDTS,
+	WLAN_SER_CMD_DELTS,
+	WLAN_SER_CMD_TDLS_SEND_MGMT,
+	WLAN_SER_CMD_TDLS_ADD_PEER,
+	WLAN_SER_CMD_TDLS_DEL_PEER,
+	WLAN_SER_CMD_TDLS_LINK_EST,
+	WLAN_SER_CMD_SET_HW_MODE,
+	WLAN_SER_CMD_NSS_UPDATE,
+	WLAN_SER_CMD_SET_DUAL_MAC_CONFIG,
+	WLAN_SER_CMD_SET_ANTENNA_MODE,
+	WLAN_SER_CMD_ENTER_BMPS,
+	WLAN_SER_CMD_EXIT_BMPS,
+	WLAN_SER_CMD_ENTER_UAPSD,
+	WLAN_SER_CMD_EXIT_UAPSD,
+	WLAN_SER_CMD_EXIT_WOWL,
+	WLAN_SER_CMD_DEL_STA_SESSION,
+	WLAN_SER_CMD_VDEV_START_BSS,
+	WLAN_SER_CMD_VDEV_STOP_BSS,
+	WLAN_SER_CMD_VDEV_CONNECT,
+	WLAN_SER_CMD_VDEV_DISCONNECT,
+	WLAN_SER_CMD_VDEV_RESTART,
+	WLAN_SER_CMD_MAX
+};
+
+/**
+ * enum wlan_serialization_cancel_type - Type of commands to be cancelled
+ * @WLAN_SER_CANCEL_SINGLE_SCAN: Cancel a single scan with a given ID
+ * @WLAN_SER_CANCEL_PDEV_SCANS: Cancel all the scans on a given pdev
+ * @WLAN_SER_CANCEL_VDEV_SCANS: Cancel all the scans on given vdev
+ * @WLAN_SER_CANCEL_NON_SCAN_CMD: Cancel the given non scan command
+ */
+enum wlan_serialization_cancel_type {
+	WLAN_SER_CANCEL_SINGLE_SCAN,
+	WLAN_SER_CANCEL_PDEV_SCANS,
+	WLAN_SER_CANCEL_VDEV_SCANS,
+	WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD,
+	WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD,
+	WLAN_SER_CANCEL_NON_SCAN_CMD,
+	WLAN_SER_CANCEL_MAX,
+};
+
+/**
+ * enum wlan_serialization_status - Return status of cmd serialization request
+ * @WLAN_SER_CMD_PENDING: Command is put into the pending queue
+ * @WLAN_SER_CMD_ACTIVE: Command is activated and put in active queue
+ * @WLAN_SER_CMD_DENIED_RULES_FAILED: Command denied as the rules fail
+ * @WLAN_SER_CMD_DENIED_LIST_FULL: Command denied as the pending list is full
+ * @WLAN_SER_CMD_DENIED_UNSPECIFIED: Command denied due to unknown reason
+ */
+enum wlan_serialization_status {
+	WLAN_SER_CMD_PENDING,
+	WLAN_SER_CMD_ACTIVE,
+	WLAN_SER_CMD_DENIED_RULES_FAILED,
+	WLAN_SER_CMD_DENIED_LIST_FULL,
+	WLAN_SER_CMD_DENIED_UNSPECIFIED,
+};
+
+/**
+ * enum wlan_serialization_cmd_status - Return status for a cancel request
+ * @WLAN_SER_CMD_IN_PENDING_LIST: Command cancelled from pending list
+ * @WLAN_SER_CMD_IN_ACTIVE_LIST: Command cancelled from active list
+ * @WLAN_SER_CMDS_IN_ALL_LISTS: Command cancelled from all lists
+ * @WLAN_SER_CMD_NOT_FOUND: Specified command to be cancelled
+ *                                    not found in the lists
+ */
+enum wlan_serialization_cmd_status {
+	WLAN_SER_CMD_IN_PENDING_LIST,
+	WLAN_SER_CMD_IN_ACTIVE_LIST,
+	WLAN_SER_CMDS_IN_ALL_LISTS,
+	WLAN_SER_CMD_MARKED_FOR_ACTIVATION,
+	WLAN_SER_CMD_NOT_FOUND,
+};
+
+/**
+ * struct wlan_serialization_command - Command to be serialized
+ * @wlan_serialization_cmd_type: Type of command
+ * @cmd_id: Command Identifier
+ * @cmd_cb: Command callback
+ * @source: component ID of the source of the command
+ * @is_high_priority: Normal/High Priority at which the cmd has to be queued
+ * @cmd_timeout_cb: Command timeout callback
+ * @cmd_timeout_duration: Timeout duration in milliseconds
+ * @vdev: VDEV object associated to the command
+ * @umac_cmd: Actual command that needs to be sent to WMI/firmware
+ *
+ * Note: Unnamed union has been used in this structure, so that in future if
+ * somebody wants to add pdev or psoc structure then that person can add without
+ * modifying existing code.
+ */
+struct wlan_serialization_command {
+	enum wlan_serialization_cmd_type cmd_type;
+	uint32_t cmd_id;
+	wlan_serialization_cmd_callback cmd_cb;
+	enum wlan_umac_comp_id source;
+	bool is_high_priority;
+	bool is_blocking;
+	uint16_t cmd_timeout_duration;
+	union {
+		struct wlan_objmgr_vdev *vdev;
+	};
+	void *umac_cmd;
+};
+
+/**
+ * struct wlan_serialization_queued_cmd_info  - cmd that has to be cancelled
+ * @requestor: component ID of the source requesting this action
+ * @cmd_type: Command type
+ * @cmd_id: Command ID
+ * @req_type: Commands that need to be cancelled
+ * @vdev: VDEV object associated to the command
+ * @queue_type: Queues from which the command to be cancelled
+ */
+struct wlan_serialization_queued_cmd_info {
+	enum wlan_umac_comp_id requestor;
+	enum wlan_serialization_cmd_type cmd_type;
+	uint32_t cmd_id;
+	enum wlan_serialization_cancel_type req_type;
+	union {
+		struct wlan_objmgr_vdev *vdev;
+	};
+	uint8_t queue_type;
+};
+
+/**
+ * wlan_serialization_cancel_request() - Request to cancel a command
+ * @req: Request information
+ *
+ * This API is used by external components to cancel a command
+ * that is either in the pending or active queue. Based on the
+ * req_type, it is decided whether to use pdev or vdev
+ * object. For all non-scan commands, it will be pdev.
+ *
+ * Return: Status specifying the removal of a command from a certain queue
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_cancel_request(
+		struct wlan_serialization_queued_cmd_info *req);
+
+/**
+ * wlan_serialization_remove_cmd() - Request to release a command
+ * @cmd: Command information
+ *
+ * This API is used to release a command sitting in the active
+ * queue upon successful completion of the command
+ *
+ * Return: None
+ */
+void wlan_serialization_remove_cmd(
+		struct wlan_serialization_queued_cmd_info *cmd);
+
+/**
+ * wlan_serialization_flush_cmd() - Request to flush command
+ * @cmd: Command information
+ *
+ * This API is used to flush a cmd sitting in the queue. It
+ * simply flushes the cmd from the queue and does not call
+ * any callbacks in between. If the request is for active
+ * queue, and if the active queue becomes empty upon flush,
+ * then it will pick the next pending cmd and put in the active
+ * queue before returning.
+ *
+ * Return: None
+ */
+void wlan_serialization_flush_cmd(
+		struct wlan_serialization_queued_cmd_info *cmd);
+/**
+ * wlan_serialization_request() - Request to serialize a command
+ * @cmd: Command information
+ *
+ * Return: Status of the serialization request
+ */
+enum wlan_serialization_status
+wlan_serialization_request(struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_register_comp_info_cb() - Register component's info cb
+ * @psoc: PSOC object information
+ * @comp_id: Component ID
+ * @cmd_type: Command Type
+ * @cb: Callback
+ *
+ * This is called from component during its initialization.It initializes
+ * callback handler for given comp_id/cmd_id in a 2-D array.
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+wlan_serialization_register_comp_info_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_umac_comp_id comp_id,
+		enum wlan_serialization_cmd_type cmd_type,
+		wlan_serialization_comp_info_cb cb);
+
+/**
+ * wlan_serialization_deregister_comp_info_cb() - Deregister component's info
+ *						callback
+ * @psoc: PSOC object information
+ * @comp_id: Component ID
+ * @cmd_type: Command Type
+ *
+ * This routine is called from other component during its de-initialization.
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+wlan_serialization_deregister_comp_info_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_umac_comp_id comp_id,
+		enum wlan_serialization_cmd_type cmd_type);
+
+/**
+ * wlan_serialization_register_apply_rules_cb() - Register component's rules
+ *						callback
+ * @psoc: PSOC object information
+ * @cmd_type: Command Type
+ * @cb: Callback
+ *
+ * This is called from component during its initialization.It initializes
+ * callback handler for given cmd_type in a 1-D array.
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+wlan_serialization_register_apply_rules_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_serialization_cmd_type cmd_type,
+		wlan_serialization_apply_rules_cb apply_rules_cb);
+
+/**
+ * wlan_serialization_deregister_apply_rules_cb() - Deregister component's rules
+ *						callback
+ * @psoc: PSOC object information
+ * @cmd_type: Command Type
+ *
+ * This routine is called from other component during its de-initialization.
+ *
+ * Return: QDF Status
+ */
+QDF_STATUS
+wlan_serialization_deregister_apply_rules_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_serialization_cmd_type cmd_type);
+
+/**
+ * @wlan_serialization_init() - Serialization component initialization routine
+ *
+ * Return - QDF Status
+ */
+QDF_STATUS wlan_serialization_init(void);
+
+/**
+ * @wlan_serialization_deinit() - Serialization component de-init routine
+ *
+ * Return - QDF Status
+ */
+QDF_STATUS wlan_serialization_deinit(void);
+
+/**
+ * @wlan_serialization_psoc_open() - Serialization component open routine
+ *
+ * Return - QDF Status
+ */
+QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * @wlan_serialization_psoc_close() - Serialization component close routine
+ *
+ * Return - QDF Status
+ */
+QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_serialization_vdev_scan_status() - Return the status of the vdev scan
+ * @vdev: VDEV Object
+ *
+ * Return: Status of the scans for the corresponding vdev
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_serialization_pdev_scan_status() - Return the status of the pdev scan
+ * @pdev: PDEV Object
+ *
+ * Return: Status of the scans for the corresponding pdev
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev);
+
+/**
+ * wlan_serialization_non_scan_cmd_status() - Return status of pdev non-scan cmd
+ * @pdev: PDEV Object
+ * @cmd_id: ID of the command for which the status has to be checked
+ *
+ * Return: Status of the command for the corresponding pdev
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_non_scan_cmd_status(struct wlan_objmgr_pdev *pdev,
+				       enum wlan_serialization_cmd_type cmd_id);
+
+/**
+ * wlan_serialization_is_cmd_present_in_pending_queue() - Return if the command
+ *				is already present in pending queue
+ * @cmd: pointer to serialization command to check
+ *
+ * This API will check if command is present in pending queue. If present
+ * then return true, so use know that it is duplicated command
+ *
+ * Return: true or false
+ */
+bool wlan_serialization_is_cmd_present_in_pending_queue(
+		struct wlan_objmgr_psoc *psoc,
+		struct wlan_serialization_command *cmd);
+/**
+ * wlan_serialization_is_cmd_present_in_active_queue() - Return if the command
+ *			is already present in active queue
+ * @cmd: pointer to serialization command to check
+ *
+ * This API will check if command is present in active queue. If present
+ * then return true, so use know that it is duplicated command
+ *
+ * Return: true or false
+ */
+bool wlan_serialization_is_cmd_present_in_active_queue(
+		struct wlan_objmgr_psoc *psoc,
+		struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_get_scan_cmd_using_scan_id() - Return command which
+ *					matches vdev_id and scan_id
+ * @psoc: pointer to soc
+ * @vdev_id: vdev id to pull vdev object
+ * @scan_id: scan id to match
+ * @is_scan_cmd_from_active_queue: to indicate active or pending queue
+ *
+ * This API fetches vdev/pdev object based on vdev_id, loops through scan
+ * command queue and find the command which matches scan id as well as vdev
+ * object.
+ *
+ * Return: pointer to serialization command
+ */
+struct wlan_serialization_command*
+wlan_serialization_get_scan_cmd_using_scan_id(
+		struct wlan_objmgr_psoc *psoc,
+		uint8_t vdev_id, uint16_t scan_id,
+		uint8_t is_scan_cmd_from_active_queue);
+/**
+ * wlan_serialization_get_active_cmd() - Return active umac command which
+ *  matches vdev and cmd type
+ * @psoc: pointer to soc
+ * @vdev_id: vdev id to pull vdev object
+ * @cmd_type: cmd type to match
+ *
+ * This API fetches vdev/pdev object based on vdev_id, loops through active
+ * command queue and find the active command which matches cmd_type as well
+ * as vdev object.
+ *
+ * Return: Pointer to umac command. NULL is returned if active command of given
+ *  type is not found.
+ */
+void *wlan_serialization_get_active_cmd(
+		struct wlan_objmgr_psoc *psoc,
+		uint8_t vdev_id,
+		enum wlan_serialization_cmd_type cmd_type);
+#endif
 #endif

+ 571 - 0
umac/cmn_services/serialization/src/wlan_serialization_api.c

@@ -22,6 +22,7 @@
  * component.
  */
 
+#ifdef CONFIG_SERIALIZATION_V1
 /* Include files */
 #include "wlan_objmgr_psoc_obj.h"
 #include "wlan_objmgr_pdev_obj.h"
@@ -435,3 +436,573 @@ release_vdev_ref:
 
 	return umac_cmd;
 }
+#else /* New serialization code*/
+/* Include files */
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_vdev_obj.h>
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_queue_i.h"
+#include "wlan_serialization_scan_i.h"
+#include "wlan_serialization_internal_i.h"
+
+bool wlan_serialization_is_cmd_present_in_pending_queue(
+		struct wlan_objmgr_psoc *psoc,
+		struct wlan_serialization_command *cmd)
+{
+	bool status = false;
+
+	if (!cmd) {
+		ser_err("invalid cmd");
+		goto error;
+	}
+
+	status = wlan_serialization_is_cmd_present_queue(cmd, false);
+
+error:
+	return status;
+}
+
+bool wlan_serialization_is_cmd_present_in_active_queue(
+		struct wlan_objmgr_psoc *psoc,
+		struct wlan_serialization_command *cmd)
+{
+	bool status;
+
+	if (!cmd) {
+		ser_err("invalid cmd");
+		status = false;
+		goto error;
+	}
+
+	status = wlan_serialization_is_cmd_present_queue(cmd, true);
+
+	ser_debug("Cmd type:%d id:%d present: %d",
+		  cmd->cmd_type, cmd->cmd_id, status);
+
+error:
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_register_apply_rules_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_serialization_cmd_type cmd_type,
+		wlan_serialization_apply_rules_cb cb)
+{
+	struct wlan_ser_psoc_obj *ser_soc_obj;
+	QDF_STATUS status;
+
+	status = wlan_serialization_validate_cmdtype(cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("invalid cmd_type %d", cmd_type);
+		goto error;
+	}
+
+	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+
+	ser_soc_obj->apply_rules_cb[cmd_type] = cb;
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_deregister_apply_rules_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_serialization_cmd_type cmd_type)
+{
+	struct wlan_ser_psoc_obj *ser_soc_obj;
+	QDF_STATUS status;
+
+	status = wlan_serialization_validate_cmdtype(cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("invalid cmd_type %d", cmd_type);
+		goto error;
+	}
+	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+	ser_soc_obj->apply_rules_cb[cmd_type] = NULL;
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_register_comp_info_cb(
+		struct wlan_objmgr_psoc *psoc,
+		enum wlan_umac_comp_id comp_id,
+		enum wlan_serialization_cmd_type cmd_type,
+		wlan_serialization_comp_info_cb cb)
+{
+	struct wlan_ser_psoc_obj *ser_soc_obj;
+	QDF_STATUS status;
+
+	status = wlan_serialization_validate_cmd(comp_id, cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("invalid comp_id %d or cmd_type %d",
+			comp_id, cmd_type);
+		goto error;
+	}
+	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+	ser_soc_obj->comp_info_cb[cmd_type][comp_id] = cb;
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_deregister_comp_info_cb(struct wlan_objmgr_psoc *psoc,
+					   enum wlan_umac_comp_id comp_id,
+		enum wlan_serialization_cmd_type cmd_type)
+{
+	struct wlan_ser_psoc_obj *ser_soc_obj;
+	QDF_STATUS status;
+
+	status = wlan_serialization_validate_cmd(comp_id, cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("invalid comp_id %d or cmd_type %d",
+			comp_id, cmd_type);
+		goto error;
+	}
+	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+	ser_soc_obj->comp_info_cb[cmd_type][comp_id] = NULL;
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	return status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_non_scan_cmd_status(
+		struct wlan_objmgr_pdev *pdev,
+		enum wlan_serialization_cmd_type cmd_type)
+{
+	bool cmd_in_active = 0;
+	bool cmd_in_pending = 0;
+	struct wlan_ser_pdev_obj *ser_pdev_obj =
+		wlan_serialization_get_pdev_obj(pdev);
+	enum wlan_serialization_cmd_status cmd_status = WLAN_SER_CMD_NOT_FOUND;
+	struct wlan_serialization_pdev_queue *pdev_q;
+	qdf_list_node_t *node = NULL;
+	qdf_list_t *queue = NULL;
+
+	ser_enter();
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
+
+	/* Look in the pdev non scan active queue */
+	queue = &pdev_q->active_list;
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	node = wlan_serialization_find_cmd(
+			queue, WLAN_SER_MATCH_CMD_TYPE,
+			NULL, cmd_type, NULL, NULL,  WLAN_SER_PDEV_NODE);
+
+	if (node)
+		cmd_in_active = true;
+
+	node = NULL;
+
+	/* Look in the pdev non scan pending queue */
+	queue = &pdev_q->pending_list;
+
+	node = wlan_serialization_find_cmd(
+			queue, WLAN_SER_MATCH_CMD_TYPE,
+			NULL, cmd_type, NULL, NULL,  WLAN_SER_PDEV_NODE);
+
+	if (node)
+		cmd_in_pending = true;
+
+	cmd_status = wlan_serialization_is_cmd_in_active_pending(
+			cmd_in_active, cmd_in_pending);
+
+	wlan_serialization_release_lock(pdev_q);
+
+	ser_exit();
+	return cmd_status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_cancel_request(
+		struct wlan_serialization_queued_cmd_info *req)
+{
+	QDF_STATUS status;
+	enum wlan_serialization_cmd_status cmd_status;
+
+	struct wlan_serialization_command cmd;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+
+	ser_enter();
+
+	if (!req) {
+		ser_err("given request is empty");
+		cmd_status = WLAN_SER_CMD_NOT_FOUND;
+		goto error;
+	}
+
+	status = wlan_serialization_validate_cmd(req->requestor, req->cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("req is not valid");
+		cmd_status = WLAN_SER_CMD_NOT_FOUND;
+		goto error;
+	}
+
+	cmd.cmd_type = req->cmd_type;
+	cmd.cmd_id = req->cmd_id;
+	cmd.source = req->requestor;
+	cmd.vdev = req->vdev;
+
+	pdev = wlan_serialization_get_pdev_from_cmd(&cmd);
+	if (!pdev) {
+		ser_err("pdev is invalid");
+		cmd_status = WLAN_SER_CMD_NOT_FOUND;
+		goto error;
+	}
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+
+	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
+							   cmd.cmd_type);
+
+	if (!pdev_queue) {
+		ser_err("pdev_queue is invalid");
+		cmd_status = WLAN_SER_CMD_NOT_FOUND;
+		goto error;
+	}
+
+	cmd_status = wlan_serialization_find_and_cancel_cmd(
+			&cmd, req->req_type, req->queue_type);
+
+error:
+	ser_exit();
+	return cmd_status;
+}
+
+void wlan_serialization_remove_cmd(
+		struct wlan_serialization_queued_cmd_info *cmd_info)
+{
+	QDF_STATUS status;
+	struct wlan_serialization_command cmd = {0};
+
+	ser_enter();
+
+	if (!cmd_info) {
+		ser_err("given request is empty");
+		QDF_ASSERT(0);
+		return;
+	}
+	status = wlan_serialization_validate_cmd(cmd_info->requestor,
+						 cmd_info->cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("cmd is not valid");
+		QDF_ASSERT(0);
+		goto error;
+	}
+
+	cmd.cmd_type = cmd_info->cmd_type;
+	cmd.cmd_id = cmd_info->cmd_id;
+	cmd.source = cmd_info->requestor;
+	cmd.vdev = cmd_info->vdev;
+
+	if (wlan_serialization_dequeue_cmd(&cmd, true) !=
+			WLAN_SER_CMD_IN_ACTIVE_LIST) {
+		ser_err("Can't dequeue requested cmd_id[%d] type[%d]",
+			cmd.cmd_id, cmd.cmd_type);
+	}
+
+error:
+	ser_exit();
+}
+
+enum wlan_serialization_status
+wlan_serialization_request(struct wlan_serialization_command *cmd)
+{
+	QDF_STATUS status;
+	enum wlan_serialization_status serialization_status;
+	uint8_t comp_id;
+	struct wlan_ser_psoc_obj *ser_soc_obj;
+	union wlan_serialization_rules_info info;
+	struct wlan_objmgr_psoc *psoc;
+
+	ser_enter();
+
+	serialization_status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+
+	if (!cmd) {
+		ser_err("serialization cmd is null");
+		goto error;
+	}
+	status = wlan_serialization_validate_cmd(cmd->source, cmd->cmd_type);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		ser_err("cmd is not valid");
+		goto error;
+	}
+
+	psoc = wlan_serialization_get_psoc_from_cmd(cmd);
+	if (!psoc) {
+		ser_err("psoc _obj is invalid");
+		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	}
+	ser_soc_obj = wlan_serialization_get_psoc_obj(psoc);
+
+	if (!ser_soc_obj) {
+		ser_err("ser_soc_obj is invalid");
+		return WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	}
+
+	/*
+	 * Get Component Info callback by calling
+	 * each registered module
+	 */
+	for (comp_id = 0; comp_id < WLAN_UMAC_COMP_ID_MAX; comp_id++) {
+		if (!ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])
+			continue;
+		ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id](cmd->vdev,
+			&info);
+		if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type])
+			continue;
+		if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type](&info, comp_id))
+			return WLAN_SER_CMD_DENIED_RULES_FAILED;
+	}
+
+	serialization_status = wlan_serialization_enqueue_cmd(cmd);
+
+error:
+	ser_exit();
+	return serialization_status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev)
+{
+	bool cmd_in_active = 0, cmd_in_pending = 0;
+	struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev);
+	struct wlan_ser_pdev_obj *ser_pdev_obj =
+		wlan_serialization_get_pdev_obj(pdev);
+	struct wlan_serialization_pdev_queue *pdev_q;
+	enum wlan_serialization_cmd_status status;
+
+	ser_enter();
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	cmd_in_active =
+	wlan_serialization_is_cmd_in_vdev_list(
+			vdev, &pdev_q->active_list, WLAN_SER_PDEV_NODE);
+
+	cmd_in_pending =
+	wlan_serialization_is_cmd_in_vdev_list(
+			vdev, &pdev_q->pending_list, WLAN_SER_PDEV_NODE);
+
+	status = wlan_serialization_is_cmd_in_active_pending(
+			cmd_in_active, cmd_in_pending);
+
+	wlan_serialization_release_lock(pdev_q);
+	ser_exit();
+
+	return status;
+}
+
+void wlan_serialization_flush_cmd(
+		struct wlan_serialization_queued_cmd_info *cmd)
+{
+	ser_enter();
+
+	if (!cmd) {
+		ser_err("cmd is null, can't flush");
+		goto error;
+	}
+
+error:
+	ser_exit();
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev)
+{
+	bool cmd_in_active, cmd_in_pending;
+	struct wlan_ser_pdev_obj *ser_pdev_obj =
+		wlan_serialization_get_pdev_obj(pdev);
+	struct wlan_serialization_pdev_queue *pdev_q;
+	enum wlan_serialization_cmd_status status;
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	cmd_in_active = !qdf_list_empty(&pdev_q->active_list);
+	cmd_in_pending = !qdf_list_empty(&pdev_q->pending_list);
+
+	status = wlan_serialization_is_cmd_in_active_pending(
+			cmd_in_active, cmd_in_pending);
+
+	wlan_serialization_release_lock(pdev_q);
+
+	return status;
+}
+
+struct wlan_serialization_command*
+wlan_serialization_get_scan_cmd_using_scan_id(
+		struct wlan_objmgr_psoc *psoc,
+		uint8_t vdev_id, uint16_t scan_id,
+		uint8_t is_scan_cmd_from_active_queue)
+{
+	uint32_t qlen;
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_command *cmd = NULL;
+	qdf_list_node_t *nnode = NULL;
+	qdf_list_t *queue;
+	struct wlan_serialization_pdev_queue *pdev_q;
+
+	if (!psoc) {
+		ser_err("invalid psoc");
+		goto error;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_SERIALIZATION_ID);
+	if (!vdev) {
+		ser_err("invalid vdev");
+		goto error;
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		ser_err("invalid pdev");
+		goto release_vdev_ref;
+	}
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+	if (!ser_pdev_obj) {
+		ser_err("invalid ser_pdev_obj");
+		goto release_vdev_ref;
+	}
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	if (is_scan_cmd_from_active_queue)
+		queue = &pdev_q->active_list;
+	else
+		queue = &pdev_q->pending_list;
+
+	qlen = wlan_serialization_list_size(queue);
+
+	while (qlen--) {
+		if (QDF_IS_STATUS_ERROR(wlan_serialization_get_cmd_from_queue(
+					queue, &nnode))) {
+			ser_debug("Node not found");
+			break;
+		}
+		if (wlan_ser_match_cmd_scan_id(nnode, &cmd, scan_id,
+					       vdev)) {
+			break;
+		}
+	}
+
+	wlan_serialization_release_lock(pdev_q);
+
+release_vdev_ref:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
+error:
+	return cmd;
+}
+
+void *wlan_serialization_get_active_cmd(
+		struct wlan_objmgr_psoc *psoc,
+		uint8_t vdev_id,
+		enum wlan_serialization_cmd_type cmd_type)
+{
+	struct wlan_objmgr_vdev *vdev;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	void *umac_cmd = NULL;
+	qdf_list_node_t *node = NULL;
+	qdf_list_t *queue;
+	struct wlan_serialization_pdev_queue *pdev_q;
+
+	ser_enter();
+
+	if (!psoc) {
+		ser_err("invalid psoc");
+		goto error;
+	}
+	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id,
+						    WLAN_SERIALIZATION_ID);
+	if (!vdev) {
+		ser_err("invalid vdev");
+		goto error;
+	}
+
+	pdev = wlan_vdev_get_pdev(vdev);
+	if (!pdev) {
+		ser_err("invalid pdev");
+		goto release_vdev_ref;
+	}
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+	if (!ser_pdev_obj) {
+		ser_err("invalid ser_pdev_obj");
+		goto release_vdev_ref;
+	}
+
+	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	queue = &pdev_q->active_list;
+
+	node = wlan_serialization_find_cmd(
+			queue, WLAN_SER_MATCH_CMD_TYPE_VDEV,
+			NULL, cmd_type, NULL, vdev,  WLAN_SER_PDEV_NODE);
+
+	if (node) {
+		cmd_list = qdf_container_of(
+				node,
+				struct wlan_serialization_command_list,
+				pdev_node);
+
+		umac_cmd = cmd_list->cmd.umac_cmd;
+	}
+
+	wlan_serialization_release_lock(pdev_q);
+
+release_vdev_ref:
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
+error:
+	ser_exit();
+	return umac_cmd;
+}
+#endif

+ 2 - 1
umac/cmn_services/serialization/src/wlan_serialization_dequeue.c

@@ -20,6 +20,7 @@
  * This file defines the routines which are pertinent
  * to the dequeue of commands.
  */
+#ifdef CONFIG_SERIALIZATION_V1
 #include <wlan_serialization_api.h>
 #include "wlan_serialization_main_i.h"
 #include "wlan_serialization_utils_i.h"
@@ -657,4 +658,4 @@ QDF_STATUS wlan_serialization_find_and_remove_cmd(
 
 	return QDF_STATUS_SUCCESS;
 }
-
+#endif

+ 2 - 0
umac/cmn_services/serialization/src/wlan_serialization_enqueue.c

@@ -20,6 +20,7 @@
  * This file defines the routines which are pertinent
  * to the queuing of commands.
  */
+#ifdef CONFIG_SERIALIZATION_V1
 #include <wlan_serialization_api.h>
 #include "wlan_serialization_main_i.h"
 #include "wlan_serialization_utils_i.h"
@@ -271,3 +272,4 @@ wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd,
 	return wlan_serialization_add_cmd_to_given_queue(queue, cmd, psoc,
 			ser_pdev_obj, is_cmd_for_active_queue, pcmd_list);
 }
+#endif

+ 902 - 0
umac/cmn_services/serialization/src/wlan_serialization_internal.c

@@ -0,0 +1,902 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_internal.c
+ * This file defines the functions which are called
+ * from serialization public API's and are internal
+ * to serialization.
+ */
+
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <qdf_list.h>
+#include <qdf_status.h>
+#include <wlan_utility.h>
+#include "wlan_serialization_api.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_non_scan_i.h"
+#include "wlan_serialization_scan_i.h"
+#include "wlan_serialization_internal_i.h"
+
+bool wlan_serialization_is_cmd_present_queue(
+			struct wlan_serialization_command *cmd,
+			uint8_t is_active_queue)
+{
+	qdf_list_t *queue;
+	bool status = false;
+	enum wlan_serialization_node node_type;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_ser_vdev_obj *ser_vdev_obj;
+	enum wlan_serialization_cmd_type cmd_type;
+
+	if (!cmd) {
+		ser_err("invalid cmd");
+		goto error;
+	}
+
+	cmd_type = cmd->cmd_type;
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(
+			wlan_serialization_get_pdev_from_cmd(cmd));
+
+	if (!ser_pdev_obj) {
+		ser_err("invalid ser vdev obj");
+		goto error;
+	}
+
+	ser_vdev_obj = wlan_serialization_get_vdev_obj(
+			wlan_serialization_get_vdev_from_cmd(cmd));
+	if (!ser_vdev_obj) {
+		ser_err("invalid ser pdev obj");
+		goto error;
+	}
+
+	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
+		queue = wlan_serialization_get_list_from_pdev_queue(
+				ser_pdev_obj, cmd_type, is_active_queue);
+		node_type = WLAN_SER_PDEV_NODE;
+	} else {
+		queue = wlan_serialization_get_list_from_vdev_queue(
+				ser_vdev_obj, cmd_type, is_active_queue);
+		node_type = WLAN_SER_VDEV_NODE;
+	}
+
+	status = wlan_serialization_is_cmd_present_in_given_queue(queue, cmd,
+								  node_type);
+
+error:
+	return status;
+}
+
+enum wlan_serialization_status
+wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd)
+{
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	struct wlan_serialization_command_list *cmd_list;
+	qdf_list_node_t *nnode;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	bool active_queue;
+
+	/* Enqueue process
+	 * 1) peek through command structure and see what is the command type
+	 * 2) two main types of commands to process
+	 *    a) SCAN
+	 *    b) NON-SCAN
+	 * 3) for each command there are separate command queues per pdev
+	 * 4) pull pdev from vdev structure and get the command queue associated
+	 *    with that pdev and try to enqueue on those queue
+	 * 5) Thumb rule:
+	 *    a) There could be only 1 active non-scan command at a
+	 *       time including all total non-scan commands of all pdevs.
+	 *
+	 *       example: pdev1 has 1 non-scan active command and
+	 *       pdev2 got 1 non-scan command then that command should go to
+	 *       pdev2's pending queue
+	 *
+	 *    b) There could be only N number of scan commands at a time
+	 *       including all total scan commands of all pdevs
+	 *
+	 *       example: Let's say N=8,
+	 *       pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3
+	 *       scan commands, if we get scan request on vdev2 then it will go
+	 *       to pending queue of vdev2 as we reached max allowed scan active
+	 *       command.
+	 */
+
+	ser_enter();
+
+	if (!cmd) {
+		ser_err("NULL command");
+		goto error;
+	}
+
+	if (!cmd->cmd_cb) {
+		ser_err("no cmd_cb for cmd type:%d, id: %d",
+			cmd->cmd_type,
+			cmd->cmd_id);
+		goto error;
+	}
+
+	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
+	if (!pdev) {
+		ser_err("pdev is invalid");
+		goto error;
+	}
+
+	ser_pdev_obj =
+		wlan_objmgr_pdev_get_comp_private_obj(
+				pdev,
+				WLAN_UMAC_COMP_SERIALIZATION);
+	if (!ser_pdev_obj) {
+		ser_err("Invalid ser_pdev_obj");
+		goto error;
+	}
+
+	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
+							   cmd->cmd_type);
+	if (!pdev_queue) {
+		ser_err("pdev_queue is invalid");
+		goto error;
+	}
+
+	ser_debug("enqueue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
+		  cmd->cmd_type,
+		  cmd->cmd_id,
+		  cmd->is_high_priority,
+		  cmd->is_blocking);
+
+	wlan_serialization_acquire_lock(pdev_queue);
+
+	active_queue = wlan_serialization_is_active_cmd_allowed(cmd);
+
+	if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) {
+		wlan_serialization_release_lock(pdev_queue);
+		ser_err("duplicate command, can't enqueue");
+		goto error;
+	}
+
+	if (wlan_serialization_remove_front(
+				&pdev_queue->cmd_pool_list,
+				&nnode) != QDF_STATUS_SUCCESS) {
+		wlan_serialization_release_lock(pdev_queue);
+		ser_err("Failed to get cmd buffer from global pool");
+		goto error;
+	}
+
+	ser_debug("Global pool node: %pK", nnode);
+
+	cmd_list =
+		qdf_container_of(nnode,
+				 struct wlan_serialization_command_list,
+				 pdev_node);
+
+	qdf_mem_copy(&cmd_list->cmd, cmd,
+		     sizeof(struct wlan_serialization_command));
+
+	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN) {
+		status = wlan_ser_add_scan_cmd(ser_pdev_obj,
+					       cmd_list,
+					       active_queue);
+	} else {
+		status = wlan_ser_add_non_scan_cmd(ser_pdev_obj,
+						   cmd_list,
+						   active_queue);
+	}
+
+	if (status != WLAN_SER_CMD_PENDING && status != WLAN_SER_CMD_ACTIVE) {
+		ser_err("Failed to add cmd to active/pending queue");
+		qdf_mem_zero(&cmd_list->cmd,
+			     sizeof(struct wlan_serialization_command));
+		wlan_serialization_insert_back(
+			&pdev_queue->cmd_pool_list,
+			&cmd_list->pdev_node);
+	}
+
+	if (WLAN_SER_CMD_ACTIVE == status) {
+		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
+				   &cmd_list->cmd_in_use);
+	}
+
+	wlan_serialization_release_lock(pdev_queue);
+
+	if (WLAN_SER_CMD_ACTIVE == status)
+		wlan_serialization_activate_cmd(cmd_list,
+						ser_pdev_obj);
+
+error:
+	ser_exit();
+
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_activate_multiple_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj)
+{
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	qdf_list_t *active_queue;
+	QDF_STATUS peek_status = QDF_STATUS_E_FAILURE;
+	struct wlan_serialization_command_list *active_cmd_list;
+	uint32_t qsize;
+	uint32_t vdev_id;
+	qdf_list_node_t *nnode = NULL;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
+	active_queue = &pdev_queue->active_list;
+
+	qsize =  wlan_serialization_list_size(active_queue);
+	while (qsize--) {
+		peek_status = wlan_serialization_get_cmd_from_queue(
+				active_queue, &nnode);
+
+		if (peek_status != QDF_STATUS_SUCCESS) {
+			ser_err("can't peek cmd");
+			break;
+		}
+
+		active_cmd_list = qdf_container_of(
+				nnode, struct wlan_serialization_command_list,
+				pdev_node);
+
+		if (!qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
+					 &active_cmd_list->cmd_in_use)) {
+			continue;
+		}
+
+		/*
+		 * Command is already pushed to active queue.
+		 * Now start the timer.
+		 */
+		psoc = wlan_vdev_get_psoc(active_cmd_list->cmd.vdev);
+		wlan_serialization_find_and_start_timer(psoc,
+							&active_cmd_list->cmd);
+
+		ser_debug("cmd cb: type[%d] id[%d] : reason: %s",
+			  active_cmd_list->cmd.cmd_type,
+			  active_cmd_list->cmd.cmd_id,
+			  "WLAN_SER_CB_ACTIVATE_CMD");
+
+		status = active_cmd_list->cmd.cmd_cb(&active_cmd_list->cmd,
+					    WLAN_SER_CB_ACTIVATE_CMD);
+
+		qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION,
+				     &active_cmd_list->cmd_in_use);
+
+		qdf_atomic_set_bit(CMD_IS_ACTIVE,
+				   &active_cmd_list->cmd_in_use);
+
+		vdev_id = wlan_vdev_get_id(active_cmd_list->cmd.vdev);
+		pdev_queue->vdev_active_cmd_bitmap |= (1 << vdev_id);
+
+		if (active_cmd_list->cmd.is_blocking)
+			pdev_queue->blocking_cmd_active = 1;
+
+		if (QDF_IS_STATUS_ERROR(status))
+			wlan_serialization_dequeue_cmd(&active_cmd_list->cmd,
+						       true);
+	}
+	return status;
+}
+
+QDF_STATUS wlan_serialization_activate_cmd(
+			struct wlan_serialization_command_list *cmd_list,
+			struct wlan_ser_pdev_obj *ser_pdev_obj)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	psoc = wlan_vdev_get_psoc(cmd_list->cmd.vdev);
+	if (!psoc) {
+		ser_err("invalid psoc");
+		goto error;
+	}
+
+	/*
+	 * command is already pushed to active queue above
+	 * now start the timer and notify requestor
+	 */
+	wlan_serialization_find_and_start_timer(psoc, &cmd_list->cmd);
+	/*
+	 * Remember that serialization module may send
+	 * this callback in same context through which it
+	 * received the serialization request. Due to which
+	 * it is caller's responsibility to ensure acquiring
+	 * and releasing its own lock appropriately.
+	 */
+
+	ser_debug("cmd cb: type[%d] id[%d] : reason: %s",
+		  cmd_list->cmd.cmd_type,
+		  cmd_list->cmd.cmd_id,
+		  "WLAN_SER_CB_ACTIVATE_CMD");
+
+	status = cmd_list->cmd.cmd_cb(&cmd_list->cmd,
+				WLAN_SER_CB_ACTIVATE_CMD);
+
+	qdf_atomic_clear_bit(CMD_MARKED_FOR_ACTIVATION,
+			     &cmd_list->cmd_in_use);
+	qdf_atomic_set_bit(CMD_IS_ACTIVE,
+			   &cmd_list->cmd_in_use);
+
+	if (QDF_IS_STATUS_ERROR(status))
+		wlan_serialization_dequeue_cmd(&cmd_list->cmd, true);
+
+error:
+	return status;
+}
+
+bool
+wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
+{
+	struct wlan_objmgr_pdev *pdev;
+	bool active_cmd_allowed = 0;
+
+	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
+	if (!pdev) {
+		ser_err("NULL pdev");
+		goto error;
+	}
+
+	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
+		active_cmd_allowed =
+			wlan_serialization_is_active_scan_cmd_allowed(cmd);
+	else
+		active_cmd_allowed =
+			wlan_serialization_is_active_non_scan_cmd_allowed(cmd);
+
+	ser_debug("active cmd_type[%d] cmd_id[%d] allowed: %d",
+		  cmd->cmd_type,
+		  cmd->cmd_id,
+		  active_cmd_allowed);
+
+error:
+	return active_cmd_allowed;
+}
+
+enum wlan_serialization_status
+wlan_serialization_move_pending_to_active(
+		enum wlan_serialization_cmd_type cmd_type,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_objmgr_vdev *vdev,
+		bool blocking_cmd_removed,
+		bool blocking_cmd_waiting)
+{
+	enum wlan_serialization_status status;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+
+	if (cmd_type < WLAN_SER_CMD_NONSCAN) {
+		status =
+		wlan_ser_move_scan_pending_to_active(
+				pcmd_list,
+				ser_pdev_obj);
+	} else {
+		pdev_queue =
+			&ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
+
+		if (!blocking_cmd_removed && !blocking_cmd_waiting)
+			status =
+			wlan_ser_move_non_scan_pending_to_active(
+				pcmd_list,
+				ser_pdev_obj,
+				vdev);
+		else
+			status =
+			wlan_ser_move_multiple_non_scan_pending_to_active(
+				ser_pdev_obj);
+	}
+
+	return status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
+			       uint8_t active_cmd)
+{
+	enum wlan_serialization_cmd_status status =
+		WLAN_SER_CMD_NOT_FOUND;
+	enum wlan_serialization_status ser_status =
+		WLAN_SER_CMD_DENIED_UNSPECIFIED;
+
+	QDF_STATUS qdf_status;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_objmgr_psoc *psoc;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_command cmd_bkup;
+	struct wlan_serialization_command_list *cmd_list;
+	struct wlan_serialization_command_list *pcmd_list;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	bool blocking_cmd_removed = 0;
+	bool blocking_cmd_waiting = 0;
+
+	ser_enter();
+
+	if (!cmd) {
+		ser_err("NULL command");
+		goto error;
+	}
+
+	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
+	if (!pdev) {
+		ser_err("invalid pdev");
+		goto error;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		ser_err("invalid psoc");
+		goto error;
+	}
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+	if (!ser_pdev_obj) {
+		ser_err("ser_pdev_obj is empty");
+		goto error;
+	}
+
+	pdev_queue = wlan_serialization_get_pdev_queue_obj(
+			ser_pdev_obj, cmd->cmd_type);
+
+	ser_debug("dequeue cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
+		  cmd->cmd_type,
+		  cmd->cmd_id,
+		  cmd->is_high_priority,
+		  cmd->is_blocking);
+
+	wlan_serialization_acquire_lock(pdev_queue);
+
+	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
+		qdf_status = wlan_ser_remove_scan_cmd(
+				ser_pdev_obj, &cmd_list, cmd, active_cmd);
+	else {
+		qdf_status = wlan_ser_remove_non_scan_cmd(
+				ser_pdev_obj, &cmd_list, cmd, active_cmd);
+	}
+
+	if (qdf_status != QDF_STATUS_SUCCESS) {
+		wlan_serialization_release_lock(pdev_queue);
+		status = WLAN_SER_CMD_NOT_FOUND;
+		goto error;
+	}
+
+	if (active_cmd) {
+		wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd);
+
+		if (cmd_list->cmd.cmd_type >= WLAN_SER_CMD_NONSCAN)
+			blocking_cmd_removed = cmd_list->cmd.is_blocking;
+	}
+
+	qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
+		     sizeof(struct wlan_serialization_command));
+	qdf_mem_zero(&cmd_list->cmd,
+		     sizeof(struct wlan_serialization_command));
+	qdf_status = wlan_serialization_insert_back(
+			&pdev_queue->cmd_pool_list,
+			&cmd_list->pdev_node);
+
+	/*
+	 * For NON SCAN commands, the following is possible:
+	 *
+	 * If the remove is for non blocking command,
+	 * and there is no blocking command waiting,
+	 * look at vdev pending queue and
+	 * only one command moves from pending
+	 * to active
+	 *
+	 * If the remove is for blocking comamnd,
+	 * look at the pdev queue and
+	 * either single blocking command
+	 * or multiple non blocking commands moves
+	 * from pending to active
+	 */
+
+	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
+
+	if (active_cmd) {
+		ser_status = wlan_serialization_move_pending_to_active(
+			cmd_bkup.cmd_type, &pcmd_list, ser_pdev_obj,
+			cmd_bkup.vdev,
+			blocking_cmd_removed,
+			blocking_cmd_waiting);
+	}
+
+	wlan_serialization_release_lock(pdev_queue);
+
+	/* Call cmd cb for remove request*/
+	if (cmd_bkup.cmd_cb) {
+		/* caller should release the memory */
+		ser_debug("cmd cb: type[%d] id[%d]: reason: %s",
+			  cmd_bkup.cmd_type,
+			  cmd_bkup.cmd_id,
+			  "WLAN_SER_CB_RELEASE_MEM_CMD");
+		cmd_bkup.cmd_cb(&cmd_bkup,
+				     WLAN_SER_CB_RELEASE_MEM_CMD);
+	}
+
+	/*
+	 * If the remove is for non blocking command,
+	 * and there is no blocking command waiting,
+	 * look at vdev pending queue and
+	 * only one command moves from pending
+	 * to active and gets activated
+	 */
+	if (WLAN_SER_CMD_ACTIVE == ser_status && !blocking_cmd_removed &&
+	    !blocking_cmd_waiting) {
+		ser_debug("cmd type[%d] id[%d] moved from pending to active",
+			  pcmd_list->cmd.cmd_type,
+			  pcmd_list->cmd.cmd_id);
+		wlan_serialization_activate_cmd(pcmd_list,
+						ser_pdev_obj);
+	} else if (ser_status == WLAN_SER_CMD_ACTIVE) {
+		/* If the remove is for blocking command
+		 * either one or multiple commands can move
+		 * from pending to active and gets activated
+		 */
+		wlan_serialization_activate_multiple_cmd(ser_pdev_obj);
+	} else {
+		goto exit;
+	}
+
+exit:
+	if (active_cmd)
+		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
+	else
+		status = WLAN_SER_CMD_IN_PENDING_LIST;
+
+error:
+	ser_exit();
+	return status;
+}
+
+void wlan_serialization_generic_timer_cb(void *arg)
+{
+	struct wlan_serialization_timer *timer = arg;
+	struct wlan_serialization_command *cmd = timer->cmd;
+
+	if (!cmd) {
+		ser_err("command not found");
+		QDF_ASSERT(0);
+		return;
+	}
+
+	ser_err("active cmd timeout for cmd_type[%d] vdev[%pK]",
+		cmd->cmd_type, cmd->vdev);
+
+	if (cmd->cmd_cb)
+		cmd->cmd_cb(cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
+
+	/*
+	 * dequeue cmd API will cleanup and destroy the timer. If it fails to
+	 * dequeue command then we have to destroy the timer.
+	 */
+	wlan_serialization_dequeue_cmd(cmd, true);
+}
+
+static QDF_STATUS wlan_serialization_mc_flush_noop(struct scheduler_msg *msg)
+{
+	return QDF_STATUS_SUCCESS;
+}
+
+static void
+wlan_serialization_timer_cb_mc_ctx(void *arg)
+{
+	struct scheduler_msg msg = {0};
+
+	msg.type = SYS_MSG_ID_MC_TIMER;
+	msg.reserved = SYS_MSG_COOKIE;
+	msg.callback = wlan_serialization_generic_timer_cb;
+	msg.bodyptr = arg;
+	msg.bodyval = 0;
+	msg.flush_callback = wlan_serialization_mc_flush_noop;
+
+	if (scheduler_post_msg(QDF_MODULE_ID_SYS, &msg) == QDF_STATUS_SUCCESS)
+		return;
+
+	ser_err("Could not enqueue timer to timer queue");
+}
+
+#ifdef CONFIG_MCL
+static void wlan_serialization_timer_handler(void *arg)
+{
+	ser_enter();
+
+	wlan_serialization_timer_cb_mc_ctx(arg);
+
+	ser_exit();
+}
+#else
+static void wlan_serialization_timer_handler(void *arg)
+{
+	struct wlan_serialization_timer *timer = arg;
+	struct wlan_serialization_command *cmd = timer->cmd;
+
+	if (!cmd) {
+		ser_err("command not found");
+		QDF_ASSERT(0);
+		return;
+	}
+
+	if (cmd->cmd_type < WLAN_SER_CMD_NONSCAN)
+		wlan_serialization_timer_cb_mc_ctx(arg);
+	else
+		wlan_serialization_generic_timer_cb(arg);
+}
+#endif
+
+QDF_STATUS
+wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
+				       struct wlan_serialization_command *cmd)
+{
+	struct wlan_ser_psoc_obj *psoc_ser_obj;
+	struct wlan_serialization_timer *ser_timer;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	int i = 0;
+	uint32_t phy_version;
+
+	if (!psoc || !cmd) {
+		ser_err("invalid param");
+		goto error;
+	}
+
+	if (cmd->cmd_timeout_duration == 0) {
+		phy_version = wlan_psoc_get_nif_phy_version(psoc);
+		if (wlan_is_emulation_platform(phy_version)) {
+			ser_err("[SCAN-EMULATION]: Not performing timer funcs");
+			status = QDF_STATUS_SUCCESS;
+		goto exit;
+		}
+	}
+
+	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
+	/*
+	 * Here cmd_id and cmd_type are used to locate the timer being
+	 * associated with command. For scan command, cmd_id is expected to
+	 * be unique and For non-scan command, there should be only one active
+	 * command per pdev
+	 */
+	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
+		ser_timer = &psoc_ser_obj->timers[i];
+		if (!(ser_timer->cmd) ||
+		    (ser_timer->cmd->cmd_id != cmd->cmd_id) ||
+		    (ser_timer->cmd->cmd_type != cmd->cmd_type) ||
+		    (ser_timer->cmd->vdev != cmd->vdev))
+			continue;
+		status = wlan_serialization_stop_timer(ser_timer);
+		ser_debug("\n Stopping timer for cmd type:%d, id: %d",
+			  cmd->cmd_type, cmd->cmd_id);
+		break;
+	}
+
+	if (QDF_STATUS_SUCCESS != status)
+		ser_err("Can't find timer for cmd_type[%d]", cmd->cmd_type);
+
+error:
+exit:
+
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
+					struct wlan_serialization_command *cmd)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	struct wlan_ser_psoc_obj *psoc_ser_obj;
+	struct wlan_serialization_timer *ser_timer;
+	int i = 0;
+	uint32_t nif_phy_ver;
+
+	if (!psoc || !cmd) {
+		ser_err("invalid param");
+		goto error;
+	}
+
+	nif_phy_ver = wlan_psoc_get_nif_phy_version(psoc);
+	if ((cmd->cmd_timeout_duration == 0) &&
+	    (wlan_is_emulation_platform(nif_phy_ver))) {
+		ser_err("[SCAN-EMULATION]: Not performing timer functions\n");
+		status = QDF_STATUS_SUCCESS;
+		goto exit;
+	}
+
+	psoc_ser_obj = wlan_serialization_get_psoc_obj(psoc);
+
+	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
+		/* Keep trying timer */
+		ser_timer = &psoc_ser_obj->timers[i];
+		if (ser_timer->cmd)
+			continue;
+
+		/* Remember timer is pointing to command */
+		ser_timer->cmd = cmd;
+		qdf_timer_init(NULL,
+			       &ser_timer->timer,
+			       wlan_serialization_timer_handler,
+			       ser_timer,
+			       QDF_TIMER_TYPE_SW);
+			       qdf_timer_mod(&ser_timer->timer,
+					     cmd->cmd_timeout_duration);
+
+		ser_debug("starting timer for cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
+			  cmd->cmd_type,
+			  cmd->cmd_id,
+			  cmd->is_high_priority,
+			  cmd->is_blocking);
+
+		status = QDF_STATUS_SUCCESS;
+		break;
+	}
+
+error:
+exit:
+
+	return status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_cmd_cancel_handler(
+		struct wlan_ser_pdev_obj *ser_obj,
+		struct wlan_serialization_command *cmd,
+		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
+		enum wlan_serialization_cmd_type cmd_type, uint8_t queue_type)
+{
+	enum wlan_serialization_cmd_status active_status =
+		WLAN_SER_CMD_NOT_FOUND;
+	enum wlan_serialization_cmd_status pending_status =
+		WLAN_SER_CMD_NOT_FOUND;
+	enum wlan_serialization_cmd_status status =
+		WLAN_SER_CMD_NOT_FOUND;
+
+	ser_enter();
+
+	if (!ser_obj) {
+		ser_err("invalid serial object");
+		goto error;
+	}
+
+	if (queue_type & WLAN_SERIALIZATION_ACTIVE_QUEUE) {
+		if (cmd_type < WLAN_SER_CMD_NONSCAN)
+			active_status = wlan_ser_cancel_scan_cmd(
+					ser_obj, pdev, vdev, cmd,
+					cmd_type, true);
+		else
+			active_status = wlan_ser_cancel_non_scan_cmd(
+					ser_obj, pdev, vdev, cmd,
+					cmd_type, true);
+	}
+
+	if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) {
+		if (cmd_type < WLAN_SER_CMD_NONSCAN)
+			pending_status = wlan_ser_cancel_scan_cmd(
+					ser_obj, pdev, vdev, cmd,
+					cmd_type, false);
+		else
+			pending_status = wlan_ser_cancel_non_scan_cmd(
+					ser_obj, pdev, vdev, cmd,
+					cmd_type, false);
+	}
+
+	if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST &&
+	    pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
+		status = WLAN_SER_CMDS_IN_ALL_LISTS;
+	else if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST)
+		status = active_status;
+	else if (pending_status == WLAN_SER_CMD_IN_PENDING_LIST)
+		status = pending_status;
+
+error:
+	ser_exit();
+	return status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_find_and_cancel_cmd(
+		struct wlan_serialization_command *cmd,
+		enum wlan_serialization_cancel_type req_type,
+		uint8_t queue_type)
+{
+	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
+	struct wlan_ser_pdev_obj *ser_obj = NULL;
+	struct wlan_objmgr_pdev *pdev;
+
+	ser_enter();
+
+	if (!cmd) {
+		ser_err("Invalid cmd");
+		goto error;
+	}
+
+	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
+	if (!pdev) {
+		ser_err("Invalid pdev");
+		goto error;
+	}
+	ser_obj = wlan_serialization_get_pdev_obj(pdev);
+	if (!ser_obj) {
+		ser_err("Invalid ser_obj");
+		goto error;
+	}
+
+	switch (req_type) {
+	case WLAN_SER_CANCEL_SINGLE_SCAN:
+		/* remove scan cmd which matches the given cmd struct */
+		status =  wlan_serialization_cmd_cancel_handler(ser_obj,
+								cmd,
+								NULL,
+								NULL,
+								cmd->cmd_type,
+								queue_type);
+		break;
+	case WLAN_SER_CANCEL_PDEV_SCANS:
+		/* remove all scan cmds which matches the pdev object */
+		status = wlan_serialization_cmd_cancel_handler(
+				ser_obj,
+				NULL,
+				wlan_vdev_get_pdev(cmd->vdev),
+				NULL,
+				cmd->cmd_type,
+				queue_type);
+		break;
+	case WLAN_SER_CANCEL_VDEV_SCANS:
+		/* remove all scan cmds which matches the vdev object */
+		status = wlan_serialization_cmd_cancel_handler(ser_obj,
+							       NULL, NULL,
+							       cmd->vdev,
+							       cmd->cmd_type,
+							       queue_type);
+		break;
+	case WLAN_SER_CANCEL_NON_SCAN_CMD:
+		/* remove nonscan cmd which matches the given cmd */
+		status = wlan_serialization_cmd_cancel_handler(ser_obj,
+							       cmd,
+							       NULL,
+							       NULL,
+							       cmd->cmd_type,
+							       queue_type);
+		break;
+	case WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD:
+		/* remove all non scan cmds which matches the pdev object */
+		status = wlan_serialization_cmd_cancel_handler(
+				ser_obj,
+				NULL,
+				wlan_vdev_get_pdev(cmd->vdev),
+				NULL,
+				cmd->cmd_type,
+				queue_type);
+		break;
+	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD:
+		/* remove all non scan cmds which matches the vdev object */
+		status = wlan_serialization_cmd_cancel_handler(ser_obj,
+							       NULL, NULL,
+							       cmd->vdev,
+							       cmd->cmd_type,
+							       queue_type);
+		break;
+	default:
+		ser_err("Invalid request");
+	}
+
+error:
+	ser_exit();
+	return status;
+}

+ 211 - 0
umac/cmn_services/serialization/src/wlan_serialization_internal_i.h

@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_internal_i.h
+ * This file defines the prototypes of functions which are called
+ * from serialization public API's and are internal
+ * to serialization.
+ */
+#ifndef __WLAN_SERIALIZATION_PVT_I_H
+#define __WLAN_SERIALIZATION_PVT_I_H
+
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <qdf_list.h>
+#include <qdf_status.h>
+#include "wlan_serialization_api.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_non_scan_i.h"
+
+/**
+ * wlan_serialization_is_cmd_present_queue() - Check if same command
+ *				is already present active or pending queue
+ * @cmd: pointer to command which we need to find
+ * @is_active_queue: flag to find the command in active or pending queue
+ *
+ * This API will check the given command is already present in active or
+ * pending queue based on flag
+ * If present then return true otherwise false
+ *
+ * Return: true or false
+ */
+bool
+wlan_serialization_is_cmd_present_queue(
+					struct wlan_serialization_command *cmd,
+					uint8_t is_active_queue);
+
+/**
+ * wlan_serialization_is_active_cmd_allowed() - Check if the given command
+ *			can be moved to active queue
+ * @cmd: Serialization command information
+ *
+ * Return: true or false
+ */
+bool
+wlan_serialization_is_active_cmd_allowed(
+		struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_enqueue_cmd() - Enqueue the cmd to pending/active Queue
+ * @cmd: Command information
+ *
+ * Return: Status of the serialization request
+ */
+enum wlan_serialization_status
+wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_activate_cmd() - activate cmd in active queue
+ * @cmd_list: Command needs to be activated
+ * @ser_pdev_obj: Serialization private pdev object
+ *
+ * Return: Status of activation of the command
+ */
+QDF_STATUS
+wlan_serialization_activate_cmd(
+		struct wlan_serialization_command_list *cmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj);
+
+/**
+ * wlan_serialization_activate_multiple_cmd() - Activate multiple cmd in
+ *			active queue
+ * @ser_pdev_obj: Serialization private pdev object
+ *
+ * Return: Status of activation of the command
+ */
+QDF_STATUS
+wlan_serialization_activate_multiple_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj);
+
+/**
+ * wlan_serialization_move_pending_to_active() - Move a cmd from pending
+ *			queue to active queue
+ * @cmd_type: Type of command to be moved i.e scan or non scan
+ * @pcmd_list: Pointer to command list containing the command
+ * @ser_pdev_obj: Serialization private pdev object
+ * @vdev: Pointer to vdev object manager
+ * @blocking_cmd_removed: If a blocking cmd is removed from active queue
+ * @blocking_cmd_waiting: If a blocking cmd is waiting in pending queue
+ *
+ * Return: Status of command request
+ */
+enum wlan_serialization_status
+wlan_serialization_move_pending_to_active(
+		enum wlan_serialization_cmd_type cmd_type,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_objmgr_vdev *vdev,
+		bool blocking_cmd_removed,
+		bool blocking_cmd_waiting);
+
+/**
+ * wlan_serialization_dequeue_cmd() - dequeue the cmd to pending/active Queue
+ * @cmd: Command information
+ * @active_cmd: whether command is for active queue
+ *
+ * Return: Status of the serialization request
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
+			       uint8_t active_cmd);
+
+/**
+ * wlan_serialization_generic_timer_cb() - timer callback when timer fire
+ * @arg: argument that timer passes to this callback
+ *
+ * All the timers in serialization module calls this callback when they fire,
+ * and this API in turn calls command specific timeout callback and remove
+ * timed-out command from active queue and move any pending command to active
+ * queue of same cmd_type.
+ *
+ * Return: none
+ */
+void wlan_serialization_generic_timer_cb(void *arg);
+
+/**
+ * wlan_serialization_find_and_start_timer() - to find and start the timer
+ * @psoc: pointer to psoc
+ * @cmd: pointer to actual command
+ *
+ * find the free timer, initialize it, and start it
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
+					struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_find_and_stop_timer() - to find and stop the timer
+ * @psoc: pointer to psoc
+ * @cmd: pointer to actual command
+ *
+ * find the timer associated with command, stop it and destroy it
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
+				       struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_find_and_cancel_cmd() - to find cmd from queue and cancel
+ * @cmd: pointer to serialization command
+ * @req_type: Command cancel request type
+ * @queue_type: Bitmask for member queue type i.e active or pending or both
+ *
+ * This api will find command from active queue and pending queue and
+ * removes the command. If it is in active queue then it will notifies the
+ * requester that it is in active queue and from there it expects requester
+ * to send remove command
+ *
+ * Return: wlan_serialization_cmd_status
+ */
+
+enum wlan_serialization_cmd_status
+wlan_serialization_find_and_cancel_cmd(
+		struct wlan_serialization_command *cmd,
+		enum wlan_serialization_cancel_type req_type,
+		uint8_t queue_type);
+
+/**
+ * wlan_serialization_cmd_cancel_handler() - helper func to cancel cmd
+ * @ser_obj: private pdev ser obj
+ * @cmd: pointer to command
+ * @pdev: pointer to pdev
+ * @vdev: pointer to vdev
+ * @cmd_type: pointer to cmd_type
+ * @queue_type: If active queue or pending queue
+ *
+ * This API will decide from which queue, command needs to be cancelled
+ * and pass that queue and other parameter required to cancel the command
+ * to helper function.
+ *
+ * Return: wlan_serialization_cmd_status
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_cmd_cancel_handler(
+				      struct wlan_ser_pdev_obj *ser_obj,
+				      struct wlan_serialization_command *cmd,
+				      struct wlan_objmgr_pdev *pdev,
+				      struct wlan_objmgr_vdev *vdev,
+				      enum wlan_serialization_cmd_type cmd_type,
+				      uint8_t queue_type);
+#endif

+ 607 - 0
umac/cmn_services/serialization/src/wlan_serialization_main.c

@@ -22,6 +22,7 @@
  * serialization to initialize and de-initialize the
  * component.
  */
+#ifdef CONFIG_SERIALIZATION_V1
 #include "qdf_status.h"
 #include "qdf_list.h"
 #include "wlan_objmgr_cmn.h"
@@ -486,3 +487,609 @@ QDF_STATUS wlan_serialization_deinit(void)
 
 	return ret_status;
 }
+#else /* New serialition code*/
+#include <qdf_status.h>
+#include <qdf_list.h>
+#include <wlan_objmgr_cmn.h>
+#include <wlan_objmgr_global_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_rules_i.h"
+#include "wlan_serialization_utils_i.h"
+
+struct serialization_legacy_callback ser_legacy_cb;
+
+QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	struct wlan_ser_psoc_obj *ser_soc_obj =
+		wlan_serialization_get_psoc_obj(psoc);
+
+	ser_enter();
+
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		goto error;
+	}
+	/* clean up all timers before exiting */
+	status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
+	if (status != QDF_STATUS_SUCCESS)
+		ser_err("ser cleanning up all timer failed");
+
+	qdf_mem_free(ser_soc_obj->timers);
+	ser_soc_obj->timers = NULL;
+	ser_soc_obj->max_active_cmds = 0;
+
+error:
+	ser_exit();
+	return status;
+}
+
+QDF_STATUS wlan_serialization_psoc_open(struct wlan_objmgr_psoc *psoc)
+{
+	uint8_t pdev_count;
+	struct wlan_ser_psoc_obj *ser_soc_obj =
+		wlan_serialization_get_psoc_obj(psoc);
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		goto error;
+	}
+
+	pdev_count = wlan_psoc_get_pdev_count(psoc);
+	ser_soc_obj->max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS +
+					(pdev_count * WLAN_SER_MAX_VDEVS);
+
+	ser_soc_obj->timers =
+		qdf_mem_malloc(sizeof(struct wlan_serialization_timer) *
+				ser_soc_obj->max_active_cmds);
+	if (!ser_soc_obj->timers) {
+		ser_alert("Mem alloc failed for ser timers");
+		status = QDF_STATUS_E_NOMEM;
+		goto error;
+	}
+
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_psoc_create_handler() - PSOC obj create callback
+ * @psoc: PSOC object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization and
+ * when obj manager gets its turn to create the object, it would notify each
+ * component with the corresponding callback registered to inform the
+ * completion of the creation of the respective object.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS wlan_serialization_psoc_create_handler(
+		struct wlan_objmgr_psoc *psoc, void *arg_list)
+{
+	struct wlan_ser_psoc_obj *soc_ser_obj;
+	QDF_STATUS status = QDF_STATUS_E_NOMEM;
+
+	ser_enter();
+
+	soc_ser_obj =
+		qdf_mem_malloc(sizeof(*soc_ser_obj));
+	if (!soc_ser_obj) {
+		ser_alert("Mem alloc failed for ser psoc priv obj");
+		goto error;
+	}
+	wlan_objmgr_psoc_component_obj_attach(psoc,
+					      WLAN_UMAC_COMP_SERIALIZATION,
+					      soc_ser_obj,
+					      QDF_STATUS_SUCCESS);
+	ser_debug("ser psoc obj created");
+
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_destroy_cmd_pool() - Destroy the global cmd pool
+ * @ser_pdev_obj: Serialization private pdev object
+ *
+ * Return: None
+ */
+static void wlan_serialization_destroy_cmd_pool(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	qdf_list_node_t *node = NULL;
+	struct wlan_serialization_command_list *cmd_list;
+
+	ser_enter();
+	while (!qdf_list_empty(&pdev_queue->cmd_pool_list)) {
+		qdf_list_remove_front(&pdev_queue->cmd_pool_list,
+				      &node);
+		cmd_list = (struct wlan_serialization_command_list *)node;
+		ser_debug("Node being freed from global pool %pK",
+			  cmd_list);
+		qdf_mem_free(cmd_list);
+	}
+
+	qdf_list_destroy(&pdev_queue->cmd_pool_list);
+
+	ser_exit();
+}
+
+/**
+ * wlan_serialization_create_cmd_pool() - Create the global cmd pool
+ * @pdev: PDEV Object
+ * @ser_pdev_obj: Serialization private pdev object
+ *
+ * Global command pool of memory is created here.
+ * It is safe to allocate memory individually for each command rather than
+ * requesting for a huge chunk of memory at once.
+ *
+ * The individual command nodes allocated above will keep moving between
+ * the active, pending and global pool lists dynamically, but all the
+ * memory will be freed during driver unload only.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS
+wlan_serialization_create_cmd_pool(
+		struct wlan_serialization_pdev_queue *pdev_queue,
+		uint16_t cmd_pool_size)
+{
+	struct wlan_serialization_command_list *cmd_list_ptr;
+	uint8_t i;
+	QDF_STATUS status = QDF_STATUS_E_NOMEM;
+
+	ser_enter();
+
+	for (i = 0; i < cmd_pool_size; i++) {
+		cmd_list_ptr = qdf_mem_malloc(sizeof(*cmd_list_ptr));
+		if (!cmd_list_ptr) {
+			ser_alert("Mem alloc failed for cmd node");
+			wlan_serialization_destroy_cmd_pool(pdev_queue);
+			goto error;
+		}
+
+		qdf_mem_zero(cmd_list_ptr, sizeof(*cmd_list_ptr));
+		qdf_list_insert_back(
+				     &pdev_queue->cmd_pool_list,
+				     &cmd_list_ptr->pdev_node);
+		cmd_list_ptr->cmd_in_use = 0;
+		ser_debug("Created node at %pK and inserted to pool",
+			  cmd_list_ptr);
+	}
+
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_pdev_create_handler() - PDEV obj create callback
+ * @pdev: PDEV object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization and
+ * when obj manager gets its turn to create the object, it would notify each
+ * component with the corresponding callback registered to inform the
+ * completion of the creation of the respective object.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS wlan_serialization_pdev_create_handler(
+		struct wlan_objmgr_pdev *pdev, void *arg_list)
+{
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	QDF_STATUS status = QDF_STATUS_E_NOMEM;
+	uint8_t index;
+	uint8_t max_active_cmds;
+	uint8_t max_pending_cmds;
+	uint16_t cmd_pool_size;
+
+	ser_enter();
+
+	ser_pdev_obj =
+		qdf_mem_malloc(sizeof(*ser_pdev_obj));
+	if (!ser_pdev_obj) {
+		ser_alert("Mem alloc failed for ser pdev obj");
+		goto error;
+	}
+
+	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
+		pdev_queue = &ser_pdev_obj->pdev_q[index];
+
+		qdf_spinlock_create(&pdev_queue->pdev_queue_lock);
+
+		switch (index) {
+		case SER_PDEV_QUEUE_COMP_SCAN:
+			max_active_cmds = WLAN_SER_MAX_ACTIVE_SCAN_CMDS;
+			max_pending_cmds = WLAN_SER_MAX_PENDING_SCAN_CMDS;
+			cmd_pool_size = max_active_cmds + max_pending_cmds;
+			break;
+
+		case SER_PDEV_QUEUE_COMP_NON_SCAN:
+			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS;
+			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS;
+			cmd_pool_size = max_active_cmds + max_pending_cmds;
+			break;
+		}
+		qdf_list_create(&pdev_queue->active_list,
+				max_active_cmds);
+		qdf_list_create(&pdev_queue->pending_list,
+				max_pending_cmds);
+		qdf_list_create(&pdev_queue->cmd_pool_list,
+				cmd_pool_size);
+
+		status = wlan_serialization_create_cmd_pool(pdev_queue,
+							    cmd_pool_size);
+		if (status != QDF_STATUS_SUCCESS) {
+			ser_err("ser_pdev_obj failed status %d", status);
+			goto error;
+	}
+
+		pdev_queue->vdev_active_cmd_bitmap = 0;
+		pdev_queue->blocking_cmd_active = 0;
+		pdev_queue->blocking_cmd_waiting = 0;
+	}
+
+	status = wlan_objmgr_pdev_component_obj_attach(
+			pdev, WLAN_UMAC_COMP_SERIALIZATION,
+			ser_pdev_obj, QDF_STATUS_SUCCESS);
+
+	if (status != QDF_STATUS_SUCCESS)
+		ser_err("serialization pdev obj attach failed");
+
+error:
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_psoc_destroy_handler() - PSOC obj delete callback
+ * @psoc: PSOC object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization and
+ * when obj manager gets its turn to delete the object, it would notify each
+ * component with the corresponding callback registered to inform the
+ * completion of the deletion of the respective object.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS
+wlan_serialization_psoc_destroy_handler(struct wlan_objmgr_psoc *psoc,
+					void *arg_list)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAULT;
+	struct wlan_ser_psoc_obj *ser_soc_obj =
+		wlan_serialization_get_psoc_obj(psoc);
+
+	ser_enter();
+
+	if (!ser_soc_obj) {
+		ser_err("invalid ser_soc_obj");
+		goto error;
+	}
+	status = wlan_objmgr_psoc_component_obj_detach(
+			psoc, WLAN_UMAC_COMP_SERIALIZATION, ser_soc_obj);
+	if (status != QDF_STATUS_SUCCESS)
+		ser_err("ser psoc private obj detach failed");
+
+	ser_debug("ser psoc obj deleted with status %d", status);
+	qdf_mem_free(ser_soc_obj);
+
+error:
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_pdev_destroy_handler() - PDEV obj delete callback
+ * @pdev: PDEV object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization and
+ * when obj manager gets its turn to delete the object, it would notify each
+ * component with the corresponding callback registered to inform the
+ * completion of the deletion of the respective object.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS wlan_serialization_pdev_destroy_handler(
+		struct wlan_objmgr_pdev *pdev, void *arg_list)
+{
+	QDF_STATUS status;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	struct wlan_ser_pdev_obj *ser_pdev_obj =
+		wlan_serialization_get_pdev_obj(pdev);
+	uint8_t index;
+
+	ser_enter();
+
+	status = wlan_objmgr_pdev_component_obj_detach(
+			pdev, WLAN_UMAC_COMP_SERIALIZATION, ser_pdev_obj);
+
+	for (index = 0; index < SER_PDEV_QUEUE_COMP_MAX; index++) {
+		pdev_queue = &ser_pdev_obj->pdev_q[index];
+
+		wlan_serialization_destroy_pdev_list(pdev_queue);
+		wlan_serialization_destroy_cmd_pool(pdev_queue);
+
+		qdf_spinlock_destroy(&pdev_queue->pdev_queue_lock);
+	}
+
+	qdf_mem_free(ser_pdev_obj);
+
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_vdev_create_handler() - VDEV obj create callback
+ * @vdev: VDEV object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization and
+ * when obj manager gets its turn to create the object, it would notify each
+ * component with the corresponding callback registered to inform the
+ * completion of the creation of the respective object.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS
+wlan_serialization_vdev_create_handler(struct wlan_objmgr_vdev *vdev,
+				       void *arg_list)
+{
+	struct wlan_ser_vdev_obj *ser_vdev_obj;
+	struct wlan_serialization_vdev_queue *vdev_q;
+	QDF_STATUS status = QDF_STATUS_E_NOMEM;
+	uint8_t index;
+	uint8_t max_active_cmds;
+	uint8_t max_pending_cmds;
+
+	ser_enter();
+
+	ser_vdev_obj = qdf_mem_malloc(sizeof(*ser_vdev_obj));
+	if (!ser_vdev_obj) {
+		ser_alert("Mem alloc failed for ser vdev obj");
+		goto error;
+	}
+
+	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
+		vdev_q = &ser_vdev_obj->vdev_q[index];
+
+		switch (index) {
+		case SER_VDEV_QUEUE_COMP_NON_SCAN:
+			max_active_cmds = WLAN_SER_MAX_ACTIVE_CMDS /
+				WLAN_SER_MAX_VDEVS;
+			max_pending_cmds = WLAN_SER_MAX_PENDING_CMDS /
+				WLAN_SER_MAX_VDEVS;
+			break;
+		}
+
+		qdf_list_create(&vdev_q->active_list,
+				max_active_cmds);
+		qdf_list_create(&vdev_q->pending_list,
+				max_pending_cmds);
+	}
+
+	status = wlan_objmgr_vdev_component_obj_attach(
+			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj,
+			QDF_STATUS_SUCCESS);
+
+	if (status != QDF_STATUS_SUCCESS)
+		ser_err("serialization vdev obj attach failed");
+
+error:
+	ser_exit();
+	return status;
+}
+
+/**
+ * wlan_serialization_vdev_destroy_handler() - vdev obj delete callback
+ * @vdev: VDEV object
+ * @arg_list: Variable argument list
+ *
+ * This callback is registered with object manager during initialization and
+ * when obj manager gets its turn to delete the object, it would notify each
+ * component with the corresponding callback registered to inform the
+ * completion of the deletion of the respective object.
+ *
+ * Return: QDF Status
+ */
+static QDF_STATUS wlan_serialization_vdev_destroy_handler(
+		struct wlan_objmgr_vdev *vdev, void *arg_list)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	struct wlan_serialization_vdev_queue *vdev_q;
+	struct wlan_ser_vdev_obj *ser_vdev_obj =
+		wlan_serialization_get_vdev_obj(vdev);
+	uint8_t vdev_id = wlan_vdev_get_id(vdev);
+	uint8_t index;
+
+	ser_enter();
+
+	status = wlan_objmgr_vdev_component_obj_detach(
+			vdev, WLAN_UMAC_COMP_SERIALIZATION, ser_vdev_obj);
+
+	for (index = 0; index < SER_VDEV_QUEUE_COMP_MAX; index++) {
+		vdev_q = &ser_vdev_obj->vdev_q[index];
+		wlan_serialization_destroy_vdev_list(&vdev_q->active_list);
+		wlan_serialization_destroy_vdev_list(&vdev_q->pending_list);
+	}
+
+	qdf_mem_free(ser_vdev_obj);
+	if (!ser_legacy_cb.serialization_purge_cmd_list)
+		goto error;
+
+	ser_debug("for vdev_id[%d] vdev[%pK] flush all cmds",
+		  vdev_id, vdev);
+	ser_legacy_cb.serialization_purge_cmd_list(wlan_vdev_get_psoc(vdev),
+						   vdev, false, false,
+						   false, false, true);
+
+error:
+	ser_exit();
+	return status;
+}
+
+QDF_STATUS wlan_serialization_init(void)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	ser_enter();
+
+	status = wlan_objmgr_register_psoc_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_psoc_create_handler, NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to reg soc ser obj create handler");
+		goto err_psoc_create;
+	}
+
+	status = wlan_objmgr_register_psoc_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_psoc_destroy_handler, NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to reg soc ser obj delete handler");
+		goto err_psoc_delete;
+	}
+
+	status = wlan_objmgr_register_pdev_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_pdev_create_handler, NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to reg pdev ser obj create handler");
+		goto err_pdev_create;
+	}
+
+	status = wlan_objmgr_register_pdev_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_pdev_destroy_handler, NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to reg pdev ser obj delete handler");
+		goto err_pdev_delete;
+	}
+
+	status = wlan_objmgr_register_vdev_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_vdev_create_handler, NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to reg vdev ser obj create handler");
+		goto err_vdev_create;
+	}
+
+	status = wlan_objmgr_register_vdev_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_vdev_destroy_handler, NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to reg vdev ser obj delete handler");
+		goto err_vdev_delete;
+	}
+	ser_debug("serialization handlers registered with obj mgr");
+	/*
+	 * Initialize the structure so all callbacks are registered
+	 * initially as NULL.
+	 */
+	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
+
+	status = QDF_STATUS_SUCCESS;
+	goto exit;
+
+err_vdev_delete:
+	wlan_objmgr_unregister_vdev_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_vdev_create_handler,
+			NULL);
+err_vdev_create:
+	wlan_objmgr_unregister_pdev_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_pdev_destroy_handler,
+			NULL);
+err_pdev_delete:
+	wlan_objmgr_unregister_pdev_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_pdev_create_handler,
+			NULL);
+err_pdev_create:
+	wlan_objmgr_unregister_psoc_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_psoc_destroy_handler,
+			NULL);
+err_psoc_delete:
+	wlan_objmgr_unregister_psoc_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_psoc_create_handler,
+			NULL);
+err_psoc_create:
+exit:
+	ser_exit();
+	return status;
+}
+
+QDF_STATUS wlan_serialization_deinit(void)
+{
+	QDF_STATUS status;
+	QDF_STATUS ret_status = QDF_STATUS_SUCCESS;
+
+	ser_enter();
+
+	status = wlan_objmgr_unregister_psoc_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_psoc_create_handler,
+			NULL);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("unreg fail for psoc ser obj create notf:%d", status);
+		ret_status = QDF_STATUS_E_FAILURE;
+	}
+	status = wlan_objmgr_unregister_psoc_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_psoc_destroy_handler,
+			NULL);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("unreg fail for psoc ser obj destroy notf:%d", status);
+		ret_status = QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_objmgr_unregister_pdev_create_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_pdev_create_handler,
+			NULL);
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("unreg fail for pdev ser obj create notf:%d", status);
+		ret_status = QDF_STATUS_E_FAILURE;
+	}
+
+	status = wlan_objmgr_unregister_pdev_destroy_handler(
+			WLAN_UMAC_COMP_SERIALIZATION,
+			wlan_serialization_pdev_destroy_handler,
+			NULL);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("unreg fail for pdev ser destroy notf:%d", status);
+		ret_status = QDF_STATUS_E_FAILURE;
+	}
+
+	ser_alert("deregistered callbacks with obj mgr successfully");
+	/*
+	 * Initialize the structure so all callbacks are registered
+	 * initially as NULL.
+	 */
+	qdf_mem_zero(&ser_legacy_cb, sizeof(ser_legacy_cb));
+
+	ser_exit();
+	return ret_status;
+}
+#endif

+ 51 - 0
umac/cmn_services/serialization/src/wlan_serialization_main_i.h

@@ -22,6 +22,8 @@
  */
 #ifndef __WLAN_SERIALIZATION_MAIN_I_H
 #define __WLAN_SERIALIZATION_MAIN_I_H
+
+#ifdef CONFIG_SERIALIZATION_V1
 /* Include files */
 #include "wlan_objmgr_cmn.h"
 #include "wlan_objmgr_psoc_obj.h"
@@ -72,5 +74,54 @@ struct serialization_legacy_callback {
 	void (*serialization_purge_cmd_list) (struct wlan_objmgr_psoc *,
 		struct wlan_objmgr_vdev *, bool, bool, bool, bool, bool);
 };
+#else /*New serialization code*/
+/* Include files */
+#include <wlan_objmgr_cmn.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_mc_timer.h>
+
+#define WLAN_SER_MAX_VDEVS 17
+
+#define WLAN_SER_MAX_ACTIVE_CMDS WLAN_SER_MAX_VDEVS
+#define WLAN_SER_MAX_PENDING_CMDS (WLAN_SER_MAX_VDEVS * 4)
 
+#define WLAN_SER_MAX_ACTIVE_SCAN_CMDS 8
+#define WLAN_SER_MAX_PENDING_SCAN_CMDS 24
+
+#define WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS \
+	(WLAN_SER_MAX_ACTIVE_CMDS + \
+	 WLAN_SER_MAX_PENDING_CMDS + \
+	 WLAN_SER_MAX_ACTIVE_SCAN_CMDS + \
+	 WLAN_SER_MAX_PENDING_SCAN_CMDS)
+
+#define ser_alert(params...) \
+	QDF_TRACE_FATAL(QDF_MODULE_ID_SERIALIZATION, params)
+#define ser_err(params...) \
+	QDF_TRACE_ERROR(QDF_MODULE_ID_SERIALIZATION, params)
+#define ser_warn(params...) \
+	QDF_TRACE_WARN(QDF_MODULE_ID_SERIALIZATION, params)
+#define ser_info(params...) \
+	QDF_TRACE_INFO(QDF_MODULE_ID_SERIALIZATION, params)
+#define ser_debug(params...) \
+	QDF_TRACE_DEBUG(QDF_MODULE_ID_SERIALIZATION, params)
+#define ser_enter() \
+	QDF_TRACE_ENTER(QDF_MODULE_ID_SERIALIZATION, "enter")
+#define ser_exit() \
+	QDF_TRACE_EXIT(QDF_MODULE_ID_SERIALIZATION, "exit")
+
+/**
+ * struct serialization_legacy_callback - to handle legacy serialization cb
+ * @serialization_purge_cmd_list: function ptr to be filled by serialization
+ *				  module
+ *
+ * Some of the legacy modules wants to call API to purge the commands in
+ * order to handle backward compatibility.
+ */
+struct serialization_legacy_callback {
+	void (*serialization_purge_cmd_list)(struct wlan_objmgr_psoc *,
+					     struct wlan_objmgr_vdev *,
+					     bool, bool, bool, bool, bool);
+};
+#endif
 #endif

+ 649 - 0
umac/cmn_services/serialization/src/wlan_serialization_non_scan.c

@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_non_scan.c
+ * This file defines the functions which deals with
+ * serialization non scan commands.
+ */
+
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_vdev_obj.h>
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_non_scan_i.h"
+
+/**
+ * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
+ * @pdev: pointer to pdev object
+ *
+ * This API will be called to find out if non scan cmd is allowed.
+ *
+ * Return: true or false
+ */
+bool
+wlan_serialization_is_active_non_scan_cmd_allowed(
+		struct wlan_serialization_command *cmd)
+{
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	uint32_t vdev_active_cmd_bitmap;
+	bool blocking_cmd_active = 0;
+	uint8_t blocking_cmd_waiting = 0;
+	bool status = false;
+	uint32_t vdev_id;
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(
+			wlan_serialization_get_pdev_from_cmd(cmd));
+
+	pdev_queue = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj,
+							   cmd->cmd_type);
+
+	vdev_active_cmd_bitmap = pdev_queue->vdev_active_cmd_bitmap;
+	blocking_cmd_active = pdev_queue->blocking_cmd_active;
+	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
+
+	/*
+	 * Command is blocking
+	 */
+	if (cmd->is_blocking) {
+		/*
+		 * For blocking commands, no other
+		 * commands from any vdev should be active
+		 */
+		if (vdev_active_cmd_bitmap) {
+			status = false;
+			pdev_queue->blocking_cmd_waiting++;
+		} else {
+			status = true;
+		}
+	} else {
+		/*
+		 * Command is non blocking
+		 * For activating non blocking commands, if there any blocking
+		 * commands, waiting or active, put it to pending queue
+		 */
+		if (blocking_cmd_active || blocking_cmd_waiting) {
+			status = false;
+		} else {
+		/*
+		 * For non blocking command, and no blocking commands
+		 * waiting or active, check if a cmd for that vdev is active
+		 * If not active, put to active else pending queue
+		 */
+			vdev_id = wlan_vdev_get_id(cmd->vdev);
+			status = vdev_active_cmd_bitmap & (1 << vdev_id)
+						? false : true;
+		}
+	}
+	return status;
+}
+
+enum wlan_serialization_status wlan_ser_add_non_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t is_cmd_for_active_queue)
+{
+	enum wlan_serialization_status pdev_status, vdev_status;
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	struct wlan_serialization_command_list *pcmd_list;
+	uint8_t vdev_id;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+
+	ser_debug("add non scan cmd: type[%d] id[%d] prio[%d] blocking[%d]",
+		  cmd_list->cmd.cmd_type,
+		  cmd_list->cmd.cmd_id,
+		  cmd_list->cmd.is_high_priority,
+		  cmd_list->cmd.is_blocking);
+
+	vdev_status = wlan_serialization_add_cmd_to_vdev_queue(
+			ser_pdev_obj, cmd_list, is_cmd_for_active_queue);
+
+	if (vdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) {
+		status = vdev_status;
+		goto vdev_error;
+	}
+
+	if (is_cmd_for_active_queue) {
+		if (vdev_status != WLAN_SER_CMD_ACTIVE) {
+			ser_err("Failed to add to vdev active queue");
+			QDF_ASSERT(0);
+			goto vdev_error;
+		}
+	} else {
+		if (vdev_status != WLAN_SER_CMD_PENDING) {
+			ser_err("Failed to add to vdev pending queue");
+			QDF_ASSERT(0);
+			goto vdev_error;
+		}
+	}
+
+	pdev_status = wlan_serialization_add_cmd_to_pdev_queue(
+			ser_pdev_obj, cmd_list, is_cmd_for_active_queue);
+
+	if (pdev_status == WLAN_SER_CMD_DENIED_LIST_FULL) {
+		status = pdev_status;
+		goto pdev_error;
+	}
+
+	if (is_cmd_for_active_queue) {
+		if (pdev_status != WLAN_SER_CMD_ACTIVE) {
+			ser_err("Failed to add to pdev active queue");
+			QDF_ASSERT(0);
+			goto pdev_error;
+		}
+	} else {
+		if (pdev_status != WLAN_SER_CMD_PENDING) {
+			ser_err("Failed to add to pdev pending queue");
+			QDF_ASSERT(0);
+			goto pdev_error;
+		}
+	}
+pdev_error:
+	/*
+	 * If cmd added to vdev queue, but failed while
+	 * adding to pdev queue, remove cmd from vdev queue as well
+	 */
+	if (pdev_status != vdev_status) {
+		wlan_serialization_remove_cmd_from_vdev_queue(
+			ser_pdev_obj, &pcmd_list,
+			&cmd_list->cmd,
+			is_cmd_for_active_queue);
+	} else {
+		status = pdev_status;
+	}
+
+	if (is_cmd_for_active_queue) {
+		pdev_queue = wlan_serialization_get_pdev_queue_obj(
+				ser_pdev_obj, cmd_list->cmd.cmd_type);
+		vdev_id = wlan_vdev_get_id(cmd_list->cmd.vdev);
+		pdev_queue->vdev_active_cmd_bitmap |= (1 << vdev_id);
+
+		if (cmd_list->cmd.is_blocking)
+			pdev_queue->blocking_cmd_active = 1;
+	}
+
+vdev_error:
+	return status;
+}
+
+static
+struct wlan_serialization_command_list*
+wlan_serialization_get_next_non_scan_active_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_objmgr_vdev *vdev)
+{
+	qdf_list_t *pending_queue;
+	qdf_list_node_t *pending_node = NULL;
+	struct wlan_serialization_command_list *pending_cmd_list = NULL;
+	struct wlan_ser_vdev_obj *ser_vdev_obj;
+	struct wlan_serialization_vdev_queue *vdev_q_obj;
+	QDF_STATUS status;
+
+	ser_vdev_obj = wlan_serialization_get_vdev_obj(vdev);
+
+	vdev_q_obj = &ser_vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN];
+	pending_queue = &vdev_q_obj->pending_list;
+
+	if (wlan_serialization_list_empty(pending_queue)) {
+		ser_debug("nothing to move from pending to active queue");
+		goto error;
+	}
+
+	status = wlan_serialization_get_cmd_from_queue(pending_queue,
+						       &pending_node);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		ser_err("can't read cmd from queue");
+		pending_cmd_list = NULL;
+		goto error;
+	}
+
+	pending_cmd_list =
+		qdf_container_of(pending_node,
+				 struct wlan_serialization_command_list,
+				 vdev_node);
+
+	if (pending_cmd_list)
+		ser_debug("next non scan active cmd found from pending queue");
+
+error:
+	return pending_cmd_list;
+}
+
+enum wlan_serialization_status
+wlan_ser_move_multiple_non_scan_pending_to_active(
+		struct wlan_ser_pdev_obj *ser_pdev_obj)
+{
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	qdf_list_t *active_queue;
+	qdf_list_t *pending_queue;
+	qdf_list_node_t *nnode = NULL;
+	struct wlan_serialization_command_list *pending_cmd_list;
+	struct wlan_serialization_command_list *active_cmd_list;
+	struct wlan_serialization_command cmd_to_remove;
+	uint32_t blocking_cmd_waiting;
+	uint32_t vdev_id;
+	uint32_t qsize;
+	bool vdev_cmd_active = 0;
+
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	QDF_STATUS peek_status = QDF_STATUS_E_FAILURE;
+	QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
+
+	pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
+	active_queue = &pdev_queue->active_list;
+	pending_queue = &pdev_queue->pending_list;
+	blocking_cmd_waiting = pdev_queue->blocking_cmd_waiting;
+
+	qsize =  wlan_serialization_list_size(pending_queue);
+	while (qsize--) {
+		peek_status = wlan_serialization_get_cmd_from_queue(
+				pending_queue, &nnode);
+		if (peek_status != QDF_STATUS_SUCCESS) {
+			ser_err("can't peek cmd");
+			break;
+		}
+
+		pending_cmd_list = qdf_container_of(
+				nnode, struct wlan_serialization_command_list,
+				pdev_node);
+		if (!pending_cmd_list) {
+			ser_debug(
+				"non scan cmd cannot move from pending to active");
+			goto error;
+		}
+
+		if (pending_cmd_list->cmd.is_blocking &&
+		    pdev_queue->vdev_active_cmd_bitmap) {
+			break;
+		}
+
+		vdev_id = wlan_vdev_get_id(pending_cmd_list->cmd.vdev);
+		vdev_cmd_active =
+			pdev_queue->vdev_active_cmd_bitmap & (1 << vdev_id);
+		if (vdev_cmd_active)
+			continue;
+
+		status = WLAN_SER_CMD_ACTIVE;
+
+		qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd,
+			     sizeof(struct wlan_serialization_command));
+
+		if (!wlan_serialization_is_active_cmd_allowed(&cmd_to_remove)) {
+			ser_debug("Can't add to active queue cmd_id:%d",
+				  cmd_to_remove.cmd_id);
+			continue;
+		}
+
+		qdf_status = wlan_ser_remove_non_scan_cmd(ser_pdev_obj,
+							  &pending_cmd_list,
+							  &cmd_to_remove,
+							  false);
+
+		if (QDF_STATUS_SUCCESS != qdf_status) {
+			ser_err("Can't remove cmd from pendingQ id-%d type-%d",
+				pending_cmd_list->cmd.cmd_id,
+				pending_cmd_list->cmd.cmd_type);
+			QDF_ASSERT(0);
+			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+			goto error;
+		}
+
+		active_cmd_list = pending_cmd_list;
+
+		status = wlan_ser_add_non_scan_cmd(
+				ser_pdev_obj, active_cmd_list, true);
+
+		if (WLAN_SER_CMD_ACTIVE != status) {
+			ser_err("Can't move cmd to activeQ id-%d type-%d",
+				pending_cmd_list->cmd.cmd_id,
+				pending_cmd_list->cmd.cmd_type);
+			wlan_serialization_insert_back(
+				&pdev_queue->cmd_pool_list,
+				&active_cmd_list->pdev_node);
+			status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+			goto error;
+		}
+
+		qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
+				   &active_cmd_list->cmd_in_use);
+
+		nnode = NULL;
+		if (active_cmd_list->cmd.is_blocking)
+			pdev_queue->blocking_cmd_waiting--;
+
+		if (pending_cmd_list->cmd.is_blocking)
+			break;
+	}
+
+error:
+	return status;
+}
+
+enum wlan_serialization_status
+wlan_ser_move_non_scan_pending_to_active(
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_serialization_command_list *pending_cmd_list;
+	struct wlan_serialization_command_list *active_cmd_list;
+	struct wlan_serialization_command cmd_to_remove;
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	QDF_STATUS qdf_status;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+
+	pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
+
+	ser_enter();
+
+	if (!ser_pdev_obj) {
+		ser_err("Can't find ser_pdev_obj");
+		goto error;
+	}
+
+	pending_cmd_list =
+		wlan_serialization_get_next_non_scan_active_cmd(
+						ser_pdev_obj,
+						vdev);
+
+	if (!pending_cmd_list) {
+		ser_debug("non scan cmd cannot move from pending to active");
+		goto error;
+	}
+
+	qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd,
+		     sizeof(struct wlan_serialization_command));
+
+	qdf_status = wlan_ser_remove_non_scan_cmd(ser_pdev_obj,
+						  &pending_cmd_list,
+						  &cmd_to_remove, false);
+
+	if (QDF_STATUS_SUCCESS != qdf_status) {
+		ser_err("Can't remove cmd from pendingQ id-%d type-%d",
+			pending_cmd_list->cmd.cmd_id,
+			pending_cmd_list->cmd.cmd_type);
+		QDF_ASSERT(0);
+		status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+		goto error;
+	}
+
+	active_cmd_list = pending_cmd_list;
+
+	status = wlan_ser_add_non_scan_cmd(
+				ser_pdev_obj, active_cmd_list, true);
+
+	if (WLAN_SER_CMD_ACTIVE != status) {
+		ser_err("Can't move cmd to activeQ id-%d type-%d",
+			pending_cmd_list->cmd.cmd_id,
+			pending_cmd_list->cmd.cmd_type);
+		wlan_serialization_insert_back(
+			&pdev_queue->cmd_pool_list,
+			&active_cmd_list->pdev_node);
+		goto error;
+	}
+
+	qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
+			   &active_cmd_list->cmd_in_use);
+
+	*pcmd_list = active_cmd_list;
+
+error:
+	ser_exit();
+	return status;
+}
+
+QDF_STATUS wlan_ser_remove_non_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_serialization_command *cmd,
+		uint8_t is_active_cmd)
+{
+	QDF_STATUS pdev_status, vdev_status;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	uint32_t vdev_id;
+	bool blocking_cmd_removed = 0;
+	struct wlan_serialization_pdev_queue *pdev_queue;
+
+	ser_debug("remove non scan cmd: type[%d] id[%d] prio[%d] blocking[%d]",
+		  cmd->cmd_type,
+		  cmd->cmd_id,
+		  cmd->is_high_priority,
+		  cmd->is_blocking);
+
+	vdev_status =
+		wlan_serialization_remove_cmd_from_vdev_queue(ser_pdev_obj,
+							      pcmd_list,
+							      cmd,
+							      is_active_cmd);
+
+	if (vdev_status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to remove cmd from vdev active/pending queue");
+		goto error;
+	}
+
+	pdev_status =
+		wlan_serialization_remove_cmd_from_pdev_queue(ser_pdev_obj,
+							      pcmd_list,
+							      cmd,
+							      is_active_cmd);
+
+	if (pdev_status != QDF_STATUS_SUCCESS) {
+		ser_err("Failed to remove cmd from pdev active/pending queue");
+		goto error;
+	}
+
+	if (is_active_cmd) {
+		blocking_cmd_removed = (*pcmd_list)->cmd.is_blocking;
+		pdev_queue = wlan_serialization_get_pdev_queue_obj(
+				ser_pdev_obj, (*pcmd_list)->cmd.cmd_type);
+
+		if (blocking_cmd_removed)
+			pdev_queue->blocking_cmd_active = 0;
+
+		vdev_id = wlan_vdev_get_id(cmd->vdev);
+		pdev_queue->vdev_active_cmd_bitmap &= ~(1 << vdev_id);
+	}
+
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	return status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_ser_cancel_non_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
+		struct wlan_serialization_command *cmd,
+		enum wlan_serialization_cmd_type cmd_type,
+		uint8_t is_active_queue)
+{
+	qdf_list_t *pdev_queue;
+	qdf_list_t *vdev_queue;
+	struct wlan_serialization_pdev_queue *pdev_q;
+	uint32_t qsize;
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	struct wlan_serialization_command cmd_bkup;
+	qdf_list_node_t *nnode = NULL, *pnode = NULL;
+	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
+	struct wlan_objmgr_psoc *psoc = NULL;
+	QDF_STATUS qdf_status;
+	QDF_STATUS pdev_status, vdev_status;
+	struct wlan_ser_vdev_obj *ser_vdev_obj;
+
+	ser_enter();
+
+	pdev_q = wlan_serialization_get_pdev_queue_obj(ser_pdev_obj, cmd_type);
+
+	pdev_queue = wlan_serialization_get_list_from_pdev_queue(
+			ser_pdev_obj, cmd_type, is_active_queue);
+
+	if (pdev)
+		psoc = wlan_pdev_get_psoc(pdev);
+	else if (vdev)
+		psoc = wlan_vdev_get_psoc(vdev);
+	else if (cmd && cmd->vdev)
+		psoc = wlan_vdev_get_psoc(cmd->vdev);
+	else
+		ser_debug("Can't find psoc");
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	qsize = wlan_serialization_list_size(pdev_queue);
+	while (!wlan_serialization_list_empty(pdev_queue) && qsize--) {
+		if (wlan_serialization_get_cmd_from_queue(pdev_queue, &nnode)
+		    != QDF_STATUS_SUCCESS) {
+			ser_err("can't read cmd from queue");
+			status = WLAN_SER_CMD_NOT_FOUND;
+			break;
+		}
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+		if (cmd && !wlan_serialization_match_cmd_id_type(
+							nnode, cmd,
+							WLAN_SER_PDEV_NODE)) {
+			pnode = nnode;
+			continue;
+		}
+
+		if (vdev &&
+		    !wlan_serialization_match_cmd_vdev(nnode,
+						      vdev,
+						      WLAN_SER_PDEV_NODE)) {
+			pnode = nnode;
+			continue;
+		}
+
+		if (pdev &&
+		    !wlan_serialization_match_cmd_pdev(nnode,
+						       pdev,
+						       WLAN_SER_PDEV_NODE)) {
+			pnode = nnode;
+			continue;
+		}
+
+		/*
+		 * active queue can't be removed directly, requester needs to
+		 * wait for active command response and send remove request for
+		 * active command separately
+		 */
+		if (is_active_queue) {
+			if (!psoc || !cmd_list) {
+				ser_err("psoc:0x%pK, cmd_list:0x%pK",
+					psoc, cmd_list);
+				status = WLAN_SER_CMD_NOT_FOUND;
+				break;
+			}
+
+			/* Cancel request received for a cmd in active
+			 * queue which has not been activated yet, we
+			 * should assert here
+			 */
+			if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
+						&cmd_list->cmd_in_use)) {
+				wlan_serialization_release_lock(pdev_q);
+				status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
+				goto error;
+			}
+
+			qdf_status = wlan_serialization_find_and_stop_timer(
+							psoc, &cmd_list->cmd);
+			if (QDF_STATUS_SUCCESS != qdf_status) {
+				ser_err("Can't fix timer for active cmd");
+				status = WLAN_SER_CMD_NOT_FOUND;
+				break;
+			}
+			status = WLAN_SER_CMD_IN_ACTIVE_LIST;
+		}
+
+		qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
+			     sizeof(struct wlan_serialization_command));
+
+		pdev_status =
+			wlan_serialization_remove_node(pdev_queue,
+						       &cmd_list->pdev_node);
+
+		ser_vdev_obj = wlan_serialization_get_vdev_obj(
+					cmd_list->cmd.vdev);
+
+		vdev_queue = wlan_serialization_get_list_from_vdev_queue(
+			ser_vdev_obj, cmd_type, is_active_queue);
+
+		vdev_status =
+			wlan_serialization_remove_node(vdev_queue,
+						       &cmd_list->vdev_node);
+
+		if (pdev_status != QDF_STATUS_SUCCESS ||
+		    vdev_status != QDF_STATUS_SUCCESS) {
+			ser_err("can't remove cmd from pdev/vdev queue");
+			status = WLAN_SER_CMD_NOT_FOUND;
+			break;
+		}
+
+		qdf_mem_zero(&cmd_list->cmd,
+			     sizeof(struct wlan_serialization_command));
+
+		qdf_status = wlan_serialization_insert_back(
+			&pdev_q->cmd_pool_list,
+			&cmd_list->pdev_node);
+
+		if (QDF_STATUS_SUCCESS != qdf_status) {
+			ser_err("can't remove cmd from queue");
+			status = WLAN_SER_CMD_NOT_FOUND;
+			break;
+		}
+		nnode = pnode;
+
+		wlan_serialization_release_lock(pdev_q);
+		/*
+		 * call pending cmd's callback to notify that
+		 * it is being removed
+		 */
+		if (cmd_bkup.cmd_cb) {
+			/* caller should now do necessary clean up */
+			ser_debug("cmd cb: type[%d] id[%d]",
+				  cmd_bkup.cmd_type,
+				  cmd_bkup.cmd_id);
+			ser_debug("reason: WLAN_SER_CB_CANCEL_CMD");
+			cmd_bkup.cmd_cb(&cmd_bkup,
+					WLAN_SER_CB_CANCEL_CMD);
+			/* caller should release the memory */
+			ser_debug("reason: WLAN_SER_CB_RELEASE_MEM_CMD");
+			cmd_bkup.cmd_cb(&cmd_bkup,
+					WLAN_SER_CB_RELEASE_MEM_CMD);
+		}
+
+		wlan_serialization_acquire_lock(pdev_q);
+
+		if (!is_active_queue)
+			status = WLAN_SER_CMD_IN_PENDING_LIST;
+
+		if (!vdev && !pdev)
+			break;
+	}
+
+	wlan_serialization_release_lock(pdev_q);
+
+error:
+	ser_exit();
+	return status;
+}

+ 126 - 0
umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h

@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_non_scan_i.h
+ * This file defines the prototypes for functions which deals with
+ * serialization non scan commands.
+ */
+
+#ifndef __WLAN_SERIALIZATION_NON_SCAN_I_H
+#define __WLAN_SERIALIZATION_NON_SCAN_I_H
+
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_mc_timer.h>
+#include <wlan_utility.h>
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_api.h"
+#include "wlan_serialization_internal_i.h"
+#include "wlan_serialization_queue_i.h"
+
+/**
+ * wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
+ *			to be enqueued in active queue
+ * @cmd: Serialization command information
+ *
+ * This API will be called to find out if non scan cmd is allowed.
+ *
+ * Return: true or false
+ */
+bool
+wlan_serialization_is_active_non_scan_cmd_allowed(
+		struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_ser_add_non_scan_cmd() - Add a non-scan cmd to serialization queue
+ * @ser_pdev_obj: Serialization private pdev object
+ * @cmd_list: Command list with command info that is to be queued
+ * @is_cmd_for_active_queue: If the cmd to be enqueued in active queue or
+ *			pending queue
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status
+wlan_ser_add_non_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t is_cmd_for_active_queue);
+/**
+ * wlan_ser_move_non_scan_pending_to_active() - Move a non-scan cmd from pending
+ *			queue to active queue
+ * @pcmd_list: Pointer to command list containing the command
+ * @ser_pdev_obj: Serialization private pdev object
+ * @vdev: Pointer to object manager vdev
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status
+wlan_ser_move_non_scan_pending_to_active(
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_ser_move_multiple_non_scan_pending_to_active() - Move multiple non-scan
+ *			cmd from pending queue to active queue
+ * @ser_pdev_obj: Serialization private pdev object
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status
+wlan_ser_move_multiple_non_scan_pending_to_active(
+		struct wlan_ser_pdev_obj *ser_pdev_obj);
+
+/**
+ * wlan_ser_remove_non_scan_cmd() - Remove a non-scan cmd from the given queue
+ * @ser_pdev_obj: Serialization private pdev object
+ * @pcmd_list: Pointer to command list containing the command
+ * @cmd: Serialization command information
+ * @is_active_cmd: If the cmd has to be removed from active queue or pending
+ *			queue
+ *
+ * Return: QDF_STATUS_SUCCESS on successfully removing the cmd else
+ *			QDF_STATUS_E_FAILURE
+ */
+QDF_STATUS
+wlan_ser_remove_non_scan_cmd(struct wlan_ser_pdev_obj *ser_pdev_obj,
+			     struct wlan_serialization_command_list **pcmd_list,
+			     struct wlan_serialization_command *cmd,
+			     uint8_t is_active_cmd);
+/**
+ * wlan_ser_cancel_non_scan_cmd() - Cancel a non-scan cmd from the given queue
+ * @ser_obj: Serialization private pdev object
+ * @pdev: Pointer to object manager pdev
+ * @vdev: Pointer to object manager vdev
+ * @cmd: Serialization command information
+ * @cmd_type: Serialization command type to be cancelled
+ * @is_active_queue: If the cmd has to be removed from active queue or pending
+ *			queue
+ *
+ * Return: Status specifying the cancel of a command from the given queue
+ */
+enum wlan_serialization_cmd_status
+wlan_ser_cancel_non_scan_cmd(struct wlan_ser_pdev_obj *ser_obj,
+			     struct wlan_objmgr_pdev *pdev,
+			     struct wlan_objmgr_vdev *vdev,
+			     struct wlan_serialization_command *cmd,
+			     enum wlan_serialization_cmd_type cmd_type,
+			     uint8_t is_active_queue);
+#endif

+ 198 - 0
umac/cmn_services/serialization/src/wlan_serialization_queue.c

@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_queue.c
+ * This file defines the functions which deals with the
+ * serialization queue objects.
+ */
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <qdf_list.h>
+#include <qdf_status.h>
+#include "wlan_serialization_api.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_queue_i.h"
+
+struct wlan_serialization_pdev_queue *wlan_serialization_get_pdev_queue_obj(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		enum wlan_serialization_cmd_type cmd_type)
+{
+	struct wlan_serialization_pdev_queue *pdev_queue = NULL;
+
+	if (cmd_type < WLAN_SER_CMD_NONSCAN)
+		pdev_queue = &pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+	else
+		pdev_queue = &pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN];
+
+	return pdev_queue;
+}
+
+struct wlan_serialization_vdev_queue *wlan_serialization_get_vdev_queue_obj(
+		struct wlan_ser_vdev_obj *vdev_obj,
+		enum wlan_serialization_cmd_type cmd_type)
+{
+	struct wlan_serialization_vdev_queue *vdev_queue = NULL;
+
+	vdev_queue = &vdev_obj->vdev_q[SER_VDEV_QUEUE_COMP_NON_SCAN];
+
+	return vdev_queue;
+}
+
+qdf_list_t *wlan_serialization_get_list_from_pdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		enum wlan_serialization_cmd_type cmd_type,
+		uint8_t is_active_cmd)
+{
+	struct wlan_serialization_pdev_queue *pdev_queue;
+	qdf_list_t *queue = NULL;
+
+	pdev_queue = wlan_serialization_get_pdev_queue_obj(pdev_obj, cmd_type);
+	if (is_active_cmd)
+		queue = &pdev_queue->active_list;
+	else
+		queue = &pdev_queue->pending_list;
+
+	return queue;
+}
+
+qdf_list_t *wlan_serialization_get_list_from_vdev_queue(
+		struct wlan_ser_vdev_obj *vdev_obj,
+		enum wlan_serialization_cmd_type cmd_type,
+		uint8_t is_active_cmd)
+{
+	struct wlan_serialization_vdev_queue *vdev_queue;
+	qdf_list_t *queue = NULL;
+
+	vdev_queue = wlan_serialization_get_vdev_queue_obj(vdev_obj, cmd_type);
+	if (is_active_cmd)
+		queue = &vdev_queue->active_list;
+	else
+		queue = &vdev_queue->pending_list;
+
+	return queue;
+}
+
+enum wlan_serialization_status
+wlan_serialization_add_cmd_to_pdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t for_active_queue)
+{
+	qdf_list_t *queue;
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+
+	if (!pdev_obj) {
+		ser_err("invalid serialization pdev");
+		status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+		goto error;
+	}
+
+	queue = wlan_serialization_get_list_from_pdev_queue(
+			pdev_obj, cmd_list->cmd.cmd_type, for_active_queue);
+
+	status = wlan_serialization_add_cmd_to_queue(queue, cmd_list,
+						     pdev_obj,
+						     for_active_queue,
+						     WLAN_SER_PDEV_NODE);
+
+error:
+	return status;
+}
+
+enum wlan_serialization_status
+wlan_serialization_add_cmd_to_vdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t for_active_queue)
+{
+	qdf_list_t *queue;
+	enum wlan_serialization_status status;
+	struct wlan_serialization_command *cmd;
+	struct wlan_ser_vdev_obj *vdev_obj;
+
+	cmd = &cmd_list->cmd;
+
+	vdev_obj = wlan_serialization_get_vdev_obj(
+			wlan_serialization_get_vdev_from_cmd(cmd));
+
+	queue = wlan_serialization_get_list_from_vdev_queue(vdev_obj,
+							    cmd->cmd_type,
+							    for_active_queue);
+
+	status = wlan_serialization_add_cmd_to_queue(queue, cmd_list,
+						     pdev_obj,
+						     for_active_queue,
+						     WLAN_SER_VDEV_NODE);
+
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_remove_cmd_from_pdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_serialization_command *cmd,
+		uint8_t is_active_queue)
+{
+	qdf_list_t *queue;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	if (!pdev_obj) {
+		ser_err("Invalid pdev");
+		return status;
+	}
+
+	queue = wlan_serialization_get_list_from_pdev_queue(
+			pdev_obj, cmd->cmd_type, is_active_queue);
+
+	status = wlan_serialization_remove_cmd_from_queue(queue, cmd,
+							  pcmd_list,
+							  pdev_obj,
+							  WLAN_SER_PDEV_NODE);
+
+	return status;
+}
+
+QDF_STATUS
+wlan_serialization_remove_cmd_from_vdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_serialization_command *cmd,
+		uint8_t is_active_queue)
+{
+	qdf_list_t *queue;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	struct wlan_ser_vdev_obj *vdev_obj;
+
+	vdev_obj = wlan_serialization_get_vdev_obj(
+			wlan_serialization_get_vdev_from_cmd(cmd));
+
+	queue = wlan_serialization_get_list_from_vdev_queue(vdev_obj,
+							    cmd->cmd_type,
+							    is_active_queue);
+
+	status = wlan_serialization_remove_cmd_from_queue(queue, cmd,
+							  pcmd_list,
+							  pdev_obj,
+							  WLAN_SER_VDEV_NODE);
+
+	return status;
+}
+

+ 148 - 0
umac/cmn_services/serialization/src/wlan_serialization_queue_i.h

@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_queue_i.h
+ * This file defines the prototpye for functions which deals with the
+ * serialization queue objects.
+ */
+#ifndef __WLAN_SERIALIZATION_QUEUE_I_H
+#define __WLAN_SERIALIZATION_QUEUE_I_H
+
+#include <wlan_serialization_api.h>
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_utils_i.h"
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <qdf_list.h>
+#include <qdf_status.h>
+
+/**
+ * wlan_serialization_get_pdev_queue_obj() - Get serialization pdev queue for
+ *			the given cmd_type
+ * @pdev_obj: Serialization private pdev object
+ * @cmd_type: Serialization command type i.e scan or non-scan
+ *
+ * Return: Pointer to serialization pdev queue
+ */
+struct wlan_serialization_pdev_queue *wlan_serialization_get_pdev_queue_obj(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		enum wlan_serialization_cmd_type cmd_type);
+
+/**
+ * wlan_serialization_get_vdev_queue_obj() - Get serialization vdev queue for
+ *			the given cmd_type
+ * @vdev_obj: Serialization private vdev object
+ * @cmd_type: Serialization command type i.e scan or non-scan
+ *
+ * Return: Pointer to serialization vdev queue
+ */
+struct wlan_serialization_vdev_queue *wlan_serialization_get_vdev_queue_obj(
+		struct wlan_ser_vdev_obj *vdev_obj,
+		enum wlan_serialization_cmd_type cmd_type);
+
+/**
+ * wlan_serialization_get_list_from_pdev_queue() - Get list member from the pdev
+ *			queue for the given cmd type
+ * @pdev_obj: Serialization private pdev object
+ * @cmd_type: Serialization command type i.e scan or non-scan
+ * @is_active_cmd: Get list from active queue or pending queue
+ *
+ * Return: Pointer to the obtained list member
+ */
+qdf_list_t *wlan_serialization_get_list_from_pdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		enum wlan_serialization_cmd_type cmd_type,
+		uint8_t is_active_cmd);
+
+/**
+ * wlan_serialization_get_list_from_vdev_queue() - Get list member from the vdev
+ *			queue for the given cmd type
+ * @vdev_obj: Serialization private vdev object
+ * @cmd_type: Serialization command type i.e scan or non-scan
+ * @is_active_cmd: Get list from active queue or pending queue
+ *
+ * Return: Pointer to the obtained list member
+ */
+qdf_list_t *wlan_serialization_get_list_from_vdev_queue(
+		struct wlan_ser_vdev_obj *vdev_obj,
+		enum wlan_serialization_cmd_type cmd_type,
+		uint8_t is_active_cmd);
+
+/**
+ * wlan_serialization_add_cmd_to_pdev_queue() - Add given cmd to the pdev
+ *			queue for the given cmd type
+ * @pdev_obj: Serialization private pdev object
+ * @cmd_list: Pointer to command list containing the command
+ * @is_cmd_for_active_queue: Add to active queue or pending queue
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status wlan_serialization_add_cmd_to_pdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t is_cmd_for_active_queue);
+
+/**
+ * wlan_serialization_add_cmd_to_vdev_queue() - Add given cmd to the vdev
+ *			queue for the given cmd type
+ * @pdev_obj: Serialization private pdev object
+ * @cmd_list: Pointer to command list containing the command
+ * @is_cmd_for_active_queue: Add to active queue or pending queue
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status wlan_serialization_add_cmd_to_vdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t is_cmd_for_active_queue);
+
+/**
+ * wlan_serialization_remove_cmd_from_pdev_queue() - Remove given cmd from
+ *			the pdev queue for the given cmd type
+ * @pdev_obj: Serialization private pdev object
+ * @pcmd_list: Pointer to command list containing the command
+ * @cmd: Serialization command information
+ * @is_active_queue: Remove from active queue or pending queue
+ *
+ * Return: QDF_STATUS_SUCCESS on success, error code on failure
+ */
+QDF_STATUS wlan_serialization_remove_cmd_from_pdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_serialization_command *cmd,
+		uint8_t is_active_queue);
+
+/**
+ * wlan_serialization_remove_cmd_from_vdev_queue() - Remove given cmd from
+ *			the vdev queue for the given cmd type
+ * @pdev_obj: Serialization private pdev object
+ * @pcmd_list: Pointer to command list containing the command
+ * @cmd: Serialization command information
+ * @is_active_queue: Remove from active queue or pending queue
+ *
+ * Return: QDF_STATUS_SUCCESS on success, error code on failure
+ */
+QDF_STATUS wlan_serialization_remove_cmd_from_vdev_queue(
+		struct wlan_ser_pdev_obj *pdev_obj,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_serialization_command *cmd,
+		uint8_t is_active_queue);
+
+#endif

+ 424 - 0
umac/cmn_services/serialization/src/wlan_serialization_scan.c

@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_scan.c
+ * This file defines the functions which deals with
+ * serialization scan commands.
+ */
+
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_api.h"
+#include "wlan_serialization_scan_i.h"
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_mc_timer.h>
+#include <wlan_utility.h>
+
+void
+wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc,
+						 void *obj, void *arg)
+{
+	struct wlan_objmgr_pdev *pdev = obj;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_pdev_queue *pdev_q;
+	uint32_t *count = arg;
+
+	if (!pdev) {
+		ser_err("invalid pdev");
+		return;
+	}
+
+	ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
+			pdev, WLAN_UMAC_COMP_SERIALIZATION);
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+	*count += wlan_serialization_list_size(&pdev_q->active_list);
+}
+
+bool
+wlan_serialization_is_active_scan_cmd_allowed(
+		struct wlan_serialization_command *cmd)
+{
+	uint32_t count = 0;
+	struct wlan_objmgr_pdev *pdev = NULL;
+	struct wlan_objmgr_psoc *psoc;
+	bool status = false;
+
+	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
+	if (!pdev) {
+		ser_err("invalid pdev");
+		goto error;
+	}
+
+	psoc = wlan_pdev_get_psoc(pdev);
+	if (!psoc) {
+		ser_err("invalid psoc");
+		goto error;
+	}
+
+	wlan_objmgr_iterate_obj_list(
+			psoc, WLAN_PDEV_OP,
+			wlan_serialization_active_scan_cmd_count_handler,
+			&count, 1, WLAN_SERIALIZATION_ID);
+	if (count < ucfg_scan_get_max_active_scans(psoc)) {
+		ser_debug("count is [%d]", count);
+		status =  true;
+	}
+
+error:
+	return status;
+}
+
+bool wlan_ser_match_cmd_scan_id(
+			qdf_list_node_t *nnode,
+			struct wlan_serialization_command **cmd,
+			uint16_t scan_id, struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	bool match_found = false;
+
+	cmd_list = qdf_container_of(nnode,
+				    struct wlan_serialization_command_list,
+				    pdev_node);
+	if ((cmd_list->cmd.cmd_id == scan_id) &&
+	    (cmd_list->cmd.vdev == vdev)) {
+		*cmd = &cmd_list->cmd;
+		match_found = true;
+	};
+
+	ser_debug("match found: %d", match_found);
+
+	return match_found;
+}
+
+enum wlan_serialization_status
+wlan_ser_add_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_serialization_command_list *cmd_list,
+		uint8_t is_cmd_for_active_queue)
+{
+	enum wlan_serialization_status status;
+
+	ser_debug("add scan cmd: type[%d] id[%d] prio[%d] blocking[%d]",
+		  cmd_list->cmd.cmd_type,
+		  cmd_list->cmd.cmd_id,
+		  cmd_list->cmd.is_high_priority,
+		  cmd_list->cmd.is_blocking);
+
+	status = wlan_serialization_add_cmd_to_pdev_queue(
+			ser_pdev_obj, cmd_list,
+			is_cmd_for_active_queue);
+
+	return status;
+}
+
+QDF_STATUS
+wlan_ser_remove_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_serialization_command *cmd,
+		uint8_t is_active_cmd)
+{
+	QDF_STATUS status;
+
+	ser_debug("remove scan cmd: type[%d] id[%d] prio[%d] blocking[%d]",
+		  cmd->cmd_type,
+		  cmd->cmd_id,
+		  cmd->is_high_priority,
+		  cmd->is_blocking);
+
+	status = wlan_serialization_remove_cmd_from_pdev_queue(
+			ser_pdev_obj, pcmd_list, cmd, is_active_cmd);
+
+	return status;
+}
+
+enum wlan_serialization_cmd_status
+wlan_ser_cancel_scan_cmd(
+		struct wlan_ser_pdev_obj *ser_obj,
+		struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
+		struct wlan_serialization_command *cmd,
+		enum wlan_serialization_cmd_type cmd_type,
+		uint8_t is_active_queue)
+{
+	qdf_list_t *queue;
+	struct wlan_serialization_pdev_queue *pdev_q;
+	uint32_t qsize;
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	struct wlan_serialization_command cmd_bkup;
+	qdf_list_node_t *nnode = NULL, *pnode = NULL;
+	enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
+	struct wlan_objmgr_psoc *psoc = NULL;
+	QDF_STATUS qdf_status;
+
+	ser_enter();
+
+	pdev_q = &ser_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+
+	if (is_active_queue)
+		queue = &pdev_q->active_list;
+	else
+		queue = &pdev_q->pending_list;
+
+	if (pdev)
+		psoc = wlan_pdev_get_psoc(pdev);
+	else if (vdev)
+		psoc = wlan_vdev_get_psoc(vdev);
+	else if (cmd && cmd->vdev)
+		psoc = wlan_vdev_get_psoc(cmd->vdev);
+	else
+		ser_debug("Can't find psoc");
+
+	wlan_serialization_acquire_lock(pdev_q);
+
+	qsize = wlan_serialization_list_size(queue);
+	while (!wlan_serialization_list_empty(queue) && qsize--) {
+		if (wlan_serialization_get_cmd_from_queue(
+					queue, &nnode) != QDF_STATUS_SUCCESS) {
+			ser_err("can't read cmd from queue");
+			status = WLAN_SER_CMD_NOT_FOUND;
+			break;
+		}
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+
+		if (cmd && !wlan_serialization_match_cmd_id_type(
+							nnode, cmd,
+							WLAN_SER_PDEV_NODE)) {
+			pnode = nnode;
+			continue;
+		}
+		if (vdev &&
+		    !wlan_serialization_match_cmd_vdev(nnode,
+						      vdev,
+						      WLAN_SER_PDEV_NODE)) {
+			pnode = nnode;
+			continue;
+		}
+
+		if (pdev &&
+		    !wlan_serialization_match_cmd_pdev(nnode,
+						       pdev,
+						       WLAN_SER_PDEV_NODE)) {
+			pnode = nnode;
+			continue;
+		}
+
+		/*
+		 * active queue can't be removed directly, requester needs to
+		 * wait for active command response and send remove request for
+		 * active command separately
+		 */
+		if (is_active_queue) {
+			if (!psoc || !cmd_list) {
+				ser_err("psoc:0x%pK, cmd_list:0x%pK",
+					psoc, cmd_list);
+				status = WLAN_SER_CMD_NOT_FOUND;
+				break;
+			}
+
+			/* Cancel request received for a cmd in active
+			 * queue which has not been activated yet, we
+			 * should assert here
+			 */
+			if (qdf_atomic_test_bit(CMD_MARKED_FOR_ACTIVATION,
+						&cmd_list->cmd_in_use)) {
+				wlan_serialization_release_lock(pdev_q);
+				status = WLAN_SER_CMD_MARKED_FOR_ACTIVATION;
+				goto error;
+			}
+
+			qdf_status = wlan_serialization_find_and_stop_timer(
+							psoc, &cmd_list->cmd);
+			if (QDF_STATUS_SUCCESS != qdf_status) {
+				ser_err("Can't fix timer for active cmd");
+				status = WLAN_SER_CMD_NOT_FOUND;
+				break;
+			}
+			status = WLAN_SER_CMD_IN_ACTIVE_LIST;
+		}
+
+		qdf_mem_copy(&cmd_bkup, &cmd_list->cmd,
+			     sizeof(struct wlan_serialization_command));
+
+		qdf_status =
+			wlan_serialization_remove_node(queue,
+						       &cmd_list->pdev_node);
+
+		if (qdf_status != QDF_STATUS_SUCCESS) {
+			ser_err("can't remove cmd from pdev queue");
+			status = WLAN_SER_CMD_NOT_FOUND;
+			break;
+		}
+
+		qdf_mem_zero(&cmd_list->cmd,
+			     sizeof(struct wlan_serialization_command));
+
+		qdf_status = wlan_serialization_insert_back(
+			&pdev_q->cmd_pool_list,
+			&cmd_list->pdev_node);
+
+		if (QDF_STATUS_SUCCESS != qdf_status) {
+			ser_err("can't remove cmd from queue");
+			status = WLAN_SER_CMD_NOT_FOUND;
+			break;
+		}
+		nnode = pnode;
+
+		wlan_serialization_release_lock(pdev_q);
+		/*
+		 * call pending cmd's callback to notify that
+		 * it is being removed
+		 */
+		if (cmd_bkup.cmd_cb) {
+			ser_debug("cmd cb: type[%d] id[%d]",
+				  cmd_bkup.cmd_type,
+				  cmd_bkup.cmd_id);
+			ser_debug("reason: WLAN_SER_CB_CANCEL_CMD");
+
+			cmd_bkup.cmd_cb(&cmd_bkup,
+					WLAN_SER_CB_CANCEL_CMD);
+
+			ser_debug("reason: WLAN_SER_CB_RELEASE_MEM_CMD");
+			cmd_bkup.cmd_cb(&cmd_bkup,
+					WLAN_SER_CB_RELEASE_MEM_CMD);
+		}
+
+		wlan_serialization_acquire_lock(pdev_q);
+
+		if (!is_active_queue)
+			status = WLAN_SER_CMD_IN_PENDING_LIST;
+	}
+
+	wlan_serialization_release_lock(pdev_q);
+
+error:
+	ser_exit();
+	return status;
+}
+
+static struct wlan_serialization_command_list*
+wlan_serialization_get_next_scan_active_cmd(
+		struct wlan_ser_pdev_obj *ser_pdev_obj)
+{
+	qdf_list_t *pending_queue;
+	qdf_list_node_t *pending_node = NULL;
+	struct wlan_serialization_command_list *pending_cmd_list = NULL;
+	struct wlan_serialization_pdev_queue *pdev_q;
+	QDF_STATUS status;
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+
+	pending_queue = &pdev_q->pending_list;
+
+	if (wlan_serialization_list_empty(pending_queue)) {
+		ser_debug("nothing to move from pend to active que");
+		goto error;
+	}
+
+	status = wlan_serialization_peek_front(pending_queue,
+					       &pending_node);
+	if (QDF_STATUS_SUCCESS != status) {
+		ser_err("can't read from pending queue");
+		goto error;
+	}
+
+	pending_cmd_list =
+		qdf_container_of(pending_node,
+				 struct wlan_serialization_command_list,
+				 pdev_node);
+
+	ser_debug("next active scan cmd found from pending queue");
+error:
+	return pending_cmd_list;
+}
+
+enum wlan_serialization_status wlan_ser_move_scan_pending_to_active(
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj)
+{
+	struct wlan_serialization_command_list *pending_cmd_list;
+	struct wlan_serialization_command_list *active_cmd_list;
+	struct wlan_serialization_command cmd_to_remove;
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	QDF_STATUS qdf_status;
+	struct wlan_serialization_pdev_queue *pdev_q;
+
+	pdev_q = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN];
+
+	ser_enter();
+
+	if (!ser_pdev_obj) {
+		ser_err("Can't find ser_pdev_obj");
+		goto error;
+	}
+
+	pending_cmd_list =
+		wlan_serialization_get_next_scan_active_cmd(ser_pdev_obj);
+
+	if (!pending_cmd_list)
+		goto error;
+
+	qdf_mem_copy(&cmd_to_remove, &pending_cmd_list->cmd,
+		     sizeof(struct wlan_serialization_command));
+
+	qdf_status =
+		wlan_ser_remove_scan_cmd(ser_pdev_obj,
+					 &pending_cmd_list,
+					 &cmd_to_remove, false);
+
+	if (QDF_STATUS_SUCCESS != qdf_status) {
+		ser_err("Can't remove cmd from pendingQ id-%d type-%d",
+			pending_cmd_list->cmd.cmd_id,
+			pending_cmd_list->cmd.cmd_type);
+		QDF_ASSERT(0);
+		status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+		goto error;
+	}
+
+	active_cmd_list = pending_cmd_list;
+
+	status = wlan_ser_add_scan_cmd(ser_pdev_obj,
+				       active_cmd_list, true);
+
+	if (WLAN_SER_CMD_ACTIVE != status) {
+		wlan_serialization_insert_back(
+			&pdev_q->cmd_pool_list,
+			&active_cmd_list->pdev_node);
+
+		status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+		ser_err("Can't add cmd to activeQ id-%d type-%d",
+			active_cmd_list->cmd.cmd_id,
+			active_cmd_list->cmd.cmd_type);
+		QDF_ASSERT(0);
+		goto error;
+	}
+
+	qdf_atomic_set_bit(CMD_MARKED_FOR_ACTIVATION,
+			   &active_cmd_list->cmd_in_use);
+
+	*pcmd_list = active_cmd_list;
+
+error:
+	ser_exit();
+	return status;
+}

+ 147 - 0
umac/cmn_services/serialization/src/wlan_serialization_scan_i.h

@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2017-2018 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: wlan_serialization_scan.h
+ * This file defines the prototypes for functions which deals with
+ * serialization non scan commands.
+ */
+
+#ifndef __WLAN_SERIALIZATION_SCAN_I_H
+#define __WLAN_SERIALIZATION_SCAN_I_H
+
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_mc_timer.h>
+#include <wlan_utility.h>
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_api.h"
+#include "wlan_serialization_queue_i.h"
+#include "wlan_serialization_internal_i.h"
+
+/**
+ * wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds
+ * @psoc: pointer to soc strucutre
+ * @obj : pointer to pdev object
+ * @arg: pointer to argument
+ *
+ * This API will be called while iterating each pdev object and it will count
+ * number of scan commands present in that pdev object's active queue. count
+ * will be updated in *arg
+ *
+ * Return: none
+ */
+void
+wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc,
+						 void *obj, void *arg);
+
+/**
+ * wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed
+ * @pdev: pointer to pdev object
+ *
+ * This API will be called to find out if active scan cmd is allowed. It has
+ * to iterate through all pdev to find out total number of active scan cmds.
+ * If total number of active scan cmds reach to allowed threshold then don't
+ * allow more scan cmd.
+ *
+ * Return: true or false
+ */
+bool
+wlan_serialization_is_active_scan_cmd_allowed(
+		struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_ser_match_cmd_scan_id() - Compare the scan id and the vdev to the given
+ *			command
+ * @cmd: Serialization command information
+ * @scan_id: Scan id to be compared
+ * @vdev: Pointer to object manager vdev that needs to compared
+ *
+ * Return: true if match found, else false
+ */
+bool
+wlan_ser_match_cmd_scan_id(qdf_list_node_t *nnode,
+			   struct wlan_serialization_command **cmd,
+			   uint16_t scan_id,
+			   struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_ser_add_scan_cmd() - Add a scan cmd to serialization queue
+ * @ser_pdev_obj: Serialization private pdev object
+ * @cmd_list: Command list with command info that is to be queued
+ * @is_cmd_for_active_queue: If the cmd to be enqueued in active queue or
+ *			pending queue
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status
+wlan_ser_add_scan_cmd(struct wlan_ser_pdev_obj *ser_pdev_obj,
+		      struct wlan_serialization_command_list *cmd_list,
+		      uint8_t is_cmd_for_active_queue);
+
+/**
+ * wlan_ser_remove_scan_cmd() - Remove a scan cmd from the given queue
+ * @ser_pdev_obj: Serialization private pdev object
+ * @pcmd_list: Pointer to command list containing the command
+ * @cmd: Serialization command information
+ * @is_active_cmd: If the cmd has to be removed from active queue or pending
+ *			queue
+ *
+ * Return: QDF_STATUS_SUCCESS on successfully removing the cmd else
+ *			QDF_STATUS_E_FAILURE
+ */
+QDF_STATUS
+wlan_ser_remove_scan_cmd(struct wlan_ser_pdev_obj *ser_pdev_obj,
+			 struct wlan_serialization_command_list **pcmd_list,
+			 struct wlan_serialization_command *cmd,
+			 uint8_t is_active_cmd);
+
+/**
+ * wlan_ser_cancel_scan_cmd() - Cancel a scan cmd from the given queue
+ * @ser_obj: Serialization private pdev object
+ * @pdev: Pointer to object manager pdev
+ * @vdev: Pointer to object manager vdev
+ * @cmd: Serialization command information
+ * @cmd_type: Serialization command type to be cancelled
+ * @is_active_queue: If the cmd has to be removed from active queue or pending
+ *			queue
+ *
+ * Return: Status specifying the cancel of a command from the given queue
+ */
+enum wlan_serialization_cmd_status
+wlan_ser_cancel_scan_cmd(struct wlan_ser_pdev_obj *ser_obj,
+			 struct wlan_objmgr_pdev *pdev,
+			 struct wlan_objmgr_vdev *vdev,
+			 struct wlan_serialization_command *cmd,
+			 enum wlan_serialization_cmd_type cmd_type,
+			 uint8_t is_active_queue);
+
+/**
+ * wlan_ser_move_scan_pending_to_active() - Move a scan cmd from pending
+ *			queue to active queue
+ * @pcmd_list: Pointer to command list containing the command
+ * @ser_pdev_obj: Serialization private pdev object
+ *
+ * Return: Status of the cmd's serialization request
+ */
+enum wlan_serialization_status
+wlan_ser_move_scan_pending_to_active(
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj);
+#endif
+

+ 832 - 0
umac/cmn_services/serialization/src/wlan_serialization_utils.c

@@ -20,6 +20,7 @@
  * This file defines the utility helper functions for serialization component.
  */
 
+#ifdef CONFIG_SERIALIZATION_V1
 #include "wlan_serialization_utils_i.h"
 #include "wlan_serialization_main_i.h"
 #include "wlan_serialization_api.h"
@@ -1002,3 +1003,834 @@ wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj)
 	return QDF_STATUS_SUCCESS;
 }
 #endif
+#else /*New serialization code*/
+#include <wlan_objmgr_vdev_obj.h>
+#include <wlan_objmgr_pdev_obj.h>
+#include <qdf_mc_timer.h>
+#include <wlan_utility.h>
+#include "wlan_serialization_utils_i.h"
+#include "wlan_serialization_main_i.h"
+#include "wlan_serialization_queue_i.h"
+#include "wlan_serialization_api.h"
+
+struct wlan_objmgr_pdev*
+wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd)
+{
+	struct wlan_objmgr_pdev *pdev = NULL;
+
+	if (!cmd) {
+		ser_err("invalid cmd");
+		return pdev;
+	}
+	if (!cmd->vdev) {
+		ser_err("invalid cmd->vdev");
+		return pdev;
+	}
+	pdev = wlan_vdev_get_pdev(cmd->vdev);
+
+	return pdev;
+}
+
+struct wlan_objmgr_psoc*
+wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command *cmd)
+{
+	struct wlan_objmgr_psoc *psoc = NULL;
+
+	if (!cmd) {
+		ser_err("invalid cmd");
+		return psoc;
+	}
+	if (!cmd->vdev) {
+		ser_err("invalid cmd->vdev");
+		return psoc;
+	}
+	psoc = wlan_vdev_get_psoc(cmd->vdev);
+
+	return psoc;
+}
+
+struct wlan_objmgr_vdev*
+wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command *cmd)
+{
+	struct wlan_objmgr_vdev *vdev = NULL;
+
+	if (!cmd) {
+		ser_err("invalid cmd");
+		goto error;
+	}
+
+	vdev = cmd->vdev;
+
+error:
+	return vdev;
+}
+
+QDF_STATUS
+wlan_serialization_get_cmd_from_queue(qdf_list_t *queue,
+				      qdf_list_node_t **nnode)
+{
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+	qdf_list_node_t *pnode;
+
+	if (!queue) {
+		ser_err("input parameters are invalid");
+		goto error;
+	}
+
+	pnode = *nnode;
+	if (!pnode)
+		status = wlan_serialization_peek_front(queue, nnode);
+	else
+		status = wlan_serialization_peek_next(queue, pnode, nnode);
+
+	if (status != QDF_STATUS_SUCCESS)
+		ser_err("can't get next node from queue");
+
+error:
+	return status;
+}
+
+QDF_STATUS wlan_serialization_timer_destroy(
+		struct wlan_serialization_timer *ser_timer)
+{
+	QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
+
+	if (!ser_timer || !ser_timer->cmd) {
+		ser_debug("Invalid ser_timer");
+		qdf_status =  QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+
+	ser_debug("Destroying the timer");
+	qdf_timer_stop(&ser_timer->timer);
+	ser_timer->cmd = NULL;
+
+error:
+	return qdf_status;
+}
+
+/**
+ * wlan_serialization_stop_timer() - to stop particular timer
+ * @ser_timer: pointer to serialization timer
+ *
+ * This API stops the particular timer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer)
+{
+	wlan_serialization_timer_destroy(ser_timer);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_serialization_cleanup_all_timers(
+			struct wlan_ser_psoc_obj *psoc_ser_obj)
+{
+	struct wlan_serialization_timer *ser_timer;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint32_t i = 0;
+
+	ser_enter();
+
+	if (!psoc_ser_obj) {
+		ser_err("Invalid psoc_ser_obj");
+		status = QDF_STATUS_E_FAILURE;
+		goto error;
+	}
+
+	for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
+		ser_timer = &psoc_ser_obj->timers[i];
+		if (!ser_timer->cmd)
+			continue;
+		status = wlan_serialization_stop_timer(ser_timer);
+		if (QDF_STATUS_SUCCESS != status) {
+			/* lets not break the loop but report error */
+			ser_err("some error in stopping timer");
+		}
+	}
+
+error:
+	ser_exit();
+	return status;
+}
+
+QDF_STATUS wlan_serialization_validate_cmdtype(
+		 enum wlan_serialization_cmd_type cmd_type)
+{
+	if (cmd_type < 0 || cmd_type >= WLAN_SER_CMD_MAX) {
+		ser_err("Invalid cmd or comp passed");
+		return QDF_STATUS_E_INVAL;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS wlan_serialization_validate_cmd(
+		 enum wlan_umac_comp_id comp_id,
+		 enum wlan_serialization_cmd_type cmd_type)
+{
+	QDF_STATUS status = QDF_STATUS_E_INVAL;
+
+	ser_debug("validate cmd_type:%d, comp_id:%d",
+		  cmd_type, comp_id);
+	if (cmd_type < 0 || comp_id < 0 ||
+	    cmd_type >= WLAN_SER_CMD_MAX ||
+	   comp_id >= WLAN_UMAC_COMP_ID_MAX) {
+		ser_err("Invalid cmd or comp passed");
+		goto error;
+	}
+
+	status = QDF_STATUS_SUCCESS;
+error:
+	return status;
+}
+
+QDF_STATUS wlan_serialization_validate_cmd_list(
+		struct wlan_serialization_command_list *cmd_list)
+{
+	QDF_STATUS status = QDF_STATUS_E_INVAL;
+
+	if (!cmd_list->cmd.cmd_cb) {
+		ser_err("no cmd_cb for cmd type:%d, id: %d",
+			cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id);
+		QDF_ASSERT(0);
+		goto error;
+	}
+
+	if (!cmd_list->cmd.vdev) {
+		ser_err("invalid cmd.vdev");
+		goto error;
+	}
+
+	status = QDF_STATUS_SUCCESS;
+
+error:
+	return status;
+}
+
+static void wlan_serialization_release_pdev_list_cmds(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	qdf_list_node_t *node = NULL;
+
+	ser_enter();
+
+	while (!wlan_serialization_list_empty(&pdev_queue->active_list)) {
+		wlan_serialization_remove_front(
+				&pdev_queue->pending_list, &node);
+		wlan_serialization_insert_back(
+				&pdev_queue->cmd_pool_list, node);
+	}
+
+	while (!wlan_serialization_list_empty(&pdev_queue->pending_list)) {
+		wlan_serialization_remove_front(
+				&pdev_queue->pending_list, &node);
+		wlan_serialization_insert_back(
+				&pdev_queue->cmd_pool_list, node);
+	}
+
+	ser_exit();
+}
+
+static void wlan_serialization_release_vdev_list_cmds(qdf_list_t *list)
+{
+	qdf_list_node_t *node = NULL;
+
+	ser_enter();
+
+	while (!wlan_serialization_list_empty(list))
+		wlan_serialization_remove_front(list, &node);
+
+	ser_exit();
+}
+
+void wlan_serialization_destroy_pdev_list(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	ser_enter();
+
+	wlan_serialization_release_pdev_list_cmds(pdev_queue);
+	qdf_list_destroy(&pdev_queue->active_list);
+	qdf_list_destroy(&pdev_queue->pending_list);
+
+	ser_exit();
+}
+
+void wlan_serialization_destroy_vdev_list(qdf_list_t *list)
+{
+	ser_enter();
+
+	wlan_serialization_release_vdev_list_cmds(list);
+	qdf_list_destroy(list);
+
+	ser_exit();
+}
+
+struct wlan_ser_psoc_obj *wlan_serialization_get_psoc_obj(
+		struct wlan_objmgr_psoc *psoc)
+{
+	struct wlan_ser_psoc_obj *ser_soc_obj;
+
+	ser_soc_obj =
+		wlan_objmgr_psoc_get_comp_private_obj(
+				psoc, WLAN_UMAC_COMP_SERIALIZATION);
+
+	return ser_soc_obj;
+}
+
+struct wlan_ser_pdev_obj *wlan_serialization_get_pdev_obj(
+		struct wlan_objmgr_pdev *pdev)
+{
+	struct wlan_ser_pdev_obj *obj;
+
+	obj = wlan_objmgr_pdev_get_comp_private_obj(
+			pdev, WLAN_UMAC_COMP_SERIALIZATION);
+
+	return obj;
+}
+
+struct wlan_ser_vdev_obj *wlan_serialization_get_vdev_obj(
+		struct wlan_objmgr_vdev *vdev)
+{
+	struct wlan_ser_vdev_obj *obj;
+
+	obj = wlan_objmgr_vdev_get_comp_private_obj(
+			vdev, WLAN_UMAC_COMP_SERIALIZATION);
+
+	return obj;
+}
+
+bool wlan_serialization_is_cmd_in_vdev_list(
+		struct wlan_objmgr_vdev *vdev,
+		qdf_list_t *queue,
+		enum wlan_serialization_node node_type)
+{
+	qdf_list_node_t *node = NULL;
+	bool cmd_found = false;
+
+	ser_enter();
+
+	node = wlan_serialization_find_cmd(
+			queue, WLAN_SER_MATCH_VDEV,
+			NULL, 0, NULL, vdev, node_type);
+
+	if (node)
+		cmd_found = true;
+
+	ser_exit();
+	return cmd_found;
+}
+
+bool wlan_serialization_is_cmd_in_pdev_list(
+			struct wlan_objmgr_pdev *pdev,
+			qdf_list_t *queue)
+{
+	qdf_list_node_t *node = NULL;
+	bool cmd_found = false;
+
+	ser_enter();
+
+	node = wlan_serialization_find_cmd(
+			queue, WLAN_SER_MATCH_PDEV,
+			NULL, 0, pdev, NULL,  WLAN_SER_PDEV_NODE);
+
+	if (node)
+		cmd_found = true;
+
+	ser_exit();
+	return cmd_found;
+}
+
+enum wlan_serialization_cmd_status
+wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active,
+					    bool cmd_in_pending)
+{
+	enum wlan_serialization_cmd_status status;
+
+	if (cmd_in_active && cmd_in_pending)
+		status = WLAN_SER_CMDS_IN_ALL_LISTS;
+	else if (cmd_in_active)
+		status = WLAN_SER_CMD_IN_ACTIVE_LIST;
+	else if (cmd_in_pending)
+		status = WLAN_SER_CMD_IN_PENDING_LIST;
+	else
+		status = WLAN_SER_CMD_NOT_FOUND;
+
+	return status;
+}
+
+bool
+wlan_serialization_is_cmd_present_in_given_queue(
+		qdf_list_t *queue,
+		struct wlan_serialization_command *cmd,
+		enum wlan_serialization_node node_type)
+{
+	qdf_list_node_t *node = NULL;
+	bool found = false;
+
+	node = wlan_serialization_find_cmd(
+			queue, WLAN_SER_MATCH_CMD_ID_VDEV,
+			cmd, 0, NULL, cmd->vdev, node_type);
+
+	if (node)
+		found = true;
+
+	return found;
+}
+
+/**
+ * wlan_serialization_remove_cmd_from_queue() - to remove command from
+ *							given queue
+ * @queue: queue from which command needs to be removed
+ * @cmd: command to match in the queue
+ * @ser_pdev_obj: pointer to private pdev serialization object
+ *
+ * This API takes the queue, it matches the provided command from this queue
+ * and removes it. Before removing the command, it will notify the caller
+ * that if it needs to remove any memory allocated by caller.
+ *
+ * Return: none
+ */
+QDF_STATUS
+wlan_serialization_remove_cmd_from_queue(
+		qdf_list_t *queue,
+		struct wlan_serialization_command *cmd,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		enum wlan_serialization_node node_type)
+{
+	struct wlan_serialization_command_list *cmd_list;
+	qdf_list_node_t *node = NULL;
+	QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+	if (!cmd)
+		goto error;
+
+	if (wlan_serialization_list_empty(queue)) {
+		ser_err("Empty queue");
+		goto error;
+	}
+
+	node = wlan_serialization_find_cmd(queue, WLAN_SER_MATCH_CMD_ID_VDEV,
+					   cmd, 0, NULL, cmd->vdev, node_type);
+
+	if (!node)
+		goto error;
+
+	if (node_type == WLAN_SER_PDEV_NODE)
+		cmd_list =
+			qdf_container_of(node,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+	else
+		cmd_list =
+			qdf_container_of(node,
+					 struct wlan_serialization_command_list,
+					 vdev_node);
+
+	ser_debug("Matching command found for removal from queue");
+	ser_debug("remove cmd: type[%d] id[%d] prio[%d] blocking[%d]",
+		  cmd_list->cmd.cmd_type,
+			  cmd_list->cmd.cmd_id,
+			  cmd_list->cmd.is_high_priority,
+			  cmd_list->cmd.is_blocking);
+
+	status = wlan_serialization_remove_node(queue, node);
+
+	if (QDF_STATUS_SUCCESS != status)
+		ser_err("Fail to add to free pool type[%d]",
+			cmd->cmd_type);
+
+	*pcmd_list = cmd_list;
+
+error:
+	return status;
+}
+
+enum wlan_serialization_status
+wlan_serialization_add_cmd_to_queue(
+		qdf_list_t *queue,
+		struct wlan_serialization_command_list *cmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		uint8_t is_cmd_for_active_queue,
+		enum wlan_serialization_node node_type)
+{
+	enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
+	QDF_STATUS qdf_status;
+	qdf_list_node_t *node;
+
+	if (!cmd_list || !queue || !ser_pdev_obj) {
+		ser_err("Input arguments are not valid");
+		goto error;
+	}
+
+	if (node_type == WLAN_SER_PDEV_NODE) {
+		node = &cmd_list->pdev_node;
+		ser_debug("pdev_queue: %pK", queue);
+	} else {
+		node = &cmd_list->vdev_node;
+		ser_debug("vdev_queue: %pK", queue);
+	}
+
+	ser_debug("add cmd: type[%d] id[%d] high_priority[%d] blocking[%d]",
+		  cmd_list->cmd.cmd_type,
+		  cmd_list->cmd.cmd_id,
+		  cmd_list->cmd.is_high_priority,
+		  cmd_list->cmd.is_blocking);
+
+	if (qdf_list_size(queue) == qdf_list_max_size(queue)) {
+		status = WLAN_SER_CMD_DENIED_LIST_FULL;
+		goto error;
+	}
+
+	if (cmd_list->cmd.is_high_priority)
+		qdf_status = wlan_serialization_insert_front(queue, node);
+	else
+		qdf_status = wlan_serialization_insert_back(queue, node);
+
+	if (QDF_IS_STATUS_ERROR(qdf_status))
+		goto error;
+
+	ser_debug("adding cmd to node: %pK", node);
+
+	if (is_cmd_for_active_queue)
+		status = WLAN_SER_CMD_ACTIVE;
+	else
+		status = WLAN_SER_CMD_PENDING;
+
+error:
+	return status;
+}
+
+bool wlan_serialization_list_empty(qdf_list_t *queue)
+{
+	bool is_empty;
+
+	if (qdf_list_empty(queue))
+		is_empty = true;
+	else
+		is_empty = false;
+
+	return is_empty;
+}
+
+uint32_t wlan_serialization_list_size(qdf_list_t *queue)
+{
+	uint32_t size;
+
+	size = qdf_list_size(queue);
+
+	return size;
+}
+
+QDF_STATUS wlan_serialization_remove_front(qdf_list_t *list,
+					   qdf_list_node_t **node)
+{
+	QDF_STATUS status;
+
+	if (wlan_serialization_list_empty(list)) {
+		ser_err("The list is empty");
+		status = QDF_STATUS_E_EMPTY;
+		goto error;
+	}
+
+	status = qdf_list_remove_front(list, node);
+error:
+	return status;
+}
+
+QDF_STATUS wlan_serialization_remove_node(qdf_list_t *list,
+					  qdf_list_node_t *node)
+{
+	QDF_STATUS status;
+
+	if (wlan_serialization_list_empty(list)) {
+		ser_err("The list is empty");
+		status = QDF_STATUS_E_EMPTY;
+		goto error;
+	}
+	status = qdf_list_remove_node(list, node);
+
+error:
+	return status;
+}
+
+QDF_STATUS wlan_serialization_insert_front(qdf_list_t *list,
+					   qdf_list_node_t *node)
+{
+	QDF_STATUS status;
+
+	status = qdf_list_insert_front(list, node);
+
+	return status;
+}
+
+QDF_STATUS wlan_serialization_insert_back(qdf_list_t *list,
+					  qdf_list_node_t *node)
+{
+	QDF_STATUS status;
+
+	status = qdf_list_insert_back(list, node);
+
+	return status;
+}
+
+QDF_STATUS wlan_serialization_peek_front(qdf_list_t *list,
+					 qdf_list_node_t **node)
+{
+	QDF_STATUS status;
+
+	status = qdf_list_peek_front(list, node);
+
+	return status;
+}
+
+QDF_STATUS wlan_serialization_peek_next(qdf_list_t *list,
+					qdf_list_node_t *node1,
+					qdf_list_node_t **node2)
+{
+	QDF_STATUS status;
+
+	status = qdf_list_peek_next(list, node1, node2);
+
+	return status;
+}
+
+bool
+wlan_serialization_match_cmd_type(qdf_list_node_t *nnode,
+				  enum wlan_serialization_cmd_type cmd_type,
+				  enum wlan_serialization_node node_type)
+{
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	bool match_found = true;
+
+	if (node_type == WLAN_SER_PDEV_NODE)
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+	else
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 vdev_node);
+
+	if (cmd_list->cmd.cmd_type != cmd_type)
+		match_found = false;
+
+	return match_found;
+}
+
+bool
+wlan_serialization_match_cmd_id_type(qdf_list_node_t *nnode,
+				     struct wlan_serialization_command *cmd,
+				     enum wlan_serialization_node node_type)
+{
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	bool match_found = true;
+
+	if (!cmd) {
+		match_found = false;
+		goto error;
+	}
+
+	if (node_type == WLAN_SER_PDEV_NODE)
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+	else
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 vdev_node);
+
+	if ((cmd_list->cmd.cmd_id != cmd->cmd_id) ||
+	    (cmd_list->cmd.cmd_type != cmd->cmd_type)) {
+		match_found = false;
+	};
+
+error:
+	return match_found;
+}
+
+bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode,
+				       struct wlan_objmgr_vdev *vdev,
+				       enum wlan_serialization_node node_type)
+{
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	bool match_found = false;
+
+	if (node_type == WLAN_SER_PDEV_NODE)
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+	else
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 vdev_node);
+
+	if (cmd_list->cmd.vdev == vdev)
+		match_found = true;
+
+	ser_debug("matching cmd found(vdev:%pK): %d", vdev, match_found);
+	return match_found;
+}
+
+bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode,
+				       struct wlan_objmgr_pdev *pdev,
+				       enum wlan_serialization_node node_type)
+{
+	struct wlan_serialization_command_list *cmd_list = NULL;
+	bool match_found = false;
+	struct wlan_objmgr_pdev *node_pdev = NULL;
+
+	if (node_type == WLAN_SER_PDEV_NODE)
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 pdev_node);
+	else
+		cmd_list =
+			qdf_container_of(nnode,
+					 struct wlan_serialization_command_list,
+					 vdev_node);
+
+	node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev);
+	if (node_pdev == pdev)
+		match_found = true;
+
+	return match_found;
+}
+
+qdf_list_node_t *
+wlan_serialization_find_cmd(qdf_list_t *queue,
+			    enum wlan_serialization_match_type match_type,
+			    struct wlan_serialization_command *cmd,
+			    enum wlan_serialization_cmd_type cmd_type,
+			    struct wlan_objmgr_pdev *pdev,
+			    struct wlan_objmgr_vdev *vdev,
+			    enum wlan_serialization_node node_type)
+{
+	qdf_list_node_t *cmd_node = NULL;
+	uint32_t queuelen;
+	qdf_list_node_t *nnode = NULL;
+	QDF_STATUS status;
+	bool node_found = 0;
+
+	queuelen = wlan_serialization_list_size(queue);
+
+	if (!queuelen) {
+		ser_debug("queue empty");
+		goto error;
+	}
+
+	while (queuelen--) {
+		status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
+		if (status != QDF_STATUS_SUCCESS)
+			break;
+
+		switch (match_type) {
+		case WLAN_SER_MATCH_PDEV:
+			if (wlan_serialization_match_cmd_pdev(
+					nnode, pdev, WLAN_SER_PDEV_NODE))
+				node_found = 1;
+			break;
+		case WLAN_SER_MATCH_VDEV:
+			if (wlan_serialization_match_cmd_vdev(
+					nnode, vdev, node_type))
+				node_found = 1;
+			break;
+		case WLAN_SER_MATCH_CMD_TYPE:
+			if (wlan_serialization_match_cmd_type(
+					nnode, cmd_type, node_type))
+				node_found = 1;
+			break;
+		case WLAN_SER_MATCH_CMD_ID:
+			if (wlan_serialization_match_cmd_id_type(
+					nnode, cmd, node_type))
+				node_found = 1;
+			break;
+		case WLAN_SER_MATCH_CMD_TYPE_VDEV:
+			if (wlan_serialization_match_cmd_type(
+					nnode, cmd_type, node_type) &&
+			    wlan_serialization_match_cmd_vdev(
+					nnode, vdev, node_type))
+				node_found = 1;
+			break;
+		case WLAN_SER_MATCH_CMD_ID_VDEV:
+			if (wlan_serialization_match_cmd_id_type(
+					nnode, cmd, node_type) &&
+			    wlan_serialization_match_cmd_vdev(
+					nnode, vdev, node_type))
+				node_found = 1;
+			break;
+		default:
+			break;
+		}
+
+		if (node_found) {
+			cmd_node = nnode;
+			break;
+		}
+	}
+error:
+	return cmd_node;
+}
+
+QDF_STATUS
+wlan_serialization_acquire_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	if (!pdev_queue) {
+		ser_err("invalid object");
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spin_lock_bh(&pdev_queue->pdev_queue_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_serialization_release_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	if (!pdev_queue) {
+		ser_err("invalid object");
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spin_unlock_bh(&pdev_queue->pdev_queue_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_serialization_create_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	if (!pdev_queue) {
+		ser_err("invalid object");
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spinlock_create(&pdev_queue->pdev_queue_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+wlan_serialization_destroy_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue)
+{
+	if (!pdev_queue) {
+		ser_err("invalid object");
+		return QDF_STATUS_E_FAILURE;
+	}
+	qdf_spinlock_destroy(&pdev_queue->pdev_queue_lock);
+
+	return QDF_STATUS_SUCCESS;
+}
+#endif

+ 627 - 0
umac/cmn_services/serialization/src/wlan_serialization_utils_i.h

@@ -22,6 +22,8 @@
  */
 #ifndef __WLAN_SERIALIZATION_UTILS_I_H
 #define __WLAN_SERIALIZATION_UTILS_I_H
+
+#ifdef CONFIG_SERIALIZATION_V1
 /* Include files */
 #include "qdf_status.h"
 #include "qdf_list.h"
@@ -613,4 +615,629 @@ QDF_STATUS wlan_serialization_peek_next(
 			qdf_list_node_t *node1,
 			qdf_list_node_t **node2,
 			struct wlan_serialization_pdev_priv_obj *ser_pdev_obj);
+#else /*New serialization code*/
+/* Include files */
+#include <qdf_status.h>
+#include <qdf_list.h>
+#include <qdf_mc_timer.h>
+#include <wlan_objmgr_cmn.h>
+#include <wlan_objmgr_global_obj.h>
+#include <wlan_objmgr_psoc_obj.h>
+#include <wlan_scan_ucfg_api.h>
+#include "wlan_serialization_rules_i.h"
+
+/*
+ * Below bit positions are used to identify if a
+ * serialization command is in use or marked for
+ * deletion.
+ * CMD_MARKED_FOR_ACTIVATION - The command is about to be activated
+ * CMD_IS_ACTIVE - The command is active and currently in use
+ */
+#define CMD_MARKED_FOR_ACTIVATION 1
+#define CMD_IS_ACTIVE             2
+/**
+ * struct wlan_serialization_timer - Timer used for serialization
+ * @cmd:      Cmd to which the timer is linked
+ * @timer:    Timer associated with the command
+ *
+ * Timers are allocated statically during init, one each for the
+ * maximum active commands permitted in the system. Once a cmd is
+ * moved from pending list to active list, the timer is activated
+ * and once the cmd is completed, the timer is cancelled. Timer is
+ * also cancelled if the command is aborted
+ *
+ * The timers are maintained per psoc. A timer is associated to
+ * unique combination of pdev, cmd_type and cmd_id.
+ */
+struct wlan_serialization_timer {
+	struct wlan_serialization_command *cmd;
+	qdf_timer_t timer;
+};
+
+/**
+ * enum wlan_serialization_node - Types of available nodes in serialization list
+ * @WLAN_SER_PDEV_NODE: pdev node from the pdev queue
+ * @WLAN_SER_VDEV_NODE: vdev node from the vdev queue
+ */
+enum wlan_serialization_node {
+	WLAN_SER_PDEV_NODE,
+	WLAN_SER_VDEV_NODE,
+};
+
+/**
+ * struct wlan_serialization_command_list - List of commands to be serialized
+ * @pdev_node: PDEV node identifier in the list
+ * @vdev_node: VDEV node identifier in the list
+ * @cmd: Command to be serialized
+ * @cmd_in_use: flag to check if the node/entry is logically active
+ */
+struct wlan_serialization_command_list {
+	qdf_list_node_t pdev_node;
+	qdf_list_node_t vdev_node;
+	struct wlan_serialization_command cmd;
+	unsigned long cmd_in_use;
+};
+
+/**
+ * struct wlan_serialization_pdev_queue - queue data related to pdev
+ * @active_list: list to hold the commands currently being executed
+ * @pending_list: list to hold the commands currently pending
+ * @cmd_pool_list: list to hold the global command pool
+ * @vdev_active_cmd_bitmap: Active cmd bitmap of vdev for the given pdev
+ * @blocking_cmd_active: Indicate if a blocking cmd is in active execution
+ * @blocking_cmd_waiting: Indicate if a blocking cmd is in pending queue
+ * @pdev_queue_lock: pdev lock to protect concurrent operations on the queues
+ */
+struct wlan_serialization_pdev_queue {
+	qdf_list_t active_list;
+	qdf_list_t pending_list;
+	qdf_list_t cmd_pool_list;
+	uint32_t vdev_active_cmd_bitmap;
+	bool blocking_cmd_active;
+	uint16_t blocking_cmd_waiting;
+	qdf_spinlock_t pdev_queue_lock;
+};
+
+/**
+ * struct wlan_serialization_vdev_queue - queue data related to vdev
+ * @active_list: list to hold the commands currently being executed
+ * @pending_list list: to hold the commands currently pending
+ */
+struct wlan_serialization_vdev_queue {
+	qdf_list_t active_list;
+	qdf_list_t pending_list;
+};
+
+/**
+ * enum wlan_serialization_pdev_queue_type - Types of available pdev queues
+ * @QUEUE_COMP_SCAN: Scan queue
+ * @QUEUE_COMP_NON_SCAN: Non Scan queue
+ */
+enum serialization_pdev_queue_type {
+	SER_PDEV_QUEUE_COMP_SCAN,
+	SER_PDEV_QUEUE_COMP_NON_SCAN,
+	SER_PDEV_QUEUE_COMP_MAX,
+};
+
+/**
+ * enum wlan_serialization_vdev_queue_type - Types of available vdev queues
+ * @QUEUE_COMP_NON_SCAN: Non Scan queue
+ */
+enum serialization_vdev_queue_type {
+	SER_VDEV_QUEUE_COMP_NON_SCAN,
+	SER_VDEV_QUEUE_COMP_MAX,
+};
+
+/**
+ * enum wlan_serialization_match_type - Comparison options for a command
+ * @WLAN_SER_MATCH_VDEV: Compare vdev
+ * @WLAN_SER_MATCH_PDEV: Compare pdev
+ * @WLAN_SER_MATCH_CMD_TYPE: Compare command type
+ * @WLAN_SER_MATCH_CMD_TYPE_VDEV: Compare command type and vdev
+ * @WLAN_SER_MATCH_CMD_ID: Compare command id
+ * @WLAN_SER_MATCH_CMD_ID_VDEV: Compare command id and vdev
+ */
+enum wlan_serialization_match_type {
+	WLAN_SER_MATCH_VDEV,
+	WLAN_SER_MATCH_PDEV,
+	WLAN_SER_MATCH_CMD_TYPE,
+	WLAN_SER_MATCH_CMD_TYPE_VDEV,
+	WLAN_SER_MATCH_CMD_ID,
+	WLAN_SER_MATCH_CMD_ID_VDEV,
+	WLAN_SER_MATCH_MAX,
+};
+
+/**
+ * struct wlan_ser_pdev_obj - pdev obj data for serialization
+ * @pdev_q: Array of pdev queues
+ */
+struct wlan_ser_pdev_obj {
+	struct wlan_serialization_pdev_queue pdev_q[SER_PDEV_QUEUE_COMP_MAX];
+};
+
+/**
+ * struct wlan_ser_vdev_priv_obj - Serialization private object of vdev
+ * @vdev_q: Array of vdev queues
+ */
+struct wlan_ser_vdev_obj {
+	struct wlan_serialization_vdev_queue vdev_q[SER_VDEV_QUEUE_COMP_MAX];
+};
+
+/**
+ * struct wlan_ser_psoc_obj - psoc obj data for serialization
+ * @comp_info_cb - module level callback
+ * @apply_rules_cb - pointer to apply rules on the cmd
+ * @timers - Timers associated with the active commands
+ * @max_axtive_cmds - Maximum active commands allowed
+ *
+ * Serialization component takes a command as input and checks whether to
+ * allow/deny the command. It will use the module level callback registered
+ * by each component to fetch the information needed to apply the rules.
+ * Once the information is available, the rules callback registered for each
+ * command internally by serialization will be applied to determine the
+ * checkpoint for the command. If allowed, command will be put into active/
+ * pending list and each active command is associated with a timer.
+ */
+struct wlan_ser_psoc_obj {
+	wlan_serialization_comp_info_cb comp_info_cb[
+		WLAN_SER_CMD_MAX][WLAN_UMAC_COMP_ID_MAX];
+	wlan_serialization_apply_rules_cb apply_rules_cb[WLAN_SER_CMD_MAX];
+	struct wlan_serialization_timer *timers;
+	uint8_t max_active_cmds;
+};
+
+/**
+ * wlan_serialization_remove_cmd_from_queue() - to remove command from
+ *							given queue
+ * @queue: queue from which command needs to be removed
+ * @cmd: command to match in the queue
+ * @pcmd_list: Pointer to command list containing the command
+ * @ser_pdev_obj: pointer to private pdev serialization object
+ * @node_type: Pdev node or vdev node
+ *
+ * This API takes the queue, it matches the provided command from this queue
+ * and removes it. Before removing the command, it will notify the caller
+ * that if it needs to remove any memory allocated by caller.
+ *
+ * Return: QDF_STATUS_SUCCESS on success, error code on failure
+ */
+QDF_STATUS
+wlan_serialization_remove_cmd_from_queue(
+		qdf_list_t *queue,
+		struct wlan_serialization_command *cmd,
+		struct wlan_serialization_command_list **pcmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_add_cmd_from_queue() - Add a cmd to
+ *							given queue
+ * @queue: queue from which command needs to be removed
+ * @cmd_list: Pointer to command list containing the command
+ * @ser_pdev_obj: pointer to private pdev serialization object
+ * @is_cmd_for_active_queue: Add cmd to active or pending queue
+ * @node_type: Pdev node or vdev node
+ *
+ * Return: Status of the serialization request
+ */
+enum wlan_serialization_status
+wlan_serialization_add_cmd_to_queue(
+		qdf_list_t *queue,
+		struct wlan_serialization_command_list *cmd_list,
+		struct wlan_ser_pdev_obj *ser_pdev_obj,
+		uint8_t is_cmd_for_active_queue,
+		enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_get_psoc_from_cmd() - get psoc from provided cmd
+ * @cmd: pointer to actual command
+ *
+ * This API will get the pointer to psoc through checking type of cmd
+ *
+ * Return: pointer to psoc
+ */
+struct wlan_objmgr_psoc*
+wlan_serialization_get_psoc_from_cmd(struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_get_pdev_from_cmd() - get pdev from provided cmd
+ * @cmd: pointer to actual command
+ *
+ * This API will get the pointer to pdev through checking type of cmd
+ *
+ * Return: pointer to pdev
+ */
+struct wlan_objmgr_pdev*
+wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_get_vdev_from_cmd() - get vdev from provided cmd
+ * @cmd: pointer to actual command
+ *
+ * This API will get the pointer to vdev through checking type of cmd
+ *
+ * Return: pointer to vdev
+ */
+struct wlan_objmgr_vdev*
+wlan_serialization_get_vdev_from_cmd(struct wlan_serialization_command *cmd);
+
+/**
+ * wlan_serialization_get_cmd_from_queue() - to extract command from given queue
+ * @queue: pointer to queue
+ * @nnode: next node to extract
+ *
+ * This API will try to extract node from queue which is next to prev node. If
+ * no previous node is given then take out the front node of the queue.
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_serialization_get_cmd_from_queue(
+		qdf_list_t *queue, qdf_list_node_t **nnode);
+
+/**
+ * wlan_serialization_stop_timer() - to stop particular timer
+ * @ser_timer: pointer to serialization timer
+ *
+ * This API stops the particular timer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer);
+
+/**
+ * wlan_serialization_cleanup_all_timers() - to clean-up all timers
+ *
+ * @psoc_ser_ob: pointer to serialization psoc private object
+ *
+ * This API is to cleanup all the timers. it can be used when serialization
+ * module is exiting. it will make sure that if timer is running then it will
+ * stop and destroys the timer
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_serialization_cleanup_all_timers(
+	struct wlan_ser_psoc_obj *psoc_ser_ob);
+
+/**
+ * wlan_serialization_validate_cmd() - Validate the command
+ * @comp_id: Component ID
+ * @cmd_type: Command Type
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_serialization_validate_cmd(
+		 enum wlan_umac_comp_id comp_id,
+		 enum wlan_serialization_cmd_type cmd_type);
+
+/**
+ * wlan_serialization_validate_cmd_list() - Validate the command list
+ * @cmd_list: Serialization command list
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_serialization_validate_cmd_list(
+		struct wlan_serialization_command_list *cmd_list);
+
+/**
+ * wlan_serialization_validate_cmdtype() - Validate the command type
+ * @cmd_type: Command Type
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_serialization_validate_cmdtype(
+		 enum wlan_serialization_cmd_type cmd_type);
+
+/**
+ * wlan_serialization_destroy_pdev_list() - Release the pdev cmds and
+ * destroy list
+ * @pdev_queue: Pointer to the pdev queue
+ *
+ * Return: None
+ */
+void wlan_serialization_destroy_pdev_list(
+		struct wlan_serialization_pdev_queue *pdev_queue);
+
+/**
+ * wlan_serialization_destroy_vdev_list() - Release the vdev cmds and
+ * destroy list
+ * @list: List to be destroyed
+ *
+ * Return: None
+ */
+void wlan_serialization_destroy_vdev_list(qdf_list_t *list);
+
+/**
+ * wlan_serialization_get_psoc_obj() - Return the component private obj
+ * @psoc: Pointer to the PSOC object
+ *
+ * Return: Serialization component's PSOC level private data object
+ */
+struct wlan_ser_psoc_obj *wlan_serialization_get_psoc_obj(
+		struct wlan_objmgr_psoc *psoc);
+
+/**
+ * wlan_serialization_get_pdev_obj() - Return the component private obj
+ * @psoc: Pointer to the PDEV object
+ *
+ * Return: Serialization component's PDEV level private data object
+ */
+struct wlan_ser_pdev_obj *wlan_serialization_get_pdev_obj(
+		struct wlan_objmgr_pdev *pdev);
+
+/**
+ * wlan_serialization_get_vdev_obj() - Return the component private obj
+ * @vdev: Pointer to the VDEV object
+ *
+ * Return: Serialization component's VDEV level private data object
+ */
+struct wlan_ser_vdev_obj *wlan_serialization_get_vdev_obj(
+		struct wlan_objmgr_vdev *vdev);
+
+/**
+ * wlan_serialization_is_cmd_in_vdev_list() - Check Node present in VDEV list
+ * @vdev: Pointer to the VDEV object
+ * @queue: Pointer to the qdf_list_t
+ * @node_type: Pdev node or vdev node
+ *
+ * Return: Boolean true or false
+ */
+bool
+wlan_serialization_is_cmd_in_vdev_list(
+		struct wlan_objmgr_vdev *vdev, qdf_list_t *queue,
+		enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_is_cmd_in_pdev_list() - Check Node present in PDEV list
+ * @pdev: Pointer to the PDEV object
+ * @queue: Pointer to the qdf_list_t
+ *
+ * Return: Boolean true or false
+ */
+bool
+wlan_serialization_is_cmd_in_pdev_list(
+		struct wlan_objmgr_pdev *pdev, qdf_list_t *queue);
+
+/**
+ * wlan_serialization_is_cmd_in_active_pending() - return cmd status
+ *						active/pending queue
+ * @cmd_in_active: CMD in active list
+ * @cmd_in_pending: CMD in pending list
+ *
+ * Return: enum wlan_serialization_cmd_status
+ */
+enum wlan_serialization_cmd_status
+wlan_serialization_is_cmd_in_active_pending(
+		bool cmd_in_active, bool cmd_in_pending);
+
+/**
+ * wlan_serialization_is_cmd_present_in_given_queue() - Check if the cmd is
+ * present in the given queue
+ * @queue: List of commands which has to be searched
+ * @cmd: Serialization command information
+ * @node_type: Pdev node or vdev node
+ *
+ * Return: Boolean true or false
+ */
+bool wlan_serialization_is_cmd_present_in_given_queue(
+		qdf_list_t *queue,
+		struct wlan_serialization_command *cmd,
+		enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_timer_destroy() - destroys the timer
+ * @ser_timer: pointer to particular timer
+ *
+ * This API destroys the memory allocated by timer and assigns cmd member of
+ * that timer structure to NULL
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS wlan_serialization_timer_destroy(
+		struct wlan_serialization_timer *ser_timer);
+
+/**
+ * wlan_serialization_list_empty() - check if the list is empty
+ * @queue: Queue/List that needs to be checked for emptiness
+ *
+ * Return: true if list is empty and false otherwise
+ */
+bool wlan_serialization_list_empty(qdf_list_t *queue);
+
+/**
+ * wlan_serialization_list_size() - Find the size of the provided queue
+ * @queue: Queue/List for which the size/length is to be returned
+ *
+ * Return: size/length of the queue/list
+ */
+uint32_t wlan_serialization_list_size(qdf_list_t *queue);
+
+/**
+ * wlan_serialization_match_cmd_type() - Check for a match on given nnode
+ * @nnode: The node on which the matching has to be done
+ * @cmd_type: Command type that needs to be matched
+ * @node_type: Pdev node or vdev node
+ *
+ * This API will check if the cmd ID and cmd type of the given nnode are
+ * matching with the one's that are being passed to this function.
+ *
+ * Return: True if matched,false otherwise.
+ */
+bool wlan_serialization_match_cmd_type(
+			qdf_list_node_t *nnode,
+			enum wlan_serialization_cmd_type,
+			enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_match_cmd_id_type() - Check for a match on given nnode
+ * @nnode: The node on which the matching has to be done
+ * @cmd: Command that needs to be matched
+ * @node_type: Pdev node or vdev node
+ *
+ * This API will check if the cmd ID and cmd type of the given nnode are
+ * matching with the one's that are being passed to this function.
+ *
+ * Return: True if matched,false otherwise.
+ */
+bool wlan_serialization_match_cmd_id_type(
+			qdf_list_node_t *nnode,
+			struct wlan_serialization_command *cmd,
+			enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_match_cmd_vdev() - Check for a match on given nnode
+ * @nnode: The node on which the matching has to be done
+ * @vdev: VDEV object that needs to be matched
+ * @node_type: Pdev node or vdev node
+ *
+ * This API will check if the VDEV object of the given nnode are
+ * matching with the one's that are being passed to this function.
+ *
+ * Return: True if matched,false otherwise.
+ */
+bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode,
+				       struct wlan_objmgr_vdev *vdev,
+				       enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_match_cmd_pdev() - Check for a match on given nnode
+ * @nnode: The node on which the matching has to be done
+ * @pdev: pdev object that needs to be matched
+ * @node_type: Node type. Pdev node or vdev node
+ *
+ * This API will check if the PDEV object of the given nnode are
+ * matching with the one's that are being passed to this function.
+ *
+ * Return: True if matched,false otherwise.
+ */
+bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode,
+				       struct wlan_objmgr_pdev *pdev,
+				       enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_find_cmd() - Find the cmd matching the given criterias
+ * @cmd: Serialization command information
+ * @cmd_type: Command type to be matched
+ * @pdev: pdev object that needs to be matched
+ * @vdev: vdev object that needs to be matched
+ * @node_type: Node type. Pdev node or vdev node
+ *
+ * Return: Pointer to the node member in the list
+ */
+qdf_list_node_t *
+wlan_serialization_find_cmd(qdf_list_t *queue, uint32_t match_type,
+			    struct wlan_serialization_command *cmd,
+			    enum wlan_serialization_cmd_type cmd_type,
+			    struct wlan_objmgr_pdev *pdev,
+			    struct wlan_objmgr_vdev *vdev,
+			    enum wlan_serialization_node node_type);
+
+/**
+ * wlan_serialization_remove_front() - Remove the front node of the list
+ * @list: List from which the node is to be removed
+ * @node: Pointer to store the node that is removed
+ *
+ * Return: QDF_STATUS Success or Failure
+ */
+QDF_STATUS wlan_serialization_remove_front(
+			qdf_list_t *list,
+			qdf_list_node_t **node);
+
+/**
+ * wlan_serialization_remove_node() - Remove the given node from the list
+ * @list: List from which the node is to be removed
+ * @node: Pointer to the node that is to be removed
+ *
+ * Return: QDF_STATUS Success or Failure
+ */
+QDF_STATUS wlan_serialization_remove_node(
+			qdf_list_t *list,
+			qdf_list_node_t *node);
+
+/**
+ * wlan_serialization_insert_front() - Insert a node into the front of the list
+ * @list: List to which the node is to be inserted
+ * @node: Pointer to the node that is to be inserted
+ *
+ * Return: QDF_STATUS Success or Failure
+ */
+QDF_STATUS wlan_serialization_insert_front(
+			qdf_list_t *list,
+			qdf_list_node_t *node);
+
+/**
+ * wlan_serialization_insert_back() - Insert a node into the back of the list
+ * @list: List to which the node is to be inserted
+ * @node: Pointer to the node that is to be inserted
+ *
+ * Return: QDF_STATUS Success or Failure
+ */
+QDF_STATUS wlan_serialization_insert_back(
+			qdf_list_t *list,
+			qdf_list_node_t *node);
+
+/**
+ * wlan_serialization_peek_front() - Peek the front node of the list
+ * @list: List on which the node is to be peeked
+ * @node: Pointer to the store the node that is being peeked
+ *
+ * Return: QDF_STATUS Success or Failure
+ */
+QDF_STATUS wlan_serialization_peek_front(
+			qdf_list_t *list,
+			qdf_list_node_t **node);
+
+/**
+ * wlan_serialization_peek_next() - Peek the next node of the list
+ * @list: List on which the node is to be peeked
+ * @node1: Pointer to the node1 from where the next node has to be peeked
+ * @node2: Pointer to the store the node that is being peeked
+ *
+ * Return: QDF_STATUS Success or Failure
+ */
+QDF_STATUS wlan_serialization_peek_next(
+			qdf_list_t *list,
+			qdf_list_node_t *node1,
+			qdf_list_node_t **node2);
+
+/**
+ * wlan_serialization_acquire_lock() - Acquire lock to the given queue
+ * @pdev_queue: Pointer to the pdev queue
+ *
+ * Return: QDF_STATUS success or failure
+ */
+QDF_STATUS
+wlan_serialization_acquire_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue);
+
+/**
+ * wlan_serialization_release_lock() - Release lock to the given queue
+ * @pdev_queue: Pointer to the pdev queue
+ *
+ * Return: QDF_STATUS success or failure
+ */
+QDF_STATUS
+wlan_serialization_release_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue);
+
+/**
+ * wlan_serialization_create_lock() - Init the lock to the given queue
+ * @pdev_queue: Pointer to the pdev queue
+ *
+ * Return: QDF_STATUS success or failure
+ */
+QDF_STATUS
+wlan_serialization_create_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue);
+
+/**
+ * wlan_serialization_destroy_lock() - Deinit the lock to the given queue
+ * @pdev_queue: Pointer to the pdev queue
+ *
+ * Return: QDF_STATUS success or failure
+ */
+QDF_STATUS
+wlan_serialization_destroy_lock(
+		struct wlan_serialization_pdev_queue *pdev_queue);
+#endif
 #endif