diff --git a/umac/cmn_services/serialization/src/wlan_serialization_api.c b/umac/cmn_services/serialization/src/wlan_serialization_api.c index 253c994e0295..a5cfd45e2d30 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_api.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_api.c @@ -222,7 +222,7 @@ wlan_serialization_request(struct wlan_serialization_command *cmd) return WLAN_SER_CMD_DENIED_UNSPECIFIED; } - ser_soc_obj = wlan_serialization_get_obj(cmd); + ser_soc_obj = wlan_serialization_get_psoc_obj(cmd); if (!ser_soc_obj) { serialization_err("ser_soc_obj is invalid"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; @@ -260,6 +260,7 @@ wlan_serialization_request(struct wlan_serialization_command *cmd) cmd, is_active_cmd_allowed, &cmd_list); if (WLAN_SER_CMD_ACTIVE == serialization_status) wlan_serialization_activate_cmd(cmd_list, ser_pdev_obj); + return serialization_status; } @@ -320,7 +321,6 @@ wlan_serialization_get_scan_cmd_using_scan_id( struct wlan_objmgr_vdev *vdev; struct wlan_objmgr_pdev *pdev; struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; - struct wlan_serialization_command_list *cmd_list = NULL; struct wlan_serialization_command *cmd = NULL; qdf_list_node_t *nnode = NULL; qdf_list_t *queue; @@ -351,28 +351,22 @@ wlan_serialization_get_scan_cmd_using_scan_id( queue = &ser_pdev_obj->active_scan_list; else queue = &ser_pdev_obj->pending_scan_list; - qlen = qdf_list_size(queue); - if (!qlen) { - serialization_err("Empty Queue"); - goto release_vdev_ref; - } + qlen = wlan_serialization_list_size(queue, ser_pdev_obj); while (qlen--) { if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( - queue, &nnode)) { - serialization_err("unsuccessful attempt"); + queue, &nnode, ser_pdev_obj)) { + serialization_debug("Node not found"); break; } - cmd_list = qdf_container_of(nnode, - struct wlan_serialization_command_list, node); - if ((cmd_list->cmd.cmd_id == scan_id) && - (cmd_list->cmd.vdev == vdev)) { - serialization_debug("cmd_id[%d] matched", scan_id); - cmd = &cmd_list->cmd; + if (wlan_serialization_match_cmd_scan_id(nnode, &cmd, scan_id, + vdev, ser_pdev_obj)) { + serialization_debug("Cmd matched with the scan_id"); break; } } release_vdev_ref: wlan_objmgr_vdev_release_ref(vdev, WLAN_SERIALIZATION_ID); + return cmd; } @@ -421,7 +415,8 @@ void *wlan_serialization_get_active_cmd(struct wlan_objmgr_psoc *psoc, } while (qlen--) { if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( - queue, &nnode)) { + queue, &nnode, + ser_pdev_obj)) { serialization_err("unsuccessful attempt"); break; } diff --git a/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c b/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c index 79c8e4a07b0e..15935b392fc3 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_dequeue.c @@ -27,6 +27,7 @@ #include #include #include +#include void wlan_serialization_move_pending_to_active( enum wlan_serialization_cmd_type cmd_type, @@ -37,6 +38,7 @@ void wlan_serialization_move_pending_to_active( struct wlan_serialization_command_list *active_cmd_list = NULL; enum wlan_serialization_status status; qdf_list_node_t *nnode = NULL; + QDF_STATUS list_peek_status; if (!ser_pdev_obj) { serialization_err("Can't find ser_pdev_obj"); @@ -47,13 +49,14 @@ void wlan_serialization_move_pending_to_active( pending_queue = &ser_pdev_obj->pending_scan_list; else pending_queue = &ser_pdev_obj->pending_list; - - if (qdf_list_empty(pending_queue)) { + if (wlan_serialization_list_empty(pending_queue, ser_pdev_obj)) { serialization_debug("nothing to move from pend to active que"); serialization_debug("cmd_type - %d", cmd_type); return; } - if (QDF_STATUS_SUCCESS != qdf_list_peek_front(pending_queue, &nnode)) { + list_peek_status = wlan_serialization_peek_front(pending_queue, &nnode, + ser_pdev_obj); + if (QDF_STATUS_SUCCESS != list_peek_status) { serialization_err("can't read from pending queue"); serialization_debug("cmd_type - %d", cmd_type); return; @@ -77,8 +80,23 @@ void wlan_serialization_move_pending_to_active( cmd_list->cmd.cmd_id, cmd_list->cmd.cmd_type); return; } else { - wlan_serialization_put_back_to_global_list(pending_queue, - ser_pdev_obj, cmd_list); + /* + * Before removing the cmd from pending list and putting it + * back in the global list, check if someone has already + * deleted it. if so, do not do it again. if not, continue with + * removing the node. if the CMD_MARKED_FOR_DELETE is + * cleared after deletion, then inside the below API, + * it is checked if the command is active and in use or + * not before removing. + */ + if (!qdf_atomic_test_and_set_bit(CMD_MARKED_FOR_DELETE, + &cmd_list->cmd_in_use)) { + serialization_debug("SER_CMD marked for removal"); + wlan_serialization_put_back_to_global_list( + pending_queue, ser_pdev_obj, cmd_list); + } else { + serialization_debug("SER_CMD already being deleted"); + } wlan_serialization_activate_cmd(active_cmd_list, ser_pdev_obj); } @@ -93,7 +111,7 @@ wlan_serialization_remove_all_cmd_from_queue(qdf_list_t *queue, struct wlan_serialization_command *cmd, uint8_t is_active_queue) { uint32_t qsize; - struct wlan_serialization_command_list *cmd_list; + struct wlan_serialization_command_list *cmd_list = NULL; 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; @@ -108,25 +126,31 @@ wlan_serialization_remove_all_cmd_from_queue(qdf_list_t *queue, else serialization_debug("Can't find psoc"); - qsize = qdf_list_size(queue); - while (qsize--) { - if (wlan_serialization_get_cmd_from_queue(queue, &nnode) - != QDF_STATUS_SUCCESS) { + qsize = wlan_serialization_list_size(queue, ser_pdev_obj); + while (!wlan_serialization_list_empty(queue, ser_pdev_obj) && qsize--) { + if (wlan_serialization_get_cmd_from_queue( + queue, &nnode, + ser_pdev_obj) != QDF_STATUS_SUCCESS) { serialization_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, node); - if ((cmd && ((cmd->cmd_id != cmd_list->cmd.cmd_id) || - (cmd->cmd_type != cmd_list->cmd.cmd_type))) || - (vdev && (vdev != cmd_list->cmd.vdev)) || - (pdev && (pdev != wlan_vdev_get_pdev( - cmd_list->cmd.vdev)))) { + if (cmd && !wlan_serialization_match_cmd_id_type( + nnode, cmd, + ser_pdev_obj)) { + pnode = nnode; + continue; + } + if (vdev && !wlan_serialization_match_cmd_vdev(nnode, vdev)) { + pnode = nnode; + continue; + } + if (pdev && !wlan_serialization_match_cmd_pdev(nnode, pdev)) { pnode = nnode; continue; } - /* * active queue can't be removed directly, requester needs to * wait for active command response and send remove request for @@ -148,6 +172,24 @@ wlan_serialization_remove_all_cmd_from_queue(qdf_list_t *queue, } status = WLAN_SER_CMD_IN_ACTIVE_LIST; } + /* + * There is a possiblity that the cmd cleanup may happen + * in different contexts at the same time. + * e.g: ifconfig down coming in ioctl context and command + * complete event being handled in scheduler thread context. + * In such scenario's check if either of the threads have + * marked the command for delete and then proceed further + * with cleanup. if it is already marked for cleanup, then + * there is no need to proceed since the other thread is + * cleaning it up. + */ + if (qdf_atomic_test_and_set_bit(CMD_MARKED_FOR_DELETE, + &cmd_list->cmd_in_use)) { + serialization_debug("SER_CMD already being deleted"); + status = WLAN_SER_CMD_NOT_FOUND; + break; + } + serialization_debug("SER_CMD marked for removal"); /* * call pending cmd's callback to notify that * it is being removed @@ -202,10 +244,10 @@ static void wlan_serialization_remove_cmd_from_given_queue(qdf_list_t *queue, if (!cmd) return; - qsize = qdf_list_size(queue); - + qsize = wlan_serialization_list_size(queue, ser_pdev_obj); while (qsize--) { - status = wlan_serialization_get_cmd_from_queue(queue, &nnode); + status = wlan_serialization_get_cmd_from_queue(queue, &nnode, + ser_pdev_obj); if (status != QDF_STATUS_SUCCESS) { serialization_err("can't peek cmd_id[%d] type[%d]", cmd->cmd_id, cmd->cmd_type); @@ -213,11 +255,23 @@ static void wlan_serialization_remove_cmd_from_given_queue(qdf_list_t *queue, } cmd_list = qdf_container_of(nnode, struct wlan_serialization_command_list, node); - if ((cmd_list->cmd.cmd_id != cmd->cmd_id) || - (cmd_list->cmd.cmd_type != cmd->cmd_type)) + if (!wlan_serialization_match_cmd_id_type(nnode, cmd, + ser_pdev_obj)) continue; - if (cmd_list->cmd.vdev != cmd->vdev) + if (!wlan_serialization_match_cmd_vdev(nnode, cmd->vdev)) continue; + /* + * Before removing the command from queue, check if it is + * already in process of being removed in some other + * context and if so, there is no need to continue with + * the removal. + */ + if (qdf_atomic_test_and_set_bit(CMD_MARKED_FOR_DELETE, + &cmd_list->cmd_in_use)) { + serialization_debug("SER_CMD already being deleted"); + break; + } + serialization_debug("SER_CMD marked for removal"); if (cmd_list->cmd.cmd_cb) { /* caller should release the memory */ cmd_list->cmd.cmd_cb(&cmd_list->cmd, @@ -276,7 +330,7 @@ wlan_serialization_remove_cmd_from_active_queue(struct wlan_objmgr_psoc *psoc, else queue = &ser_pdev_obj->active_list; - if (qdf_list_empty(queue)) { + if (wlan_serialization_list_empty(queue, ser_pdev_obj)) { serialization_err("Empty queue"); return; } @@ -325,7 +379,7 @@ wlan_serialization_remove_cmd_from_pending_queue(struct wlan_objmgr_psoc *psoc, else queue = &ser_pdev_obj->pending_list; - if (qdf_list_empty(queue)) { + if (wlan_serialization_list_empty(queue, ser_pdev_obj)) { serialization_err("Empty queue"); return; } diff --git a/umac/cmn_services/serialization/src/wlan_serialization_enqueue.c b/umac/cmn_services/serialization/src/wlan_serialization_enqueue.c index 0bbc1e4a8b83..43cdea50d7d4 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_enqueue.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_enqueue.c @@ -45,12 +45,16 @@ wlan_serialization_add_cmd_to_given_queue(qdf_list_t *queue, serialization_err("Input arguments are not valid"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; } - if (qdf_list_empty(&ser_pdev_obj->global_cmd_pool_list)) { + serialization_debug("add cmd cmd_id-%d type-%d", + cmd->cmd_id, cmd->cmd_type); + if (wlan_serialization_list_empty(&ser_pdev_obj->global_cmd_pool_list, + ser_pdev_obj)) { serialization_err("list is full, can't add more"); return WLAN_SER_CMD_DENIED_LIST_FULL; } - if (qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list, - &nnode) != QDF_STATUS_SUCCESS) { + if (wlan_serialization_remove_front(&ser_pdev_obj->global_cmd_pool_list, + &nnode, ser_pdev_obj) != + QDF_STATUS_SUCCESS) { serialization_err("Failed to get cmd buffer from global pool"); return WLAN_SER_CMD_DENIED_UNSPECIFIED; } @@ -59,23 +63,27 @@ wlan_serialization_add_cmd_to_given_queue(qdf_list_t *queue, qdf_mem_copy(&cmd_list->cmd, cmd, sizeof(struct wlan_serialization_command)); if (cmd->is_high_priority) - qdf_status = qdf_list_insert_front(queue, &cmd_list->node); + qdf_status = wlan_serialization_insert_front(queue, + &cmd_list->node, + ser_pdev_obj); else - qdf_status = qdf_list_insert_back(queue, &cmd_list->node); + qdf_status = wlan_serialization_insert_back(queue, + &cmd_list->node, + ser_pdev_obj); if (qdf_status != QDF_STATUS_SUCCESS) { - serialization_err("can't queue command for cmd_id-%d type-%d", - cmd->cmd_id, cmd->cmd_type); qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command)); - qdf_status = qdf_list_insert_back( + qdf_status = wlan_serialization_insert_back( &ser_pdev_obj->global_cmd_pool_list, - &cmd_list->node); + &cmd_list->node, + ser_pdev_obj); if (QDF_STATUS_SUCCESS != qdf_status) { serialization_err("can't put cmd back to global pool"); QDF_ASSERT(0); } return WLAN_SER_CMD_DENIED_UNSPECIFIED; } + qdf_atomic_set_bit(CMD_IS_ACTIVE, &cmd_list->cmd_in_use); *pcmd_list = cmd_list; if (is_cmd_for_active_queue) status = WLAN_SER_CMD_ACTIVE; @@ -102,7 +110,7 @@ void wlan_serialization_activate_cmd( queue = &ser_pdev_obj->active_scan_list; else queue = &ser_pdev_obj->active_list; - if (qdf_list_empty(queue)) { + if (wlan_serialization_list_empty(queue, ser_pdev_obj)) { serialization_err("nothing in active queue"); QDF_ASSERT(0); return; @@ -142,18 +150,32 @@ void wlan_serialization_activate_cmd( WLAN_SER_CB_ACTIVATE_CMD); if (QDF_IS_STATUS_SUCCESS(qdf_status)) return; + /* + * Since the command activation has not succeeded, + * remove the cmd from the active list and before + * doing so, try to mark the cmd for delete so that + * it is not accessed in other thread context for deletion + * again. + */ if (wlan_serialization_is_cmd_present_in_active_queue( psoc, &cmd_list->cmd)) { wlan_serialization_find_and_stop_timer(psoc, &cmd_list->cmd); - cmd_list->cmd.cmd_cb(&cmd_list->cmd, - WLAN_SER_CB_RELEASE_MEM_CMD); - wlan_serialization_put_back_to_global_list( - queue, ser_pdev_obj, cmd_list); + if (qdf_atomic_test_and_set_bit(CMD_MARKED_FOR_DELETE, + &cmd_list->cmd_in_use)) { + serialization_debug("SER_CMD already being deleted"); + } else { + serialization_debug("SER_CMD marked for removal"); + cmd_list->cmd.cmd_cb(&cmd_list->cmd, + WLAN_SER_CB_RELEASE_MEM_CMD); + wlan_serialization_put_back_to_global_list(queue, + ser_pdev_obj, + cmd_list); + } } else { - serialization_err("cmd type:%d, id: %d is removed from active list already", - cmd_list->cmd.cmd_type, - cmd_list->cmd.cmd_id); + serialization_err("active cmd :%d,id:%d is removed already", + cmd_list->cmd.cmd_type, + cmd_list->cmd.cmd_id); } wlan_serialization_move_pending_to_active( cmd_list->cmd.cmd_type, diff --git a/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c b/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c index a97e42e1a513..7e5921795986 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_legacy_api.c @@ -82,6 +82,7 @@ uint32_t wlan_serialization_get_active_list_count( { struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; qdf_list_t *queue; + uint32_t count; ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); if (!ser_pdev_obj) { @@ -89,12 +90,16 @@ uint32_t wlan_serialization_get_active_list_count( return 0; } + wlan_serialization_acquire_lock(ser_pdev_obj); if (is_cmd_from_active_scan_queue) queue = &ser_pdev_obj->active_scan_list; else queue = &ser_pdev_obj->active_list; - return qdf_list_size(queue); + count = qdf_list_size(queue); + wlan_serialization_release_lock(ser_pdev_obj); + + return count; } uint32_t wlan_serialization_get_pending_list_count( @@ -103,6 +108,7 @@ uint32_t wlan_serialization_get_pending_list_count( { struct wlan_serialization_pdev_priv_obj *ser_pdev_obj; qdf_list_t *queue; + uint32_t count = 0; ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); if (!ser_pdev_obj) { @@ -110,12 +116,16 @@ uint32_t wlan_serialization_get_pending_list_count( return 0; } + wlan_serialization_acquire_lock(ser_pdev_obj); if (is_cmd_from_pending_scan_queue) queue = &ser_pdev_obj->pending_scan_list; else queue = &ser_pdev_obj->pending_list; - return qdf_list_size(queue); + count = qdf_list_size(queue); + wlan_serialization_release_lock(ser_pdev_obj); + + return count; } struct wlan_serialization_command* @@ -132,29 +142,31 @@ wlan_serialization_peek_head_active_cmd_using_psoc( ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); if (!ser_pdev_obj) { serialization_err("invalid ser_pdev_obj"); - return 0; + return NULL; } if (is_cmd_from_active_scan_queue) queue = &ser_pdev_obj->active_scan_list; else queue = &ser_pdev_obj->active_list; - if (!qdf_list_size(queue)) { + if (wlan_serialization_list_empty(queue, ser_pdev_obj)) { serialization_err("Empty Queue"); - return NULL; + goto end; } if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue, - &nnode)) { + &nnode, ser_pdev_obj)) { serialization_err("Can't get command from queue"); - return NULL; + goto end; } cmd_list = qdf_container_of(nnode, struct wlan_serialization_command_list, node); - serialization_debug("cmd_type[%d]", cmd_list->cmd.cmd_type); cmd = &cmd_list->cmd; + serialization_debug("cmd_type[%d], cmd_id[%d]", + cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); +end: return cmd; } @@ -172,76 +184,89 @@ wlan_serialization_peek_head_pending_cmd_using_psoc( ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); if (!ser_pdev_obj) { serialization_err("invalid ser_pdev_obj"); - return 0; + return NULL; } - if (is_cmd_from_pending_scan_queue) queue = &ser_pdev_obj->pending_scan_list; else queue = &ser_pdev_obj->pending_list; - if (!qdf_list_size(queue)) { + if (wlan_serialization_list_empty(queue, ser_pdev_obj)) { serialization_err("Empty Queue"); - return NULL; + goto end; } if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue, - &nnode)) { + &nnode, ser_pdev_obj)) { serialization_err("Can't get command from queue"); - return NULL; + goto end; } cmd_list = qdf_container_of(nnode, struct wlan_serialization_command_list, node); - serialization_debug("cmd_type[%d] matched", cmd_list->cmd.cmd_type); cmd = &cmd_list->cmd; + serialization_debug("cmd_type[%d] cmd_id[%d]matched", + cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); +end: return cmd; } static struct wlan_serialization_command* wlan_serialization_get_list_next_node(qdf_list_t *queue, - struct wlan_serialization_command *cmd) + struct wlan_serialization_command *cmd, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) { struct wlan_serialization_command_list *cmd_list = NULL; qdf_list_node_t *pnode = NULL, *nnode = NULL; bool found = false; uint32_t i = 0; QDF_STATUS status; + struct wlan_serialization_command *ret_cmd = NULL; - if (!qdf_list_empty(queue)) { - i = qdf_list_size(queue); - while (i--) { - if (!cmd_list) - status = qdf_list_peek_front(queue, &nnode); - else - status = qdf_list_peek_next(queue, pnode, - &nnode); + i = wlan_serialization_list_size(queue, ser_pdev_obj); + if (i == 0) { + serialization_err("Empty Queue"); + return NULL; + } + while (i--) { + if (!cmd_list) + status = wlan_serialization_peek_front(queue, &nnode, + ser_pdev_obj); + else + status = wlan_serialization_peek_next(queue, pnode, + &nnode, + ser_pdev_obj); - if ((status != QDF_STATUS_SUCCESS) || found) - break; + if ((status != QDF_STATUS_SUCCESS) || found) + break; - pnode = nnode; - cmd_list = qdf_container_of(nnode, + pnode = nnode; + cmd_list = qdf_container_of( + nnode, struct wlan_serialization_command_list, node); - if ((cmd_list->cmd.cmd_id == cmd->cmd_id) && - (cmd_list->cmd.cmd_type == cmd->cmd_type) && - (cmd_list->cmd.vdev == cmd->vdev)) { - found = true; - } - nnode = NULL; + if (wlan_serialization_match_cmd_id_type(nnode, cmd, + ser_pdev_obj) && + wlan_serialization_match_cmd_vdev(nnode, + cmd->vdev)) { + found = true; } + nnode = NULL; } if (nnode && found) { cmd_list = qdf_container_of(nnode, struct wlan_serialization_command_list, node); - return &cmd_list->cmd; - } else if (!found) { + ret_cmd = &cmd_list->cmd; + } + if (!found) { serialization_err("Can't locate next command"); return NULL; - } else { + } + if (!nnode) { serialization_debug("next node is empty, so fine"); return NULL; } + + return ret_cmd; } struct wlan_serialization_command* @@ -261,19 +286,16 @@ wlan_serialization_get_active_list_next_node_using_psoc( ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); if (!ser_pdev_obj) { serialization_err("invalid ser_pdev_obj"); - return 0; + return NULL; } if (is_cmd_for_active_scan_queue) queue = &ser_pdev_obj->active_scan_list; else queue = &ser_pdev_obj->active_list; - if (!qdf_list_size(queue)) { - serialization_err("Empty Queue"); - return NULL; - } - return wlan_serialization_get_list_next_node(queue, prev_cmd); + return wlan_serialization_get_list_next_node(queue, prev_cmd, + ser_pdev_obj); } struct wlan_serialization_command* @@ -293,19 +315,15 @@ wlan_serialization_get_pending_list_next_node_using_psoc( ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); if (!ser_pdev_obj) { serialization_err("invalid ser_pdev_obj"); - return 0; + return NULL; } - if (is_cmd_for_pending_scan_queue) queue = &ser_pdev_obj->pending_scan_list; else queue = &ser_pdev_obj->pending_list; - if (!qdf_list_size(queue)) { - serialization_err("Empty Queue"); - return NULL; - } - return wlan_serialization_get_list_next_node(queue, prev_cmd); + return wlan_serialization_get_list_next_node(queue, prev_cmd, + ser_pdev_obj); } void wlan_serialization_legacy_init_callback(void) diff --git a/umac/cmn_services/serialization/src/wlan_serialization_main.c b/umac/cmn_services/serialization/src/wlan_serialization_main.c index c012e43f3c21..53d0ce8241db 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_main.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_main.c @@ -168,6 +168,7 @@ wlan_serialization_create_cmd_pool(struct wlan_objmgr_pdev *pdev, qdf_list_insert_back( &ser_pdev_obj->global_cmd_pool_list, &cmd_list_ptr->node); + cmd_list_ptr->cmd_in_use = 0; serialization_debug("Created node at %pK and inserted to pool", cmd_list_ptr); } @@ -200,6 +201,11 @@ static QDF_STATUS wlan_serialization_pdev_obj_create_notification( serialization_alert("Mem alloc failed for ser pdev obj"); return QDF_STATUS_E_NOMEM; } + status = wlan_serialization_create_lock(ser_pdev_obj); + if (status != QDF_STATUS_SUCCESS) { + serialization_err("Failed to create serialization lock"); + return status; + } qdf_list_create(&ser_pdev_obj->active_list, WLAN_SERIALIZATION_MAX_ACTIVE_CMDS); qdf_list_create(&ser_pdev_obj->pending_list, @@ -290,7 +296,10 @@ static QDF_STATUS wlan_serialization_pdev_obj_destroy_notification( wlan_serialization_destroy_list(ser_pdev_obj, &ser_pdev_obj->pending_scan_list); wlan_serialization_destroy_cmd_pool(ser_pdev_obj); - serialization_debug("ser pdev obj deleted with status %d", status); + serialization_debug("ser pdev obj detached with status %d", status); + status = wlan_serialization_destroy_lock(ser_pdev_obj); + if (status != QDF_STATUS_SUCCESS) + serialization_err("Failed to destroy serialization lock"); qdf_mem_free(ser_pdev_obj); return status; diff --git a/umac/cmn_services/serialization/src/wlan_serialization_utils.c b/umac/cmn_services/serialization/src/wlan_serialization_utils.c index 9ac797b2c1e3..31db67a07a45 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_utils.c +++ b/umac/cmn_services/serialization/src/wlan_serialization_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * 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 @@ -34,28 +34,42 @@ wlan_serialization_put_back_to_global_list(qdf_list_t *queue, struct wlan_serialization_command_list *cmd_list) { QDF_STATUS status; + uint32_t cmd_id, cmd_type; if (!queue || !ser_pdev_obj || !cmd_list) { serialization_err("input parameters are invalid"); return QDF_STATUS_E_FAILURE; } - status = qdf_list_remove_node(queue, &cmd_list->node); + /* + * if the command is already removed in other context, + * then it will be marked as inactive with the same + * below code. So, test before proceeding. + */ + if (!qdf_atomic_test_and_clear_bit(CMD_IS_ACTIVE, + &cmd_list->cmd_in_use)) { + serialization_debug("CMD is not active or being used"); + return QDF_STATUS_SUCCESS; + } + status = wlan_serialization_remove_node(queue, &cmd_list->node, + ser_pdev_obj); if (QDF_STATUS_SUCCESS != status) { serialization_err("can't remove cmd from queue"); /* assert to catch any leaks */ QDF_ASSERT(0); return status; } - serialization_debug("cmd_id-%d, cmd_type-%d", cmd_list->cmd.cmd_id, - cmd_list->cmd.cmd_type); + cmd_id = cmd_list->cmd.cmd_id; + cmd_type = cmd_list->cmd.cmd_type; qdf_mem_zero(&cmd_list->cmd, sizeof(struct wlan_serialization_command)); - status = qdf_list_insert_back(&ser_pdev_obj->global_cmd_pool_list, - &cmd_list->node); + status = wlan_serialization_insert_back( + &ser_pdev_obj->global_cmd_pool_list, + &cmd_list->node, ser_pdev_obj); + qdf_atomic_clear_bit(CMD_MARKED_FOR_DELETE, &cmd_list->cmd_in_use); if (QDF_STATUS_SUCCESS != status) { serialization_err("can't put command back to global pool"); QDF_ASSERT(0); - return status; } + serialization_debug("cmd_id-%d, cmd_type-%d", cmd_id, cmd_type); return status; } @@ -78,33 +92,31 @@ wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd) return pdev; } -/** - * 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) + qdf_list_node_t **nnode, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) { QDF_STATUS status; qdf_list_node_t *pnode; + if (!queue || !ser_pdev_obj) { + serialization_err("input parameters are invalid"); + return QDF_STATUS_E_FAILURE; + } + pnode = *nnode; if (!pnode) - status = qdf_list_peek_front(queue, nnode); + status = wlan_serialization_peek_front(queue, nnode, + ser_pdev_obj); else - status = qdf_list_peek_next(queue, pnode, nnode); + status = wlan_serialization_peek_next(queue, pnode, nnode, + ser_pdev_obj); if (status != QDF_STATUS_SUCCESS) { serialization_err("can't get next node from queue"); - return status; } - return QDF_STATUS_SUCCESS; + + return status; } /** @@ -368,7 +380,8 @@ wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc, ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj( pdev, WLAN_UMAC_COMP_SERIALIZATION); - *count += qdf_list_size(&ser_pdev_obj->active_scan_list); + *count += wlan_serialization_list_size(&ser_pdev_obj->active_scan_list, + ser_pdev_obj); } /** @@ -437,7 +450,8 @@ wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev) return false; } - if (qdf_list_empty(&ser_pdev_obj->active_list)) + if (wlan_serialization_list_empty(&ser_pdev_obj->active_list, + ser_pdev_obj)) return true; return false; @@ -489,15 +503,17 @@ QDF_STATUS wlan_serialization_validate_cmd( return QDF_STATUS_SUCCESS; } -void wlan_serialization_release_list_cmds( +static void wlan_serialization_release_list_cmds( struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, qdf_list_t *list) { qdf_list_node_t *node = NULL; - while (!qdf_list_empty(list)) { - qdf_list_remove_front(list, &node); - qdf_list_insert_back(&ser_pdev_obj->global_cmd_pool_list, node); + while (!wlan_serialization_list_empty(list, ser_pdev_obj)) { + wlan_serialization_remove_front(list, &node, ser_pdev_obj); + wlan_serialization_insert_back( + &ser_pdev_obj->global_cmd_pool_list, + node, ser_pdev_obj); } return; @@ -532,7 +548,7 @@ struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj( } struct wlan_serialization_psoc_priv_obj * -wlan_serialization_get_obj(struct wlan_serialization_command *cmd) +wlan_serialization_get_psoc_obj(struct wlan_serialization_command *cmd) { struct wlan_serialization_psoc_priv_obj *ser_soc_obj = NULL; struct wlan_objmgr_psoc *psoc; @@ -547,55 +563,55 @@ wlan_serialization_get_obj(struct wlan_serialization_command *cmd) } bool wlan_serialization_is_cmd_in_vdev_list(struct wlan_objmgr_vdev *vdev, - qdf_list_t *queue) + qdf_list_t *queue) { uint32_t queuelen; qdf_list_node_t *nnode = NULL; - struct wlan_serialization_command_list *cmd_list = NULL; + struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = + wlan_serialization_get_pdev_priv_obj(pdev); QDF_STATUS status; - queuelen = qdf_list_size(queue); + queuelen = wlan_serialization_list_size(queue, ser_pdev_obj); if (!queuelen) { serialization_debug("queue empty"); return false; } while (queuelen--) { - status = wlan_serialization_get_cmd_from_queue(queue, &nnode); + status = wlan_serialization_get_cmd_from_queue(queue, &nnode, + ser_pdev_obj); if (status != QDF_STATUS_SUCCESS) break; - cmd_list = qdf_container_of(nnode, - struct wlan_serialization_command_list, node); - if (cmd_list->cmd.vdev == vdev) + if (wlan_serialization_match_cmd_vdev(nnode, vdev)) return true; - }; + } return false; } -bool wlan_serialization_is_cmd_in_pdev_list(struct wlan_objmgr_pdev *pdev, - qdf_list_t *queue) +bool wlan_serialization_is_cmd_in_pdev_list( + struct wlan_objmgr_pdev *pdev, + qdf_list_t *queue) { uint32_t queuelen; qdf_list_node_t *nnode = NULL; - struct wlan_objmgr_pdev *node_pdev = NULL; - struct wlan_serialization_command_list *cmd_list = NULL; + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = + wlan_serialization_get_pdev_priv_obj(pdev); QDF_STATUS status; - queuelen = qdf_list_size(queue); + queuelen = wlan_serialization_list_size(queue, ser_pdev_obj); if (!queuelen) { serialization_debug("queue empty"); return false; } while (queuelen--) { - status = wlan_serialization_get_cmd_from_queue(queue, &nnode); + status = wlan_serialization_get_cmd_from_queue(queue, &nnode, + ser_pdev_obj); if (status != QDF_STATUS_SUCCESS) break; - cmd_list = qdf_container_of(nnode, - struct wlan_serialization_command_list, node); - node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); - if (node_pdev == pdev) + if (wlan_serialization_match_cmd_pdev(nnode, pdev)) return true; } @@ -617,7 +633,8 @@ wlan_serialization_is_cmd_in_active_pending(bool cmd_in_active, } static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue, - struct wlan_serialization_command *cmd) + struct wlan_serialization_command *cmd, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) { uint32_t qsize; QDF_STATUS status; @@ -625,13 +642,15 @@ static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue, qdf_list_node_t *nnode = NULL, *pnode = NULL; bool found = false; - qsize = qdf_list_size(queue); + qsize = wlan_serialization_list_size(queue, ser_pdev_obj); while (qsize--) { if (!cmd_list) - status = qdf_list_peek_front(queue, &nnode); + status = wlan_serialization_peek_front(queue, &nnode, + ser_pdev_obj); else - status = qdf_list_peek_next(queue, pnode, - &nnode); + status = wlan_serialization_peek_next(queue, pnode, + &nnode, + ser_pdev_obj); if (status != QDF_STATUS_SUCCESS) break; @@ -639,14 +658,15 @@ static bool wlan_serialization_is_cmd_present_in_given_queue(qdf_list_t *queue, pnode = nnode; cmd_list = qdf_container_of(nnode, struct wlan_serialization_command_list, node); - if ((cmd_list->cmd.cmd_id == cmd->cmd_id) && - (cmd_list->cmd.cmd_type == cmd->cmd_type) && - (cmd_list->cmd.vdev == cmd->vdev)) { + if (wlan_serialization_match_cmd_id_type(nnode, cmd, + ser_pdev_obj) && + wlan_serialization_match_cmd_vdev(nnode, cmd->vdev)) { found = true; break; } nnode = NULL; } + return found; } @@ -685,5 +705,280 @@ bool wlan_serialization_is_cmd_present_queue( queue = &ser_pdev_obj->active_list; } - return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd); + return wlan_serialization_is_cmd_present_in_given_queue(queue, cmd, + ser_pdev_obj); } + +bool wlan_serialization_list_empty( + qdf_list_t *queue, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + bool is_empty; + + wlan_serialization_acquire_lock(ser_pdev_obj); + if (qdf_list_empty(queue)) + is_empty = true; + else + is_empty = false; + wlan_serialization_release_lock(ser_pdev_obj); + + return is_empty; +} + +uint32_t wlan_serialization_list_size( + qdf_list_t *queue, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + uint32_t size; + + wlan_serialization_acquire_lock(ser_pdev_obj); + size = qdf_list_size(queue); + wlan_serialization_release_lock(ser_pdev_obj); + + return size; +} + +QDF_STATUS wlan_serialization_remove_front( + qdf_list_t *list, + qdf_list_node_t **node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + QDF_STATUS status; + + wlan_serialization_acquire_lock(ser_pdev_obj); + status = qdf_list_remove_front(list, node); + wlan_serialization_release_lock(ser_pdev_obj); + + return status; +} + +QDF_STATUS wlan_serialization_remove_node( + qdf_list_t *list, + qdf_list_node_t *node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + QDF_STATUS status; + + wlan_serialization_acquire_lock(ser_pdev_obj); + status = qdf_list_remove_node(list, node); + wlan_serialization_release_lock(ser_pdev_obj); + + return status; +} + +QDF_STATUS wlan_serialization_insert_front( + qdf_list_t *list, + qdf_list_node_t *node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + QDF_STATUS status; + + wlan_serialization_acquire_lock(ser_pdev_obj); + status = qdf_list_insert_front(list, node); + wlan_serialization_release_lock(ser_pdev_obj); + + return status; +} + +QDF_STATUS wlan_serialization_insert_back( + qdf_list_t *list, + qdf_list_node_t *node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + QDF_STATUS status; + + wlan_serialization_acquire_lock(ser_pdev_obj); + status = qdf_list_insert_back(list, node); + wlan_serialization_release_lock(ser_pdev_obj); + + return status; +} + +QDF_STATUS wlan_serialization_peek_front( + qdf_list_t *list, + qdf_list_node_t **node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + QDF_STATUS status; + + wlan_serialization_acquire_lock(ser_pdev_obj); + status = qdf_list_peek_front(list, node); + wlan_serialization_release_lock(ser_pdev_obj); + + return status; +} + +QDF_STATUS wlan_serialization_peek_next( + qdf_list_t *list, + qdf_list_node_t *node1, qdf_list_node_t **node2, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + QDF_STATUS status; + + wlan_serialization_acquire_lock(ser_pdev_obj); + status = qdf_list_peek_next(list, node1, node2); + wlan_serialization_release_lock(ser_pdev_obj); + + return status; +} + +bool wlan_serialization_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_pdev_priv_obj *ser_pdev_obj) +{ + struct wlan_serialization_command_list *cmd_list = NULL; + bool match_found = false; + + wlan_serialization_acquire_lock(ser_pdev_obj); + cmd_list = qdf_container_of(nnode, + struct wlan_serialization_command_list, + node); + if ((cmd_list->cmd.cmd_id == scan_id) && + (cmd_list->cmd.vdev == vdev)) { + *cmd = &cmd_list->cmd; + match_found = true; + }; + wlan_serialization_release_lock(ser_pdev_obj); + + return match_found; +} + +bool wlan_serialization_match_cmd_id_type( + qdf_list_node_t *nnode, + struct wlan_serialization_command *cmd, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj) +{ + struct wlan_serialization_command_list *cmd_list = NULL; + bool match_found = true; + + if (!cmd) + return false; + wlan_serialization_acquire_lock(ser_pdev_obj); + cmd_list = qdf_container_of(nnode, + struct wlan_serialization_command_list, + node); + if ((cmd_list->cmd.cmd_id != cmd->cmd_id) || + (cmd_list->cmd.cmd_type != cmd->cmd_type)) { + match_found = false; + }; + wlan_serialization_release_lock(ser_pdev_obj); + + return match_found; +} + +bool wlan_serialization_match_cmd_vdev(qdf_list_node_t *nnode, + struct wlan_objmgr_vdev *vdev) +{ + struct wlan_serialization_command_list *cmd_list = NULL; + bool match_found = false; + struct wlan_objmgr_pdev *pdev = wlan_vdev_get_pdev(vdev); + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = + wlan_serialization_get_pdev_priv_obj(pdev); + + wlan_serialization_acquire_lock(ser_pdev_obj); + cmd_list = qdf_container_of(nnode, + struct wlan_serialization_command_list, + node); + if (cmd_list->cmd.vdev == vdev) + match_found = true; + wlan_serialization_release_lock(ser_pdev_obj); + + return match_found; +} + +bool wlan_serialization_match_cmd_pdev(qdf_list_node_t *nnode, + struct wlan_objmgr_pdev *pdev) +{ + struct wlan_serialization_command_list *cmd_list = NULL; + bool match_found = false; + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj = + wlan_serialization_get_pdev_priv_obj(pdev); + struct wlan_objmgr_pdev *node_pdev = NULL; + + wlan_serialization_acquire_lock(ser_pdev_obj); + cmd_list = qdf_container_of(nnode, + struct wlan_serialization_command_list, + node); + node_pdev = wlan_vdev_get_pdev(cmd_list->cmd.vdev); + if (node_pdev == pdev) + match_found = true; + wlan_serialization_release_lock(ser_pdev_obj); + + return match_found; +} + +#ifdef WLAN_CMD_SERIALIZATION_LOCKING +QDF_STATUS +wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + if (!obj) { + serialization_err("invalid object"); + return QDF_STATUS_E_FAILURE; + } + qdf_spin_lock_bh(&obj->pdev_ser_list_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + if (!obj) { + serialization_err("invalid object"); + return QDF_STATUS_E_FAILURE; + } + qdf_spin_unlock_bh(&obj->pdev_ser_list_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + if (!obj) { + serialization_err("invalid object"); + return QDF_STATUS_E_FAILURE; + } + qdf_spinlock_create(&obj->pdev_ser_list_lock); + + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + if (!obj) { + serialization_err("invalid object"); + return QDF_STATUS_E_FAILURE; + } + qdf_spinlock_destroy(&obj->pdev_ser_list_lock); + + return QDF_STATUS_SUCCESS; +} +#else +QDF_STATUS +wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + return QDF_STATUS_SUCCESS; +} + +QDF_STATUS +wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj) +{ + return QDF_STATUS_SUCCESS; +} +#endif 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 374982937b36..050e944c5d2e 100644 --- a/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h +++ b/umac/cmn_services/serialization/src/wlan_serialization_utils_i.h @@ -32,6 +32,15 @@ #include "wlan_serialization_rules_i.h" #include "wlan_scan_ucfg_api.h" +/* + * Below bit positions are used to identify if a + * serialization command is in use or marked for + * deletion. + * CMD_MARKED_FOR_DELETE - The command is about to be deleted + * CMD_IS_ACTIVE - The command is active and currently in use + */ +#define CMD_MARKED_FOR_DELETE 1 +#define CMD_IS_ACTIVE 2 /** * struct wlan_serialization_timer - Timer used for serialization * @cmd: Cmd to which the timer is linked @@ -55,10 +64,12 @@ struct wlan_serialization_timer { * struct wlan_serialization_command_list - List of commands to be serialized * @node: Node identifier in the list * @cmd: Command to be serialized + * @active: flag to check if the node/entry is logically active */ struct wlan_serialization_command_list { qdf_list_node_t node; struct wlan_serialization_command cmd; + unsigned long cmd_in_use; }; /** @@ -68,7 +79,8 @@ struct wlan_serialization_command_list { * @active_scan_list: list to hold the scan commands currently active * @pending_scan_list: list to hold the scan commands currently pending * @global_cmd_pool_list: list to hold the global buffers - * @cmd_ptr: pointer to globally allocated cmd pool + * @pdev_ser_list_lock: A per pdev lock to protect the concurrent operations + * on the queues. * * Serialization component maintains linked lists to store the commands * sent by other components to get serialized. All the lists are per @@ -84,6 +96,7 @@ struct wlan_serialization_pdev_priv_obj { qdf_list_t active_scan_list; qdf_list_t pending_scan_list; qdf_list_t global_cmd_pool_list; + qdf_spinlock_t pdev_ser_list_lock; }; /** @@ -150,6 +163,7 @@ wlan_serialization_get_pdev_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 + * @ser_pdev_obj: Serialization PDEV object pointer * * 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. @@ -157,7 +171,8 @@ wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd); * Return: QDF_STATUS */ QDF_STATUS wlan_serialization_get_cmd_from_queue(qdf_list_t *queue, - qdf_list_node_t **nnode); + qdf_list_node_t **nnode, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); /** * wlan_serialization_is_active_cmd_allowed() - check to see if command @@ -280,16 +295,6 @@ QDF_STATUS wlan_serialization_validate_cmd( QDF_STATUS wlan_serialization_validate_cmdtype( enum wlan_serialization_cmd_type cmd_type); -/** - * wlan_serialization_release_list_cmds() - Release the list cmds to global pool - * @ser_pdev_obj: Serialization private pdev object - * @list: List for which the commands have to be returned to the global pool - * - * Return: None - */ -void wlan_serialization_release_list_cmds( - struct wlan_serialization_pdev_priv_obj *ser_pdev_obj, - qdf_list_t *list); /** * wlan_serialization_destroy_list() - Release the cmds and destroy list @@ -321,13 +326,13 @@ struct wlan_serialization_pdev_priv_obj *wlan_serialization_get_pdev_priv_obj( struct wlan_objmgr_pdev *pdev); /** - * wlan_serialization_get_obj() - Return the component private obj + * wlan_serialization_get_psoc_obj() - Return the component private obj * @psoc: Pointer to the SERIALIZATION object * * Return: Serialization component's level private data object */ struct wlan_serialization_psoc_priv_obj * -wlan_serialization_get_obj(struct wlan_serialization_command *cmd); +wlan_serialization_get_psoc_obj(struct wlan_serialization_command *cmd); /** * wlan_serialization_is_cmd_in_vdev_list() - Check Node present in VDEV list @@ -411,4 +416,201 @@ bool wlan_serialization_is_cmd_present_queue( void wlan_serialization_activate_cmd( struct wlan_serialization_command_list *cmd_list, struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); + +/** + * wlan_serialization_list_empty() - check if the list is empty + * @queue: Queue/List that needs to be checked for emptiness + * @ser_pdev_obj: Serialization private pdev object + * + * Return: true if list is empty and false otherwise + */ +bool wlan_serialization_list_empty( + qdf_list_t *queue, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); + +/** + * wlan_serialization_list_size() - Find the size of the provided queue + * @queue: Queue/List for which the size/length is to be returned + * @ser_pdev_obj: Serialization private pdev object + * + * Return: size/length of the queue/list + */ +uint32_t wlan_serialization_list_size( + qdf_list_t *queue, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * wlan_serialization_acquire_lock() - to acquire lock for serialization module + * @obj: pdev private object + * + * This API will acquire lock for serialization module. Mutex or spinlock will + * be decided based on the context of the operation. + * + * Return: QDF_STATUS based on outcome of the operation + */ +QDF_STATUS +wlan_serialization_acquire_lock(struct wlan_serialization_pdev_priv_obj *obj); + +/** + * wlan_serialization_release_lock() - to release lock for serialization module + * @obj: pdev private object + * + * This API will release lock for serialization module. Mutex or spinlock will + * be decided based on the context of the operation. + * + * Return: QDF_STATUS based on outcome of the operation + */ +QDF_STATUS +wlan_serialization_release_lock(struct wlan_serialization_pdev_priv_obj *obj); + +/** + * wlan_serialization_create_lock() - to create lock for serialization module + * @obj: pdev private object + * + * This API will create a lock for serialization module. + * + * Return: QDF_STATUS based on outcome of the operation + */ +QDF_STATUS +wlan_serialization_create_lock(struct wlan_serialization_pdev_priv_obj *obj); + +/** + * wlan_serialization_destroy_lock() - to destroy lock for serialization module + * + * This API will destroy a lock for serialization module. + * + * Return: QDF_STATUS based on outcome of the operation + */ +QDF_STATUS +wlan_serialization_destroy_lock(struct wlan_serialization_pdev_priv_obj *obj); +/** + * wlan_serialization_match_cmd_scan_id() - Check for a match on given nnode + * @nnode: The node on which the matching has to be done + * @cmd: Command that needs to be filled if there is a match + * @scan_id: Scan ID to be matched + * @vdev: VDEV object to be matched + * @ser_pdev_obj: Serialization PDEV Object pointer. + * + * This API will check if the scan ID and VDEV 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_scan_id( + qdf_list_node_t *nnode, + struct wlan_serialization_command **cmd, + uint16_t scan_id, struct wlan_objmgr_vdev *vdev, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * 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 + * @ser_pdev_obj: Serialization PDEV Object pointer. + * + * 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, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * 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 + * + * 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); +/** + * wlan_serialization_match_cmd_pdev() - Check for a match on given nnode + * @nnode: The node on which the matching has to be done + * @pdev: VDEV object that needs to be matched + * + * 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); +/** + * 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 + * @ser_pdev_obj: Serialization PDEV Object pointer + * + * Return: QDF_STATUS Success or Failure + */ +QDF_STATUS wlan_serialization_remove_front( + qdf_list_t *list, + qdf_list_node_t **node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * 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 + * @ser_pdev_obj: Serialization PDEV Object pointer + * + * Return: QDF_STATUS Success or Failure + */ +QDF_STATUS wlan_serialization_remove_node( + qdf_list_t *list, + qdf_list_node_t *node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * 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 + * @ser_pdev_obj: Serialization PDEV Object pointer + * + * Return: QDF_STATUS Success or Failure + */ +QDF_STATUS wlan_serialization_insert_front( + qdf_list_t *list, + qdf_list_node_t *node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * 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 + * @ser_pdev_obj: Serialization PDEV Object pointer + * + * Return: QDF_STATUS Success or Failure + */ +QDF_STATUS wlan_serialization_insert_back( + qdf_list_t *list, + qdf_list_node_t *node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * 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 + * @ser_pdev_obj: Serialization PDEV Object pointer + * + * Return: QDF_STATUS Success or Failure + */ +QDF_STATUS wlan_serialization_peek_front( + qdf_list_t *list, + qdf_list_node_t **node, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); +/** + * wlan_serialization_peek_next() - Peek the next node of the list + * @list: List on which the node is to be peeked + * @node1: Input node which is previous to the node to be peeked + * @node2: Pointer to the store the node that is being peeked + * @ser_pdev_obj: Serialization PDEV Object pointer + * + * 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, + struct wlan_serialization_pdev_priv_obj *ser_pdev_obj); #endif