qcacmn: Add API for cancellation of non-blocking cmd

Add API to support cancellation of a non-scan command to match with the
vdev and is a non-blocking serialization command.

Change-Id: I31556ea8f35b9caf314f10eba0f0f655e3fce806
CRs-Fixed: 2481935
diff --git a/umac/cmn_services/serialization/inc/wlan_serialization_api.h b/umac/cmn_services/serialization/inc/wlan_serialization_api.h
index 8002aec..3f4f71b 100644
--- a/umac/cmn_services/serialization/inc/wlan_serialization_api.h
+++ b/umac/cmn_services/serialization/inc/wlan_serialization_api.h
@@ -237,6 +237,8 @@
  * @WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD: Cancel all non scans on a given vdev
  * @WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE: Cancel all non scans on a given vdev
  * and matching cmd type
+ * @WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD: Cancel all non-blocking,
+ * non-scan commands of a given vdev
  * @WLAN_SER_CANCEL_NON_SCAN_CMD: Cancel the given non scan command
  */
 enum wlan_serialization_cancel_type {
@@ -246,6 +248,7 @@
 	WLAN_SER_CANCEL_PDEV_NON_SCAN_CMD,
 	WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD,
 	WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE,
+	WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD,
 	WLAN_SER_CANCEL_NON_SCAN_CMD,
 	WLAN_SER_CANCEL_MAX,
 };
@@ -287,6 +290,18 @@
 };
 
 /**
+ * enum wlan_ser_cmd_attr - Serialization cmd attribute
+ * @WLAN_SER_CMD_ATTR_NONE - No attribuate associated
+ * @WLAN_SER_CMD_ATTR_BLOCK - Blocking attribute
+ * @WLAN_SER_CMD_ATTR_NONBLOCK - Non-blocking attribute
+ */
+enum wlan_ser_cmd_attr {
+	WLAN_SER_CMD_ATTR_NONE,
+	WLAN_SER_CMD_ATTR_BLOCK,
+	WLAN_SER_CMD_ATTR_NONBLOCK,
+};
+
+/**
  * struct wlan_serialization_command - Command to be serialized
  * @wlan_serialization_cmd_type: Type of command
  * @cmd_id: Command Identifier
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_api.c b/umac/cmn_services/serialization/src/wlan_serialization_api.c
index 6c3e72e..d2ad0ca 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_api.c
+++ b/umac/cmn_services/serialization/src/wlan_serialization_api.c
@@ -821,9 +821,11 @@
 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
 				 WLAN_SER_CMD_SCAN, true);
 	wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
-				     WLAN_SER_CMD_NONSCAN, false);
+				     WLAN_SER_CMD_NONSCAN, false,
+				     WLAN_SER_CMD_ATTR_NONE);
 	wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, NULL, NULL,
-				     WLAN_SER_CMD_NONSCAN, true);
+				     WLAN_SER_CMD_NONSCAN, true,
+				     WLAN_SER_CMD_ATTR_NONE);
 }
 
 static inline
@@ -870,7 +872,8 @@
 	wlan_ser_cancel_scan_cmd(ser_pdev_obj, pdev, vdev, NULL,
 				 WLAN_SER_CMD_SCAN, false);
 	wlan_ser_cancel_non_scan_cmd(ser_pdev_obj, pdev, vdev, NULL,
-				     WLAN_SER_CMD_NONSCAN, false);
+				     WLAN_SER_CMD_NONSCAN, false,
+				     WLAN_SER_CMD_ATTR_NONE);
 
 	wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID);
 }
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_internal.c b/umac/cmn_services/serialization/src/wlan_serialization_internal.c
index 56509fb..8319347 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_internal.c
+++ b/umac/cmn_services/serialization/src/wlan_serialization_internal.c
@@ -371,7 +371,8 @@
 		wlan_serialization_cmd_cancel_handler(
 				ser_pdev_obj, &cmd_list->cmd,
 				NULL, NULL, cmd_list->cmd.cmd_type,
-				WLAN_SERIALIZATION_ACTIVE_QUEUE);
+				WLAN_SERIALIZATION_ACTIVE_QUEUE,
+				WLAN_SER_CMD_ATTR_NONE);
 error:
 	return status;
 }
@@ -847,7 +848,8 @@
 		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_type cmd_type, uint8_t queue_type,
+		enum wlan_ser_cmd_attr cmd_attr)
 {
 	enum wlan_serialization_cmd_status active_status =
 		WLAN_SER_CMD_NOT_FOUND;
@@ -871,7 +873,7 @@
 		else
 			active_status = wlan_ser_cancel_non_scan_cmd(
 					ser_obj, pdev, vdev, cmd,
-					cmd_type, true);
+					cmd_type, true, cmd_attr);
 	}
 
 	if (queue_type & WLAN_SERIALIZATION_PENDING_QUEUE) {
@@ -882,7 +884,7 @@
 		else
 			pending_status = wlan_ser_cancel_non_scan_cmd(
 					ser_obj, pdev, vdev, cmd,
-					cmd_type, false);
+					cmd_type, false, cmd_attr);
 	}
 
 	if (active_status == WLAN_SER_CMD_IN_ACTIVE_LIST &&
@@ -931,37 +933,43 @@
 		/* remove scan cmd which matches the given cmd struct */
 		status = wlan_serialization_cmd_cancel_handler(
 				ser_obj, cmd, NULL, NULL,
-				WLAN_SER_CMD_SCAN, queue_type);
+				WLAN_SER_CMD_SCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
 		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, pdev, NULL,
-				WLAN_SER_CMD_SCAN, queue_type);
+				WLAN_SER_CMD_SCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
 		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,
-				WLAN_SER_CMD_SCAN, queue_type);
+				WLAN_SER_CMD_SCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
 		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,
-				WLAN_SER_CMD_NONSCAN, queue_type);
+				WLAN_SER_CMD_NONSCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
 		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, pdev, NULL,
-				WLAN_SER_CMD_NONSCAN, queue_type);
+				WLAN_SER_CMD_NONSCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
 		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,
-				WLAN_SER_CMD_NONSCAN, queue_type);
+				WLAN_SER_CMD_NONSCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
 		break;
 	case WLAN_SER_CANCEL_VDEV_NON_SCAN_CMD_TYPE:
 		/*
@@ -970,7 +978,18 @@
 		 */
 		status = wlan_serialization_cmd_cancel_handler(
 				ser_obj, NULL, NULL, cmd->vdev,
-				cmd->cmd_type, queue_type);
+				cmd->cmd_type, queue_type,
+				WLAN_SER_CMD_ATTR_NONE);
+		break;
+	case WLAN_SER_CANCEL_VDEV_NON_SCAN_NB_CMD:
+		/*
+		 * remove all non-blocking non-scan cmds which matches the given
+		 * vdev
+		 */
+		status = wlan_serialization_cmd_cancel_handler(
+				ser_obj, NULL, NULL, cmd->vdev,
+				WLAN_SER_CMD_NONSCAN, queue_type,
+				WLAN_SER_CMD_ATTR_NONBLOCK);
 		break;
 	default:
 		ser_err("Invalid request");
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h b/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h
index 2e2e724..1dfd8b7 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h
+++ b/umac/cmn_services/serialization/src/wlan_serialization_internal_i.h
@@ -205,6 +205,7 @@
  * @vdev: pointer to vdev
  * @cmd_type: pointer to cmd_type
  * @queue_type: If active queue or pending queue
+ * @cmd_attr: Attrbute to indicate a blocking or a non-blocking command
  *
  * This API will decide from which queue, command needs to be cancelled
  * and pass that queue and other parameter required to cancel the command
@@ -219,5 +220,6 @@
 				      struct wlan_objmgr_pdev *pdev,
 				      struct wlan_objmgr_vdev *vdev,
 				      enum wlan_serialization_cmd_type cmd_type,
-				      uint8_t queue_type);
+				      uint8_t queue_type,
+				      enum wlan_ser_cmd_attr cmd_attr);
 #endif
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c b/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c
index 4aabd72..e451eda 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c
+++ b/umac/cmn_services/serialization/src/wlan_serialization_non_scan.c
@@ -461,7 +461,7 @@
 		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)
+		uint8_t is_active_queue, enum wlan_ser_cmd_attr cmd_attr)
 {
 	qdf_list_t *pdev_queue;
 	qdf_list_t *vdev_queue;
@@ -541,6 +541,18 @@
 		}
 
 		/*
+		 * If a non-blocking cmd is required to be cancelled, but
+		 * the nnode cmd is a blocking cmd then continue with the
+		 * next command in the list else proceed with cmd cancel.
+		 */
+		if ((cmd_attr == WLAN_SER_CMD_ATTR_NONBLOCK) &&
+		    wlan_serialization_match_cmd_blocking(nnode,
+							  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
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h b/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h
index 5426ae4..d52402b 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h
+++ b/umac/cmn_services/serialization/src/wlan_serialization_non_scan_i.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2019 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
@@ -115,6 +115,8 @@
  * @cmd_type: Serialization command type to be cancelled
  * @is_active_queue: If the cmd has to be removed from active queue or pending
  *			queue
+ * @cmd_attr: Indicate the attribute of the cmd to be cancelled
+ *      i.e blocking/non-blocking
  *
  * Return: Status specifying the cancel of a command from the given queue
  */
@@ -124,5 +126,6 @@
 			     struct wlan_objmgr_vdev *vdev,
 			     struct wlan_serialization_command *cmd,
 			     enum wlan_serialization_cmd_type cmd_type,
-			     uint8_t is_active_queue);
+			     uint8_t is_active_queue,
+			     enum wlan_ser_cmd_attr cmd_attr);
 #endif
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_utils.c b/umac/cmn_services/serialization/src/wlan_serialization_utils.c
index 1f636ab..8395ec5 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_utils.c
+++ b/umac/cmn_services/serialization/src/wlan_serialization_utils.c
@@ -775,6 +775,30 @@
 	return match_found;
 }
 
+bool wlan_serialization_match_cmd_blocking(
+		qdf_list_node_t *nnode,
+		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.is_blocking)
+		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,
diff --git a/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h b/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h
index d068122..6b9c82f 100644
--- a/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h
+++ b/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h
@@ -547,6 +547,19 @@
 				       enum wlan_serialization_node node_type);
 
 /**
+ * wlan_serialization_match_cmd_blocking() - Check for a blocking cmd
+ * @nnode: The node on which the matching has to be done
+ * @node_type: Pdev node or vdev node
+ *
+ * This API will check if the give command of nnode is a blocking command.
+ *
+ * Return: True if blocking command, false otherwise.
+ */
+bool wlan_serialization_match_cmd_blocking(
+		qdf_list_node_t *nnode,
+		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