diff --git a/umac/cmn_services/serialization/inc/wlan_serialization_api.h b/umac/cmn_services/serialization/inc/wlan_serialization_api.h index f8430fe9c253..8cec6fbe7a52 100644 --- a/umac/cmn_services/serialization/inc/wlan_serialization_api.h +++ b/umac/cmn_services/serialization/inc/wlan_serialization_api.h @@ -661,6 +661,7 @@ enum wlan_serialization_cancel_type { * @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_QUEUE_DISABLED: Command denied as the queue is disabled * @WLAN_SER_CMD_DENIED_UNSPECIFIED: Command denied due to unknown reason */ enum wlan_serialization_status { @@ -668,6 +669,7 @@ enum wlan_serialization_status { WLAN_SER_CMD_ACTIVE, WLAN_SER_CMD_DENIED_RULES_FAILED, WLAN_SER_CMD_DENIED_LIST_FULL, + WLAN_SER_CMD_QUEUE_DISABLED, WLAN_SER_CMD_DENIED_UNSPECIFIED, }; @@ -694,6 +696,8 @@ enum wlan_serialization_cmd_status { * @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 + * @is_blocking: Is the command blocking + * @queue_disable: Should the command disable the queues * @cmd_timeout_cb: Command timeout callback * @cmd_timeout_duration: Timeout duration in milliseconds * @vdev: VDEV object associated to the command @@ -710,6 +714,7 @@ struct wlan_serialization_command { enum wlan_umac_comp_id source; bool is_high_priority; bool is_blocking; + bool queue_disable; uint16_t cmd_timeout_duration; union { struct wlan_objmgr_vdev *vdev; diff --git a/umac/cmn_services/serialization/src/wlan_serialization_internal.c b/umac/cmn_services/serialization/src/wlan_serialization_internal.c index f4eeb83171e0..7797fda6a65b 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_internal.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_internal.c @@ -95,6 +95,8 @@ wlan_serialization_enqueue_cmd(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; + struct wlan_ser_vdev_obj *ser_vdev_obj; + struct wlan_serialization_vdev_queue *vdev_queue; bool active_queue; /* Enqueue process @@ -167,6 +169,53 @@ wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd, wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); + /* Before queuing any non scan command, + * as part of wlan_serialization_request, + * we check if the vdev queues are disabled. + * + * The serialization command structure has an + * attribute, where after a given command is queued, + * we can block the vdev queues. + * + * For example, after VDEV_DOWN command is queued as + * part of a vdev deletion, no other commands should be queued + * until the deletion is complete, so with VDEV_DOWN(in case of + * vdev deletion) with pass the attribute to disable vdev queues + */ + if (cmd->cmd_type > WLAN_SER_CMD_SCAN && + ser_reason == SER_REQUEST) { + ser_vdev_obj = + wlan_serialization_get_vdev_obj( + wlan_serialization_get_vdev_from_cmd(cmd)); + + if (!ser_vdev_obj) { + wlan_serialization_release_lock( + &pdev_queue->pdev_queue_lock); + goto error; + } + + vdev_queue = + wlan_serialization_get_vdev_queue_obj( + ser_vdev_obj, + cmd->cmd_type); + + if (!vdev_queue) { + wlan_serialization_release_lock( + &pdev_queue->pdev_queue_lock); + goto error; + } + + if (vdev_queue->queue_disable) { + wlan_serialization_release_lock( + &pdev_queue->pdev_queue_lock); + ser_err("VDEV queue is disabled, ser request denied"); + ser_err("cmd id[%d] cmd type[%d]", cmd->cmd_id, + cmd->cmd_type); + status = WLAN_SER_CMD_QUEUE_DISABLED; + goto error; + } + } + active_queue = wlan_serialization_is_active_cmd_allowed(cmd); if (wlan_serialization_is_cmd_present_queue(cmd, active_queue)) { diff --git a/umac/cmn_services/serialization/src/wlan_serialization_queue.c b/umac/cmn_services/serialization/src/wlan_serialization_queue.c index 374529b66e38..d4d23679267a 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_queue.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_queue.c @@ -126,12 +126,18 @@ wlan_serialization_add_cmd_to_vdev_queue( enum wlan_serialization_status status; struct wlan_serialization_command *cmd; struct wlan_ser_vdev_obj *vdev_obj; + struct wlan_serialization_vdev_queue *vdev_queue_obj; cmd = &cmd_list->cmd; vdev_obj = wlan_serialization_get_vdev_obj( wlan_serialization_get_vdev_from_cmd(cmd)); + vdev_queue_obj = + wlan_serialization_get_vdev_queue_obj( + vdev_obj, + cmd->cmd_type); + queue = wlan_serialization_get_list_from_vdev_queue(vdev_obj, cmd->cmd_type, for_active_queue); @@ -141,6 +147,9 @@ wlan_serialization_add_cmd_to_vdev_queue( for_active_queue, WLAN_SER_VDEV_NODE); + if (cmd->queue_disable) + vdev_queue_obj->queue_disable = true; + return status; } 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 c4c7623f06c7..af6dd61f1e43 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h +++ b/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h @@ -720,10 +720,12 @@ struct wlan_serialization_pdev_queue { * 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 + * @queue_disable: is the queue disabled */ struct wlan_serialization_vdev_queue { qdf_list_t active_list; qdf_list_t pending_list; + bool queue_disable; }; /**