| /* |
| * 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 |
| * above copyright notice and this permission notice appear in all |
| * copies. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| * PERFORMANCE OF THIS SOFTWARE. |
| */ |
| /** |
| * DOC: wlan_serialization_legacy_api.c |
| * This file provides prototypes of the routines needed for the |
| * legacy mcl serialization to utilize the services provided by the |
| * serialization component. |
| */ |
| |
| #include "wlan_serialization_legacy_api.h" |
| #include "wlan_serialization_main_i.h" |
| #include "wlan_serialization_utils_i.h" |
| #include "wlan_objmgr_vdev_obj.h" |
| #include "wlan_serialization_internal_i.h" |
| #include "wlan_serialization_scan_i.h" |
| #include "wlan_serialization_non_scan_i.h" |
| |
| static struct wlan_objmgr_pdev *wlan_serialization_get_first_pdev( |
| struct wlan_objmgr_psoc *psoc) |
| { |
| struct wlan_objmgr_pdev *pdev; |
| uint8_t i = 0; |
| |
| if (!psoc) { |
| ser_err("invalid psoc"); |
| return NULL; |
| } |
| for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) { |
| pdev = wlan_objmgr_get_pdev_by_id(psoc, i, |
| WLAN_SERIALIZATION_ID); |
| if (pdev) |
| break; |
| } |
| |
| return pdev; |
| } |
| |
| static struct wlan_ser_pdev_obj * |
| wlan_serialization_get_pdev_priv_obj_using_psoc(struct wlan_objmgr_psoc *psoc) |
| { |
| struct wlan_objmgr_pdev *pdev = NULL; |
| struct wlan_ser_pdev_obj *ser_pdev_obj; |
| |
| if (!psoc) { |
| ser_err("invalid psoc"); |
| return NULL; |
| } |
| |
| pdev = wlan_serialization_get_first_pdev(psoc); |
| if (!pdev) { |
| ser_err("invalid pdev"); |
| return NULL; |
| } |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_obj(pdev); |
| wlan_objmgr_pdev_release_ref(pdev, WLAN_SERIALIZATION_ID); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return NULL; |
| } |
| |
| return ser_pdev_obj; |
| } |
| |
| uint32_t wlan_serialization_get_active_list_count( |
| struct wlan_objmgr_psoc *psoc, |
| uint8_t is_cmd_from_active_scan_queue) |
| { |
| struct wlan_ser_pdev_obj *ser_pdev_obj; |
| qdf_list_t *queue; |
| struct wlan_serialization_pdev_queue *pdev_queue; |
| uint32_t count; |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return 0; |
| } |
| |
| if (is_cmd_from_active_scan_queue) |
| pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; |
| else |
| pdev_queue = |
| &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; |
| |
| wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); |
| queue = &pdev_queue->active_list; |
| count = qdf_list_size(queue); |
| wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); |
| |
| return count; |
| } |
| |
| uint32_t wlan_serialization_get_pending_list_count( |
| struct wlan_objmgr_psoc *psoc, |
| uint8_t is_cmd_from_pending_scan_queue) |
| { |
| struct wlan_ser_pdev_obj *ser_pdev_obj; |
| qdf_list_t *queue; |
| uint32_t count = 0; |
| struct wlan_serialization_pdev_queue *pdev_queue; |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return 0; |
| } |
| |
| if (is_cmd_from_pending_scan_queue) |
| pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; |
| else |
| pdev_queue = |
| &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; |
| queue = &pdev_queue->pending_list; |
| wlan_serialization_acquire_lock(&pdev_queue->pdev_queue_lock); |
| count = qdf_list_size(queue); |
| wlan_serialization_release_lock(&pdev_queue->pdev_queue_lock); |
| |
| return count; |
| } |
| |
| struct wlan_serialization_command* |
| wlan_serialization_peek_head_active_cmd_using_psoc( |
| struct wlan_objmgr_psoc *psoc, |
| uint8_t is_cmd_from_active_scan_queue) |
| { |
| struct wlan_ser_pdev_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; |
| struct wlan_serialization_pdev_queue *pdev_queue; |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return NULL; |
| } |
| |
| if (is_cmd_from_active_scan_queue) |
| pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; |
| else |
| pdev_queue = |
| &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; |
| queue = &pdev_queue->active_list; |
| if (wlan_serialization_list_empty(queue)) { |
| ser_err("Empty Queue"); |
| goto end; |
| } |
| |
| if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue(queue, |
| &nnode)) { |
| ser_err("Can't get command from queue"); |
| goto end; |
| } |
| |
| cmd_list = qdf_container_of(nnode, |
| struct wlan_serialization_command_list, pdev_node); |
| cmd = &cmd_list->cmd; |
| ser_debug("cmd_type[%d], cmd_id[%d]", |
| cmd_list->cmd.cmd_type, cmd_list->cmd.cmd_id); |
| |
| end: |
| return cmd; |
| } |
| |
| struct wlan_serialization_command* |
| wlan_serialization_peek_head_pending_cmd_using_psoc( |
| struct wlan_objmgr_psoc *psoc, |
| uint8_t is_cmd_from_pending_scan_queue) |
| { |
| struct wlan_ser_pdev_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; |
| struct wlan_serialization_pdev_queue *pdev_queue; |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return NULL; |
| } |
| if (is_cmd_from_pending_scan_queue) |
| pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; |
| else |
| pdev_queue = |
| &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; |
| queue = &pdev_queue->pending_list; |
| if (wlan_serialization_list_empty(queue)) { |
| ser_err("Empty Queue"); |
| goto end; |
| } |
| |
| if (QDF_STATUS_SUCCESS != wlan_serialization_get_cmd_from_queue( |
| queue, |
| &nnode)) { |
| ser_err("Can't get command from queue"); |
| goto end; |
| } |
| cmd_list = qdf_container_of(nnode, |
| struct wlan_serialization_command_list, pdev_node); |
| cmd = &cmd_list->cmd; |
| ser_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_ser_pdev_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; |
| |
| i = wlan_serialization_list_size(queue); |
| if (i == 0) { |
| ser_err("Empty Queue"); |
| return NULL; |
| } |
| while (i--) { |
| if (!cmd_list) |
| status = wlan_serialization_peek_front(queue, &nnode); |
| else |
| status = wlan_serialization_peek_next(queue, pnode, |
| &nnode); |
| |
| if ((status != QDF_STATUS_SUCCESS) || found) |
| break; |
| |
| pnode = nnode; |
| cmd_list = qdf_container_of( |
| nnode, |
| struct wlan_serialization_command_list, |
| pdev_node); |
| if (wlan_serialization_match_cmd_id_type( |
| nnode, cmd, WLAN_SER_PDEV_NODE) && |
| wlan_serialization_match_cmd_vdev(nnode, |
| cmd->vdev, |
| WLAN_SER_PDEV_NODE)) { |
| found = true; |
| } |
| nnode = NULL; |
| } |
| if (nnode && found) { |
| cmd_list = qdf_container_of( |
| nnode, |
| struct wlan_serialization_command_list, |
| pdev_node); |
| ret_cmd = &cmd_list->cmd; |
| } |
| if (!found) { |
| ser_err("Can't locate next command"); |
| return NULL; |
| } |
| if (!nnode) { |
| ser_debug("next node is empty, so fine"); |
| return NULL; |
| } |
| |
| return ret_cmd; |
| } |
| |
| struct wlan_serialization_command* |
| wlan_serialization_get_active_list_next_node_using_psoc( |
| struct wlan_objmgr_psoc *psoc, |
| struct wlan_serialization_command *prev_cmd, |
| uint8_t is_cmd_for_active_scan_queue) |
| { |
| struct wlan_ser_pdev_obj *ser_pdev_obj; |
| qdf_list_t *queue; |
| struct wlan_serialization_pdev_queue *pdev_queue; |
| |
| if (!prev_cmd) { |
| ser_err("invalid prev_cmd"); |
| return NULL; |
| } |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return NULL; |
| } |
| |
| if (is_cmd_for_active_scan_queue) |
| pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; |
| else |
| pdev_queue = |
| &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; |
| queue = &pdev_queue->active_list; |
| return wlan_serialization_get_list_next_node(queue, prev_cmd, |
| ser_pdev_obj); |
| } |
| |
| struct wlan_serialization_command* |
| wlan_serialization_get_pending_list_next_node_using_psoc( |
| struct wlan_objmgr_psoc *psoc, |
| struct wlan_serialization_command *prev_cmd, |
| uint8_t is_cmd_for_pending_scan_queue) |
| { |
| struct wlan_ser_pdev_obj *ser_pdev_obj; |
| qdf_list_t *queue; |
| struct wlan_serialization_pdev_queue *pdev_queue; |
| |
| if (!prev_cmd) { |
| ser_err("invalid prev_cmd"); |
| return NULL; |
| } |
| |
| ser_pdev_obj = wlan_serialization_get_pdev_priv_obj_using_psoc(psoc); |
| if (!ser_pdev_obj) { |
| ser_err("invalid ser_pdev_obj"); |
| return NULL; |
| } |
| if (is_cmd_for_pending_scan_queue) |
| pdev_queue = &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_SCAN]; |
| else |
| pdev_queue = |
| &ser_pdev_obj->pdev_q[SER_PDEV_QUEUE_COMP_NON_SCAN]; |
| queue = &pdev_queue->pending_list; |
| return wlan_serialization_get_list_next_node(queue, prev_cmd, |
| ser_pdev_obj); |
| } |