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

qcacmn: Check if cmd present in serialization queue atomically

The current API to get if a command is present in the active
queue was executed without the lock acquired. Here, at times
we get the queue size as one, and when we actually get the command
from the active queue, we get nothing.

This could be that the command from the active queue was removed
in another context almost at the same time, when we trying to read
the command from the active queue.

To avoid this, we do the operation of reading the queue size and
reading from the active queue with the queue locks held, so no
other context could remove the command from the active queue while
we are reading the command from the active queue.

CRs-Fixed: 2644038
Change-Id: Icca019320b1ba2d7d751432142b9bad50519d701
Vivek 5 жил өмнө
parent
commit
5ebf9cf853

+ 52 - 2
umac/cmn_services/serialization/src/wlan_serialization_api.c

@@ -37,14 +37,39 @@ bool wlan_serialization_is_cmd_present_in_pending_queue(
 		struct wlan_serialization_command *cmd)
 {
 	bool status = false;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_pdev_queue *pdev_queue;
 
 	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_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+	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;
+	}
+
+	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
+
 	status = wlan_serialization_is_cmd_present_queue(cmd, false);
 
+	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
 error:
 	return status;
 }
@@ -53,16 +78,41 @@ bool wlan_serialization_is_cmd_present_in_active_queue(
 		struct wlan_objmgr_psoc *psoc,
 		struct wlan_serialization_command *cmd)
 {
-	bool status;
+	bool status = false;
+	struct wlan_objmgr_pdev *pdev;
+	struct wlan_ser_pdev_obj *ser_pdev_obj;
+	struct wlan_serialization_pdev_queue *pdev_queue;
 
 	if (!cmd) {
 		ser_err("invalid cmd");
-		status = false;
 		goto error;
 	}
 
+	pdev = wlan_serialization_get_pdev_from_cmd(cmd);
+	if (!pdev) {
+		ser_err("invalid pdev");
+		goto error;
+	}
+
+	ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev);
+	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;
+	}
+
+	wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock);
+
 	status = wlan_serialization_is_cmd_present_queue(cmd, true);
 
+	wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock);
+
 error:
 	return status;
 }