blob: 7e1710311acf038361cbbc41487f5dea2e7886a3 [file] [log] [blame]
/*
* 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);
}