From 5ebf9cf853b95e1e8e616503d72f923576bef8bd Mon Sep 17 00:00:00 2001 From: Vivek Date: Fri, 27 Mar 2020 20:13:23 +0530 Subject: [PATCH] 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 --- .../src/wlan_serialization_api.c | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/umac/cmn_services/serialization/src/wlan_serialization_api.c b/umac/cmn_services/serialization/src/wlan_serialization_api.c index 6cf61b7cf3cb..1fb6f52163b0 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_api.c +++ b/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; }