qcacmn: Provide implementation of command queue operations

Provide the implementation to enqueue, dequeue, cancel,
remove, flush operation of command.

Change-Id: Id62cf320fa0936ed3ddb1264464d35ab5c60e95a
CRs-Fixed: 2000032
此提交包含在:
Krunal Soni
2017-02-01 16:07:09 -08:00
提交者 qcabuildsw
父節點 8a583437e7
當前提交 16641b145a
共有 10 個檔案被更改,包括 1407 行新增63 行删除

查看文件

@@ -192,7 +192,7 @@ struct wlan_serialization_command {
enum wlan_serialization_cmd_type cmd_type;
uint16_t cmd_id;
wlan_serialization_cmd_callback cmd_cb;
uint8_t source;
enum wlan_umac_comp_id source;
bool is_high_priority;
uint16_t cmd_timeout_duration;
union {
@@ -211,7 +211,7 @@ struct wlan_serialization_command {
* @queue_type: Queues from which the command to be cancelled
*/
struct wlan_serialization_queued_cmd_info {
uint8_t requestor;
enum wlan_umac_comp_id requestor;
enum wlan_serialization_cmd_type cmd_type;
uint16_t cmd_id;
enum wlan_serialization_cancel_type req_type;

查看文件

@@ -26,6 +26,7 @@
/* Include files */
#include "wlan_objmgr_psoc_obj.h"
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_utils_i.h"
QDF_STATUS
wlan_serialization_register_comp_info_cb(struct wlan_objmgr_psoc *psoc,
@@ -99,15 +100,40 @@ enum wlan_serialization_cmd_status
wlan_serialization_cancel_request(
struct wlan_serialization_queued_cmd_info *req)
{
serialization_info("serialization cancel request entry");
QDF_STATUS status;
return WLAN_SER_CMD_NOT_FOUND;
serialization_info("serialization cancel request entry");
if (!req) {
serialization_err("given request is empty");
return WLAN_SER_CMD_NOT_FOUND;
}
status = wlan_serialization_validate_cmd(req->requestor, req->cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("req is not valid");
return WLAN_SER_CMD_NOT_FOUND;
}
return wlan_serialization_find_and_cancel_cmd(req);
}
void wlan_serialization_remove_cmd(
struct wlan_serialization_queued_cmd_info *cmd)
{
QDF_STATUS status;
serialization_info("serialization remove request entry");
if (!cmd) {
serialization_err("given request is empty");
QDF_ASSERT(0);
return;
}
status = wlan_serialization_validate_cmd(cmd->requestor, cmd->cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("cmd is not valid");
QDF_ASSERT(0);
return;
}
wlan_serialization_find_and_remove_cmd(cmd);
return;
}
@@ -115,15 +141,33 @@ void wlan_serialization_remove_cmd(
enum wlan_serialization_status
wlan_serialization_request(struct wlan_serialization_command *cmd)
{
serialization_info("serialization queue cmd entry");
bool is_active_cmd_allowed;
QDF_STATUS status;
return WLAN_SER_CMD_NOT_FOUND;
serialization_info("serialization queue cmd entry");
if (!cmd) {
serialization_err("serialization cmd is null");
return WLAN_SER_CMD_DENIED_UNSPECIFIED;
}
status = wlan_serialization_validate_cmd(cmd->source, cmd->cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("cmd is not valid");
return WLAN_SER_CMD_DENIED_UNSPECIFIED;
}
is_active_cmd_allowed = wlan_serialization_is_active_cmd_allowed(cmd);
return wlan_serialization_enqueue_cmd(cmd, is_active_cmd_allowed);
}
void wlan_serialization_flush_cmd(
struct wlan_serialization_queued_cmd_info *cmd)
{
serialization_info("serialization cmd flushed");
if (!cmd) {
serialization_err("cmd is null, can't flush");
return;
}
/* TODO: discuss and fill this API later */
return;
}

查看文件

@@ -20,4 +20,572 @@
* This file defines the routines which are pertinent
* to the dequeue of commands.
*/
#include <wlan_serialization_api.h>
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_utils_i.h"
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_psoc_obj.h>
#include <qdf_list.h>
void wlan_serialization_move_pending_to_active(
enum wlan_serialization_cmd_type cmd_type,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
{
qdf_list_t *pending_queue;
struct wlan_serialization_command_list *cmd_list;
enum wlan_serialization_status status;
qdf_list_node_t *nnode = NULL;
if (!ser_pdev_obj) {
serialization_err("Can't find ser_pdev_obj");
return;
}
if (cmd_type == WLAN_SER_CMD_SCAN)
pending_queue = &ser_pdev_obj->pending_scan_list;
else
pending_queue = &ser_pdev_obj->pending_list;
if (qdf_list_empty(pending_queue)) {
serialization_info("nothing to move from pend to active queue");
serialization_info("cmd_type - %d", cmd_type);
return;
}
if (QDF_STATUS_SUCCESS != qdf_list_peek_front(pending_queue, &nnode)) {
serialization_err("can't read from pending queue");
serialization_info("cmd_type - %d", cmd_type);
return;
}
cmd_list = qdf_container_of(nnode,
struct wlan_serialization_command_list, node);
/*
* Idea is to peek command from pending queue, and try to
* push to active queue. If command goes to active queue
* successfully then remove the command from pending queue which
* we previously peeked.
*
* By doing this way, we will make sure that command will be removed
* from pending queue only when it was able to make it to active queue
*/
status = wlan_serialization_enqueue_cmd(&cmd_list->cmd, true);
if (WLAN_SER_CMD_ACTIVE != status) {
serialization_err("Can't move cmd to activeQ id-%d type-%d",
cmd_list->cmd.cmd_id, cmd_list->cmd.cmd_type);
return;
}
wlan_serialization_put_back_to_global_list(pending_queue,
ser_pdev_obj, cmd_list);
return;
}
/**
* wlan_serialization_remove_all_cmd_from_queue() - Remove cmd which matches
* @queue: queue from where command needs to be removed
* @ser_pdev_obj: pointer to serialization object
* @pdev: pointer to pdev
* @vdev: pointer to vdev
* @cmd: pointer to cmd
* @is_active_queue: to check if command matching is for active queue
*
* This API will remove one or more commands which match the given parameters
* interms of argument. For example, if user request all commands to removed
* which matches "vdev" then iterate through all commands, find out and remove
* command which matches vdev object.
*
* Return: enum wlan_serialization_cmd_status
*/
static enum wlan_serialization_cmd_status
wlan_serialization_remove_all_cmd_from_queue(qdf_list_t *queue,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
struct wlan_serialization_command *cmd, uint8_t is_active_queue)
{
uint32_t qsize;
struct wlan_serialization_command_list *cmd_list;
qdf_list_node_t *nnode = NULL, *pnode = NULL;
enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
QDF_STATUS qdf_status;
qsize = qdf_list_size(queue);
while (qsize--) {
if (wlan_serialization_get_cmd_from_queue(queue, &nnode)
!= 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)))) {
pnode = nnode;
continue;
}
/*
* active queue can't be removed directly, requester needs to
* wait for active command response and send remove request for
* active command seperately
*/
if (is_active_queue) {
status = WLAN_SER_CMD_IN_ACTIVE_LIST;
break;
}
/*
* call pending cmd's callback to notify that
* it is being removed
*/
if (cmd_list->cmd.cmd_cb) {
/* caller should now do necessary clean up */
cmd_list->cmd.cmd_cb(&cmd_list->cmd,
WLAN_SER_CB_CANCEL_CMD);
/* caller should release the memory */
cmd_list->cmd.cmd_cb(&cmd_list->cmd,
WLAN_SER_CB_RELEASE_MEM_CMD);
}
qdf_status = wlan_serialization_put_back_to_global_list(queue,
ser_pdev_obj, cmd_list);
if (QDF_STATUS_SUCCESS != qdf_status) {
serialization_err("can't remove cmd from queue");
status = WLAN_SER_CMD_NOT_FOUND;
break;
}
nnode = pnode;
/* If cmd was on active list then we wouldn't have come here */
status = WLAN_SER_CMD_IN_PENDING_LIST;
}
return status;
}
/**
* wlan_serialization_remove_cmd_from_given_queue() - to remove command from
* given queue
* @queue: queue from which command needs to be removed
* @cmd: command to match in the queue
* @ser_pdev_obj: pointer to private pdev serialization object
*
* This API takes the queue, it matches the provided command from this queue
* and removes it. Before removing the command, it will notify the caller
* that if it needs to remove any memory allocated by caller.
*
* Return: none
*/
static void wlan_serialization_remove_cmd_from_given_queue(qdf_list_t *queue,
struct wlan_serialization_command *cmd,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj)
{
uint32_t qsize;
struct wlan_serialization_command_list *cmd_list;
qdf_list_node_t *nnode = NULL;
QDF_STATUS status;
if (!cmd)
return;
qsize = qdf_list_size(queue);
while (qsize--) {
status = wlan_serialization_get_cmd_from_queue(queue, &nnode);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("can't peek cmd_id[%d] type[%d]",
cmd->cmd_id, cmd->cmd_type);
break;
}
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))
continue;
if (cmd_list->cmd.vdev != cmd->vdev)
continue;
if (cmd_list->cmd.cmd_cb) {
/* caller should release the memory */
cmd_list->cmd.cmd_cb(&cmd_list->cmd,
WLAN_SER_CB_RELEASE_MEM_CMD);
}
status = wlan_serialization_put_back_to_global_list(queue,
ser_pdev_obj, cmd_list);
if (QDF_STATUS_SUCCESS != status)
serialization_err("Fail to add to free pool type[%d]",
cmd->cmd_type);
/*
* zero out the command, so caller would know that command has
* been removed
*/
qdf_mem_zero(cmd, sizeof(struct wlan_serialization_command));
break;
}
}
/**
* wlan_serialization_remove_cmd_from_active_queue() - helper function to remove
* cmd from active queue
* @psoc: pointer to psoc
* @obj: pointer to object getting passed by object manager
* @arg: argument passed by caller to object manager which comes to this cb
*
* caller provide this API as callback to object manager, and in turn
* object manager iterate through each pdev and call this API callback.
*
* Return: none
*/
static void
wlan_serialization_remove_cmd_from_active_queue(struct wlan_objmgr_psoc *psoc,
void *obj, void *arg)
{
qdf_list_t *queue;
struct wlan_objmgr_pdev *pdev = obj;
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
struct wlan_serialization_command *cmd = arg;
if (!pdev || !cmd) {
serialization_err("Invalid param");
return;
}
ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_SERIALIZATION);
if (!ser_pdev_obj) {
serialization_err("Invalid ser_pdev_obj");
return;
}
if (cmd->cmd_type == WLAN_SER_CMD_SCAN)
queue = &ser_pdev_obj->active_scan_list;
else
queue = &ser_pdev_obj->active_list;
if (qdf_list_empty(queue)) {
serialization_err("Empty queue");
return;
}
wlan_serialization_remove_cmd_from_given_queue(queue, cmd,
ser_pdev_obj);
return;
}
/**
* wlan_serialization_remove_cmd_from_active_queue() - helper function to remove
* cmd from pending queue
* @psoc: pointer to psoc
* @obj: pointer to object getting passed by object manager
* @arg: argument passed by caller to object manager which comes to this cb
*
* caller provide this API as callback to object manager, and in turn
* object manager iterate through each pdev and call this API callback.
*
* Return: none
*/
static void
wlan_serialization_remove_cmd_from_pending_queue(struct wlan_objmgr_psoc *psoc,
void *obj, void *arg)
{
qdf_list_t *queue;
struct wlan_objmgr_pdev *pdev = obj;
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
struct wlan_serialization_command *cmd = arg;
if (!pdev || !cmd) {
serialization_err("Invalid param");
return;
}
ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_SERIALIZATION);
if (!ser_pdev_obj) {
serialization_err("Invalid ser_pdev_obj");
return;
}
if (cmd->cmd_type == WLAN_SER_CMD_SCAN)
queue = &ser_pdev_obj->pending_scan_list;
else
queue = &ser_pdev_obj->pending_list;
if (qdf_list_empty(queue)) {
serialization_err("Empty queue");
return;
}
wlan_serialization_remove_cmd_from_given_queue(queue,
cmd, ser_pdev_obj);
return;
}
/**
* wlan_serialization_is_cmd_removed() - to check if requested command is
* removed
* @psoc: pointer to soc
* @cmd: given command to remove
* @check_active_queue: flag to find out whether command needs to be removed
* from active queue or pending queue
*
* Return: true if removed else false
*/
static bool
wlan_serialization_is_cmd_removed(struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd,
bool check_active_queue)
{
if (!psoc) {
serialization_err("Invalid psoc");
return false;
}
if (check_active_queue)
wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
wlan_serialization_remove_cmd_from_active_queue,
cmd, 0);
else
wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
wlan_serialization_remove_cmd_from_pending_queue,
cmd, 0);
if (cmd->vdev == NULL)
return true;
return false;
}
enum wlan_serialization_cmd_status
wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
uint8_t only_active_cmd)
{
enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_psoc *psoc;
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
struct wlan_serialization_command cmd_backup;
enum wlan_serialization_cmd_type cmd_type;
bool is_cmd_removed;
if (!cmd) {
serialization_err("NULL command");
return status;
}
/* Dequeue process
* 1) peek through command structure and see what is the command type
* 2) two main types of commands to process
* a) SCAN
* b) NON-SCAN
* 3) for each command there are seperate command queues per pdev
* 4) iterate through every pdev object and find the command and remove
*/
pdev = wlan_serialization_get_pdev_from_cmd(cmd);
if (pdev == NULL) {
serialization_err("invalid pdev");
return status;
}
psoc = wlan_pdev_get_psoc(pdev);
if (psoc == NULL) {
serialization_err("invalid psoc");
return status;
}
/* get priv object by wlan_objmgr_vdev_get_comp_private_obj */
ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_UMAC_COMP_SERIALIZATION);
if (!ser_pdev_obj) {
serialization_err("ser_pdev_obj is empty");
return status;
}
/*
* Pass the copy of command, instead of actual command because
* wlan_serialization_is_cmd_removed() api cleans the command
* buffer up on successful removal. We may need to use the command's
* content to stop the timer and etc.
*/
qdf_mem_copy(&cmd_backup, cmd,
sizeof(struct wlan_serialization_command));
cmd_type = cmd->cmd_type;
/* find and remove from active list */
if (only_active_cmd) {
wlan_serialization_find_and_stop_timer(psoc, cmd);
is_cmd_removed = wlan_serialization_is_cmd_removed(psoc,
&cmd_backup, true);
if (true == is_cmd_removed) {
/*
* command is removed from active queue. now we have a
* room in active queue, so we will move from relevant
* pending queue to active queue
*/
wlan_serialization_move_pending_to_active(cmd_type,
ser_pdev_obj);
status = WLAN_SER_CMD_IN_ACTIVE_LIST;
} else {
serialization_err("cmd_type[%d], cmd_id[%d], vdev[%p]",
cmd->cmd_type, cmd->cmd_id, cmd->vdev);
/*
* if you come here means there is a possibility
* that we couldn't find the command in active queue
* which user has requested to remove or we couldn't
* remove command from active queue and timer has been
* stopped, so active queue may possibly stuck.
*/
QDF_ASSERT(0);
status = WLAN_SER_CMD_NOT_FOUND;
}
serialization_info("Request to remove only from active queue");
return status;
}
qdf_mem_copy(&cmd_backup, cmd,
sizeof(struct wlan_serialization_command));
/* find and remove from pending list */
if (wlan_serialization_is_cmd_removed(psoc, &cmd_backup, false)) {
if (status != WLAN_SER_CMD_IN_ACTIVE_LIST)
status = WLAN_SER_CMD_IN_PENDING_LIST;
else
status = WLAN_SER_CMDS_IN_ALL_LISTS;
}
return status;
}
/**
* wlan_serialization_cmd_cancel_handler() - helper func to cancel cmd
* @ser_obj: private pdev ser obj
* @cmd: pointer to command
* @pdev: pointer to pdev
* @vdev: pointer to vdev
* @cmd_type: pointer to cmd_type
*
* This API will decide from which queue, command needs to be cancelled
* and pass that queue and other parameter required to cancel the command
* to helper function.
*
* Return: wlan_serialization_cmd_status
*/
static enum wlan_serialization_cmd_status
wlan_serialization_cmd_cancel_handler(
struct wlan_serialization_pdev_priv_obj *ser_obj,
struct wlan_serialization_command *cmd,
struct wlan_objmgr_pdev *pdev, struct wlan_objmgr_vdev *vdev,
enum wlan_serialization_cmd_type cmd_type)
{
enum wlan_serialization_cmd_status status;
qdf_list_t *queue;
if (!ser_obj) {
serialization_err("invalid serial object");
return WLAN_SER_CMD_NOT_FOUND;
}
/* remove pending commands first */
if (cmd_type == WLAN_SER_CMD_SCAN)
queue = &ser_obj->pending_scan_list;
else
queue = &ser_obj->pending_list;
/* try and remove first from pending list */
status = wlan_serialization_remove_all_cmd_from_queue(queue,
ser_obj, pdev, vdev, cmd, false);
if (cmd_type == WLAN_SER_CMD_SCAN)
queue = &ser_obj->active_scan_list;
else
queue = &ser_obj->active_list;
/* try and remove next from active list */
if (WLAN_SER_CMD_IN_ACTIVE_LIST ==
wlan_serialization_remove_all_cmd_from_queue(queue,
ser_obj, pdev, vdev, cmd, true)) {
if (WLAN_SER_CMD_IN_PENDING_LIST == status)
status = WLAN_SER_CMDS_IN_ALL_LISTS;
else
status = WLAN_SER_CMD_IN_ACTIVE_LIST;
}
return status;
}
enum wlan_serialization_cmd_status
wlan_serialization_find_and_cancel_cmd(
struct wlan_serialization_queued_cmd_info *cmd_info)
{
struct wlan_serialization_command cmd;
enum wlan_serialization_cmd_status status = WLAN_SER_CMD_NOT_FOUND;
struct wlan_serialization_pdev_priv_obj *ser_obj = NULL;
struct wlan_objmgr_pdev *pdev;
if (!cmd_info) {
serialization_err("Invalid cmd_info");
return WLAN_SER_CMD_NOT_FOUND;
}
cmd.cmd_id = cmd_info->cmd_id;
cmd.cmd_type = cmd_info->cmd_type;
cmd.vdev = cmd_info->vdev;
pdev = wlan_serialization_get_pdev_from_cmd(&cmd);
if (!pdev) {
serialization_err("Invalid pdev");
return WLAN_SER_CMD_NOT_FOUND;
}
ser_obj = wlan_serialization_get_pdev_priv_obj(pdev);
if (!ser_obj) {
serialization_err("Invalid ser_obj");
return WLAN_SER_CMD_NOT_FOUND;
}
switch (cmd_info->req_type) {
case WLAN_SER_CANCEL_SINGLE_SCAN:
/* remove scan cmd which matches the given cmd struct */
status = wlan_serialization_cmd_cancel_handler(ser_obj,
&cmd, NULL, NULL, cmd.cmd_type);
break;
case WLAN_SER_CANCEL_PDEV_SCANS:
/* remove all scan cmds which matches the pdev object */
status = wlan_serialization_cmd_cancel_handler(ser_obj,
NULL,
wlan_vdev_get_pdev(cmd.vdev),
NULL, cmd.cmd_type);
break;
case WLAN_SER_CANCEL_VDEV_SCANS:
/* remove all scan cmds which matches the vdev object */
status = wlan_serialization_cmd_cancel_handler(ser_obj,
NULL, NULL,
cmd.vdev, cmd.cmd_type);
break;
case WLAN_SER_CANCEL_NON_SCAN_CMD:
/* remove nonscan cmd which matches the given cmd */
status = wlan_serialization_cmd_cancel_handler(ser_obj,
&cmd, NULL, NULL, cmd.cmd_type);
break;
default:
serialization_err("Invalid request");
}
return status;
}
QDF_STATUS wlan_serialization_find_and_remove_cmd(
struct wlan_serialization_queued_cmd_info *cmd_info)
{
struct wlan_serialization_command cmd;
if (!cmd_info) {
serialization_err("Invalid cmd_info");
return QDF_STATUS_E_FAILURE;
}
cmd.cmd_id = cmd_info->cmd_id;
cmd.cmd_type = cmd_info->cmd_type;
cmd.vdev = cmd_info->vdev;
if (WLAN_SER_CMD_IN_ACTIVE_LIST !=
wlan_serialization_dequeue_cmd(&cmd, true)) {
serialization_err("Can't dequeue requested cmd_id[%d] type[%d]",
cmd_info->cmd_id, cmd_info->cmd_type);
return QDF_STATUS_E_FAILURE;
}
return QDF_STATUS_SUCCESS;
}

查看文件

@@ -20,4 +20,171 @@
* This file defines the routines which are pertinent
* to the queuing of commands.
*/
#include <wlan_serialization_api.h>
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_utils_i.h"
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_psoc_obj.h>
#include <qdf_list.h>
static enum wlan_serialization_status
wlan_serialization_add_cmd_to_given_queue(qdf_list_t *queue,
struct wlan_serialization_command *cmd,
struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
uint8_t is_cmd_for_active_queue)
{
struct wlan_serialization_command_list *cmd_list;
enum wlan_serialization_status status;
QDF_STATUS qdf_status;
qdf_list_node_t *nnode;
if (!cmd || !queue || !ser_pdev_obj || !psoc) {
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_err("list is full, can't add more");
QDF_BUG(0);
return WLAN_SER_CMD_DENIED_LIST_FULL;
}
if (qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list,
&nnode) != QDF_STATUS_SUCCESS) {
serialization_err("Failed to get cmd buffer from global pool");
return WLAN_SER_CMD_DENIED_UNSPECIFIED;
}
cmd_list = qdf_container_of(nnode,
struct wlan_serialization_command_list, node);
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);
else
qdf_status = qdf_list_insert_back(queue, &cmd_list->node);
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(
&ser_pdev_obj->global_cmd_pool_list,
&cmd_list->node);
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;
}
if (is_cmd_for_active_queue) {
/*
* command is already pushed to active queue above
* now start the timer and notify requestor
*/
wlan_serialization_find_and_start_timer(psoc,
&cmd_list->cmd);
if (cmd_list->cmd.cmd_cb) {
/*
* Remember that serialization module may send
* this callback in same context through which it
* received the serialization request. Due to which
* it is caller's responsibility to ensure acquiring
* and releasing its own lock appropriately.
*/
qdf_status = cmd_list->cmd.cmd_cb(&cmd_list->cmd,
WLAN_SER_CB_ACTIVATE_CMD);
if (qdf_status != QDF_STATUS_SUCCESS) {
wlan_serialization_find_and_stop_timer(psoc,
&cmd_list->cmd);
wlan_serialization_put_back_to_global_list(
queue, ser_pdev_obj, cmd_list);
wlan_serialization_move_pending_to_active(
cmd_list->cmd.cmd_type,
ser_pdev_obj);
}
}
status = WLAN_SER_CMD_ACTIVE;
} else {
status = WLAN_SER_CMD_PENDING;
}
return status;
}
enum wlan_serialization_status
wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd,
uint8_t is_cmd_for_active_queue)
{
enum wlan_serialization_status status = WLAN_SER_CMD_DENIED_UNSPECIFIED;
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_psoc *psoc;
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
qdf_list_t *queue;
/* Enqueue process
* 1) peek through command structure and see what is the command type
* 2) two main types of commands to process
* a) SCAN
* b) NON-SCAN
* 3) for each command there are seperate command queues per pdev
* 4) pull pdev from vdev structure and get the command queue associated
* with that pdev and try to enqueue on those queue
* 5) Thumb rule:
* a) There could be only 1 active non-scan command at a
* time including all total non-scan commands of all pdevs.
*
* example: pdev1 has 1 non-scan active command and
* pdev2 got 1 non-scan command then that command should go to
* pdev2's pending queue
*
* b) There could be only N number of scan commands at a time
* including all total scan commands of all pdevs
*
* example: Let's say N=8,
* pdev1's vdev1 has 5 scan command, pdev2's vdev1 has 3
* scan commands, if we get scan request on vdev2 then it will go
* to pending queue of vdev2 as we reached max allowed scan active
* command.
*/
if (!cmd) {
serialization_err("NULL command");
return status;
}
pdev = wlan_serialization_get_pdev_from_cmd(cmd);
if (pdev == NULL) {
serialization_err("invalid pdev");
return status;
}
psoc = wlan_pdev_get_psoc(pdev);
if (psoc == NULL) {
serialization_err("invalid psoc");
return status;
}
/* get priv object by wlan_objmgr_vdev_get_comp_private_obj */
ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_UMAC_COMP_SERIALIZATION);
if (!ser_pdev_obj) {
serialization_err("Can't find ser_pdev_obj");
return status;
}
serialization_debug("command high_priority[%d] cmd_type[%d] cmd_id[%d]",
cmd->is_high_priority, cmd->cmd_type, cmd->cmd_id);
if (cmd->cmd_type == WLAN_SER_CMD_SCAN) {
if (is_cmd_for_active_queue)
queue = &ser_pdev_obj->active_scan_list;
else
queue = &ser_pdev_obj->pending_scan_list;
} else {
if (is_cmd_for_active_queue)
queue = &ser_pdev_obj->active_list;
else
queue = &ser_pdev_obj->pending_list;
}
return wlan_serialization_add_cmd_to_given_queue(queue, cmd, psoc,
ser_pdev_obj, is_cmd_for_active_queue);
}

查看文件

@@ -29,6 +29,7 @@
#include "wlan_objmgr_psoc_obj.h"
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_rules_i.h"
#include "wlan_serialization_utils_i.h"
/**
* wlan_serialization_apply_rules_cb_init() - Apply rule callback init
@@ -95,6 +96,11 @@ QDF_STATUS wlan_serialization_psoc_close(struct wlan_objmgr_psoc *psoc)
serialization_err("invalid ser_soc_obj");
return QDF_STATUS_E_FAILURE;
}
/* clean up all timers before exiting */
status = wlan_serialization_cleanup_all_timers(ser_soc_obj);
if (status != QDF_STATUS_SUCCESS)
serialization_err("ser cleanning up all timer failed");
qdf_mem_free(ser_soc_obj->timers);
ser_soc_obj->timers = NULL;
ser_soc_obj->max_active_cmds = 0;
@@ -160,15 +166,15 @@ static void wlan_serialization_destroy_cmd_pool(
{
qdf_list_node_t *node = NULL;
struct wlan_serialization_command_list *cmd_list_node;
struct wlan_serialization_command_list *cmd_list;
while (!qdf_list_empty(&ser_pdev_obj->global_cmd_pool_list)) {
qdf_list_remove_front(&ser_pdev_obj->global_cmd_pool_list,
&node);
cmd_list_node = (struct wlan_serialization_command_list *)node;
cmd_list = (struct wlan_serialization_command_list *)node;
serialization_info("Node being freed from global pool %p",
cmd_list_node);
qdf_mem_free(cmd_list_node);
cmd_list);
qdf_mem_free(cmd_list);
}
qdf_list_destroy(&ser_pdev_obj->global_cmd_pool_list);

查看文件

@@ -26,9 +26,6 @@
#include "wlan_objmgr_cmn.h"
#include "wlan_objmgr_psoc_obj.h"
#include "wlan_objmgr_pdev_obj.h"
#include "wlan_serialization_api.h"
#include "wlan_serialization_rules_i.h"
#include "wlan_serialization_utils_i.h"
#include "qdf_mc_timer.h"
#define WLAN_SERIALIZATION_MAX_GLOBAL_POOL_CMDS 24
@@ -53,36 +50,6 @@
#define serialization_debug(format, args...) \
serialization_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args)
/**
* struct wlan_serialization_timer - Timer used for serialization
* @cmd: Cmd to which the timer is linked
* @timer: Timer associated with the command
*
* Timers are allocated statically during init, one each for the
* maximum active commands permitted in the system. Once a cmd is
* moved from pending list to active list, the timer is activated
* and once the cmd is completed, the timer is cancelled. Timer is
* also cancelled if the command is aborted
*
* The timers are maintained per psoc. A timer is associated to
* unique combination of pdev, cmd_type and cmd_id.
*/
struct wlan_serialization_timer {
struct wlan_serialization_command *cmd;
qdf_mc_timer_t timer;
};
/**
* struct wlan_serialization_command_list - List of commands to be serialized
* @node: Node identifier in the list
* @cmd: Command to be serialized
*/
struct wlan_serialization_command_list {
qdf_list_node_t node;
struct wlan_serialization_command cmd;
};
/**
* wlan_serialization_psoc_obj_create_notification() - PSOC obj create callback
* @psoc: PSOC object

查看文件

@@ -16,7 +16,8 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_rules_i.h"
bool wlan_apply_scan_rules(union wlan_serialization_rules_info *info)
{
return true;

查看文件

@@ -22,6 +22,7 @@
*/
#ifndef __WLAN_SERIALIZATION_RULES_I_H
#define __WLAN_SERIALIZATION_RULES_I_H
#include "wlan_serialization_api.h"
/**
* wlan_apply_scan_rules() - Apply scan rules
* @status: return information status fetched from other components

查看文件

@@ -21,6 +21,418 @@
*/
#include "wlan_serialization_utils_i.h"
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_api.h"
#include "wlan_objmgr_vdev_obj.h"
#include "wlan_objmgr_pdev_obj.h"
#include "qdf_mc_timer.h"
QDF_STATUS
wlan_serialization_put_back_to_global_list(qdf_list_t *queue,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
struct wlan_serialization_command_list *cmd_list)
{
QDF_STATUS status;
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 (QDF_STATUS_SUCCESS != status) {
serialization_err("can't remove cmd from queue");
/* assert to catch any leaks */
QDF_ASSERT(0);
return status;
}
serialization_info("cmd_id-%d, cmd_type-%d", cmd_list->cmd.cmd_id,
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);
if (QDF_STATUS_SUCCESS != status) {
serialization_err("can't put command back to global pool");
QDF_ASSERT(0);
return status;
}
return status;
}
struct wlan_objmgr_pdev*
wlan_serialization_get_pdev_from_cmd(struct wlan_serialization_command *cmd)
{
struct wlan_objmgr_pdev *pdev = NULL;
if (!cmd) {
serialization_err("invalid cmd");
return pdev;
}
pdev = wlan_vdev_get_pdev(cmd->vdev);
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_STATUS status;
qdf_list_node_t *pnode;
pnode = *nnode;
if (!pnode)
status = qdf_list_peek_front(queue, nnode);
else
status = qdf_list_peek_next(queue, pnode, nnode);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("can't get next node from queue");
return status;
}
return QDF_STATUS_SUCCESS;
}
/**
* wlan_serialization_timer_destroy() - destroys the timer
* @ser_timer: pointer to particular timer
*
* This API destroys the memory allocated by timer and assigns cmd member of
* that timer structure to NULL
*
* Return: QDF_STATUS
*/
static QDF_STATUS wlan_serialization_timer_destroy(
struct wlan_serialization_timer *ser_timer)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
if (!ser_timer || !ser_timer->cmd) {
serialization_debug("Invalid ser_timer");
return status;
}
status = qdf_mc_timer_destroy(&ser_timer->timer);
if (!QDF_IS_STATUS_SUCCESS(status)) {
serialization_err("Failed to destroy timer for cmd_id[%d]",
ser_timer->cmd->cmd_id);
QDF_ASSERT(0);
return status;
}
ser_timer->cmd = NULL;
return status;
}
/**
* wlan_serialization_generic_timer_callback() - timer callback when timer fire
* @arg: argument that timer passes to this callback
*
* All the timers in serialization module calls this callback when they fire,
* and this API in turn calls command specific timeout callback and remove
* timed-out command from active queue and move any pending command to active
* queue of same cmd_type.
*
* Return: none
*/
static void wlan_serialization_generic_timer_callback(void *arg)
{
struct wlan_serialization_timer *timer = arg;
struct wlan_serialization_command *cmd = timer->cmd;
if (!cmd) {
serialization_err("command not found");
QDF_ASSERT(0);
return;
}
if (cmd->cmd_cb) {
cmd->cmd_cb(cmd->umac_cmd, WLAN_SER_CB_ACTIVE_CMD_TIMEOUT);
cmd->cmd_cb(cmd->umac_cmd, WLAN_SER_CB_RELEASE_MEM_CMD);
}
serialization_err("active command timeout for cmd_id[%d]", cmd->cmd_id);
if (cmd->cmd_type != WLAN_SER_CMD_SCAN)
QDF_BUG(0);
/*
* dequeue cmd API will cleanup and destroy the timer. If it fails to
* dequeue command then we have to destroy the timer.
*/
if (WLAN_SER_CMD_NOT_FOUND == wlan_serialization_dequeue_cmd(cmd, true))
wlan_serialization_timer_destroy(timer);
}
/**
* wlan_serialization_stop_timer() - to stop particular timer
* @ser_timer: pointer to serialization timer
*
* This API stops the particular timer
*
* Return: QDF_STATUS
*/
static QDF_STATUS
wlan_serialization_stop_timer(struct wlan_serialization_timer *ser_timer)
{
QDF_TIMER_STATE state;
QDF_STATUS status;
state = qdf_mc_timer_get_current_state(&ser_timer->timer);
if (QDF_TIMER_STATE_RUNNING != state ||
QDF_TIMER_STATE_STARTING != state) {
serialization_debug("nothing to stop");
wlan_serialization_timer_destroy(ser_timer);
return QDF_STATUS_SUCCESS;
}
status = qdf_mc_timer_stop(&ser_timer->timer);
if (!QDF_IS_STATUS_SUCCESS(status)) {
serialization_err("Failed to stop timer");
/* to catch the bug */
QDF_ASSERT(0);
return status;
}
wlan_serialization_timer_destroy(ser_timer);
status = QDF_STATUS_SUCCESS;
}
QDF_STATUS wlan_serialization_cleanup_all_timers(
struct wlan_serialization_psoc_priv_obj *psoc_ser_obj)
{
struct wlan_serialization_timer *ser_timer;
QDF_STATUS status = QDF_STATUS_SUCCESS;
uint32_t i = 0;
if (!psoc_ser_obj) {
serialization_err("Invalid psoc_ser_obj");
return QDF_STATUS_E_FAILURE;
}
for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
ser_timer = &psoc_ser_obj->timers[i];
if (!ser_timer->cmd)
continue;
status = wlan_serialization_stop_timer(ser_timer);
if (QDF_STATUS_SUCCESS != status) {
/* lets not break the loop but report error */
serialization_err("some error in stopping timer");
}
}
return status;
}
QDF_STATUS
wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd)
{
struct wlan_serialization_psoc_priv_obj *psoc_ser_obj;
struct wlan_serialization_timer *ser_timer;
QDF_STATUS status = QDF_STATUS_E_FAILURE;
int i = 0;
if (!psoc || !cmd) {
serialization_err("invalid param");
return status;
}
psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc);
/*
* Here cmd_id and cmd_type are used to locate the timer being
* associated with command. For scan command, cmd_id is expected to
* be unique and For non-scan command, there should be only one active
* command per pdev
*/
for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
ser_timer = &psoc_ser_obj->timers[i];
if (!(ser_timer->cmd) ||
(ser_timer->cmd->cmd_id != cmd->cmd_id) ||
(ser_timer->cmd->cmd_type != cmd->cmd_type) ||
(ser_timer->cmd->vdev != cmd->vdev))
continue;
status = wlan_serialization_stop_timer(ser_timer);
if (QDF_STATUS_SUCCESS != status) {
serialization_err("Failed to stop timer for cmd_id[%d]",
cmd->cmd_id);
}
break;
}
if (QDF_STATUS_SUCCESS != status) {
serialization_err("can't find timer for cmd_type[%d]",
cmd->cmd_type);
}
return status;
}
QDF_STATUS
wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd)
{
QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct wlan_serialization_psoc_priv_obj *psoc_ser_obj;
struct wlan_serialization_timer *ser_timer;
int i = 0;
if (!psoc || !cmd) {
serialization_err("invalid param");
return status;
}
psoc_ser_obj = wlan_serialization_get_psoc_priv_obj(psoc);
for (i = 0; psoc_ser_obj->max_active_cmds > i; i++) {
/* Keep trying timer */
ser_timer = &psoc_ser_obj->timers[i];
if (ser_timer->cmd)
continue;
/* Remember timer is pointing to command */
ser_timer->cmd = cmd;
if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_init(&ser_timer->timer,
QDF_TIMER_TYPE_SW,
wlan_serialization_generic_timer_callback,
ser_timer))) {
serialization_err("Failed to init timer cmdid [%d]",
cmd->cmd_id);
QDF_ASSERT(0);
continue;
}
if (!QDF_IS_STATUS_SUCCESS(qdf_mc_timer_start(&ser_timer->timer,
cmd->cmd_timeout_duration))) {
serialization_err("Failed to start timer cmdid [%d]",
cmd->cmd_id);
wlan_serialization_timer_destroy(ser_timer);
QDF_ASSERT(0);
continue;
}
status = QDF_STATUS_SUCCESS;
break;
}
return status;
}
/**
* wlan_serialization_active_scan_cmd_count_handler() - count active scan cmds
* @psoc: pointer to soc strucutre
* @obj : pointer to pdev object
* @arg: pointer to argument
*
* This API will be called while iterating each pdev object and it will count
* number of scan commands present in that pdev object's active queue. count
* will be updated in *arg
*
* Return: none
*/
static void
wlan_serialization_active_scan_cmd_count_handler(struct wlan_objmgr_psoc *psoc,
void *obj, void *arg)
{
struct wlan_objmgr_pdev *pdev = obj;
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
uint32_t *count = arg;
if (!pdev) {
serialization_err("invalid pdev");
return;
}
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);
}
/**
* wlan_serialization_is_active_scan_cmd_allowed() - find if scan cmd allowed
* @pdev: pointer to pdev object
*
* This API will be called to find out if active scan cmd is allowed. It has
* to iterate through all pdev to find out total number of active scan cmds.
* If total number of active scan cmds reach to allowed threshold then don't
* allow more scan cmd.
*
* Return: true or false
*/
static bool
wlan_serialization_is_active_scan_cmd_allowed(struct wlan_objmgr_pdev *pdev)
{
uint32_t count = 0;
struct wlan_objmgr_psoc *psoc;
if (!pdev) {
serialization_err("invalid pdev");
return false;
}
psoc = wlan_pdev_get_psoc(pdev);
if (!psoc) {
serialization_err("invalid psoc");
return false;
}
wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP,
wlan_serialization_active_scan_cmd_count_handler,
&count, 0);
if (count < WLAN_SERIALIZATION_MAX_ACTIVE_SCAN_CMDS) {
serialization_notice("count is [%d]", count);
return true;
}
return false;
}
/**
* wlan_serialization_is_active_nonscan_cmd_allowed() - find if cmd allowed
* @pdev: pointer to pdev object
*
* This API will be called to find out if non scan cmd is allowed.
*
* Return: true or false
*/
static bool
wlan_serialization_is_active_nonscan_cmd_allowed(struct wlan_objmgr_pdev *pdev)
{
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj;
if (!pdev) {
serialization_err("invalid pdev");
return false;
}
ser_pdev_obj = wlan_objmgr_pdev_get_comp_private_obj(
pdev, WLAN_UMAC_COMP_SERIALIZATION);
if (!ser_pdev_obj) {
serialization_err("invalid ser_pdev_obj");
return false;
}
if (qdf_list_empty(&ser_pdev_obj->active_list))
return true;
return false;
}
bool
wlan_serialization_is_active_cmd_allowed(struct wlan_serialization_command *cmd)
{
struct wlan_objmgr_pdev *pdev;
pdev = wlan_serialization_get_pdev_from_cmd(cmd);
if (!pdev) {
serialization_err("NULL pdev");
return false;
}
if (cmd->cmd_type == WLAN_SER_CMD_SCAN)
return wlan_serialization_is_active_scan_cmd_allowed(pdev);
else
return wlan_serialization_is_active_nonscan_cmd_allowed(pdev);
}
QDF_STATUS wlan_serialization_validate_cmd(
enum wlan_umac_comp_id comp_id,

查看文件

@@ -25,33 +25,39 @@
/* Include files */
#include "qdf_status.h"
#include "qdf_list.h"
#include "qdf_mc_timer.h"
#include "wlan_objmgr_cmn.h"
#include "wlan_objmgr_global_obj.h"
#include "wlan_objmgr_psoc_obj.h"
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_rules_i.h"
/**
* struct wlan_serialization_psoc_priv_obj - psoc obj data for serialization
* @wlan_serialization_module_state_cb - module level callback
* @wlan_serialization_apply_rules_cb - pointer to apply rules on the cmd
* @timers - Timers associated with the active commands
* @max_axtive_cmds - Maximum active commands allowed
* struct wlan_serialization_timer - Timer used for serialization
* @cmd: Cmd to which the timer is linked
* @timer: Timer associated with the command
*
* Serialization component takes a command as input and checks whether to
* allow/deny the command. It will use the module level callback registered
* by each component to fetch the information needed to apply the rules.
* Once the information is available, the rules callback registered for each
* command internally by serialization will be applied to determine the
* checkpoint for the command. If allowed, command will be put into active/
* pending list and each active command is associated with a timer.
* Timers are allocated statically during init, one each for the
* maximum active commands permitted in the system. Once a cmd is
* moved from pending list to active list, the timer is activated
* and once the cmd is completed, the timer is cancelled. Timer is
* also cancelled if the command is aborted
*
* The timers are maintained per psoc. A timer is associated to
* unique combination of pdev, cmd_type and cmd_id.
*/
struct wlan_serialization_psoc_priv_obj {
wlan_serialization_comp_info_cb comp_info_cb[
WLAN_SER_CMD_MAX][WLAN_UMAC_COMP_ID_MAX];
wlan_serialization_apply_rules_cb apply_rules_cb[WLAN_SER_CMD_MAX];
struct wlan_serialization_timer *timers;
uint8_t max_active_cmds;
struct wlan_serialization_timer {
struct wlan_serialization_command *cmd;
qdf_mc_timer_t timer;
};
/**
* struct wlan_serialization_command_list - List of commands to be serialized
* @node: Node identifier in the list
* @cmd: Command to be serialized
*/
struct wlan_serialization_command_list {
qdf_list_node_t node;
struct wlan_serialization_command cmd;
};
/**
@@ -79,6 +85,178 @@ struct wlan_serialization_pdev_priv_obj {
qdf_list_t global_cmd_pool_list;
};
/**
* struct wlan_serialization_psoc_priv_obj - psoc obj data for serialization
* @wlan_serialization_module_state_cb - module level callback
* @wlan_serialization_apply_rules_cb - pointer to apply rules on the cmd
* @timers - Timers associated with the active commands
* @max_axtive_cmds - Maximum active commands allowed
*
* Serialization component takes a command as input and checks whether to
* allow/deny the command. It will use the module level callback registered
* by each component to fetch the information needed to apply the rules.
* Once the information is available, the rules callback registered for each
* command internally by serialization will be applied to determine the
* checkpoint for the command. If allowed, command will be put into active/
* pending list and each active command is associated with a timer.
*/
struct wlan_serialization_psoc_priv_obj {
wlan_serialization_comp_info_cb comp_info_cb[
WLAN_SER_CMD_MAX][WLAN_UMAC_COMP_ID_MAX];
wlan_serialization_apply_rules_cb apply_rules_cb[WLAN_SER_CMD_MAX];
struct wlan_serialization_timer *timers;
uint8_t max_active_cmds;
};
/**
* wlan_serialization_put_back_to_global_list() - put back cmd in global pool
* @queue: queue from which cmd needs to be taken out
* @ser_pdev_obj: pdev private object
* @cmd_list: cmd which needs to be matched
*
* command will be taken off from the queue and will be put back to global
* pool of free command buffers.
*
* Return: QDF_STATUS
*/
QDF_STATUS
wlan_serialization_put_back_to_global_list(qdf_list_t *queue,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj,
struct wlan_serialization_command_list *cmd_list);
/**
* wlan_serialization_move_pending_to_active() - to move pending command to
* active queue
* @cmd_type: cmd type to device to which queue the command needs to go
* @ser_pdev_obj: pointer to ser_pdev_obj
*
* Return: none
*/
void wlan_serialization_move_pending_to_active(
enum wlan_serialization_cmd_type cmd_type,
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj);
/**
* wlan_serialization_get_pdev_from_cmd() - get pdev from provided cmd
* @cmd: pointer to actual command
*
* This API will get the pointer to pdev through checking type of cmd
*
* Return: pointer to pdev
*/
struct wlan_objmgr_pdev*
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
*
* 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);
/**
* wlan_serialization_is_active_cmd_allowed() - check to see if command
* is allowed in active queue
* @pdev: pointer to pdev structure
* @cmd_type: type of command to check against
*
* Takes the command type and based on the type, it checks scan command queue
* or nonscan command queue to see if active command is allowed or no
*
* Return: true if allowed else false
*/
bool wlan_serialization_is_active_cmd_allowed(
struct wlan_serialization_command *cmd);
/**
* wlan_serialization_cleanup_all_timers() - to clean-up all timers
*
* @psoc_ser_ob: pointer to serialization psoc private object
*
* This API is to cleanup all the timers. it can be used when serialization
* module is exiting. it will make sure that if timer is running then it will
* stop and destroys the timer
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_serialization_cleanup_all_timers(
struct wlan_serialization_psoc_priv_obj *psoc_ser_ob);
/**
* wlan_serialization_find_and_remove_cmd() - to find cmd from queue and remove
* @cmd_info: pointer to command related information
*
* This api will find command from active queue and removes the command
*
* Return: QDF_STATUS
*/
QDF_STATUS wlan_serialization_find_and_remove_cmd(
struct wlan_serialization_queued_cmd_info *cmd_info);
/**
* wlan_serialization_find_and_cancel_cmd() - to find cmd from queue and cancel
* @cmd_info: pointer to command related information
*
* This api will find command from active queue and pending queue and
* removes the command. If it is in active queue then it will notifies the
* requester that it is in active queue and from there it expects requester
* to send remove command
*
* Return: wlan_serialization_cmd_status
*/
enum wlan_serialization_cmd_status
wlan_serialization_find_and_cancel_cmd(
struct wlan_serialization_queued_cmd_info *cmd_info);
/**
* wlan_serialization_enqueue_cmd() - Enqueue the cmd to pending/active Queue
* @cmd: Command information
* @is_cmd_for_active_queue: whether command is for active queue
*
* Return: Status of the serialization request
*/
enum wlan_serialization_status
wlan_serialization_enqueue_cmd(struct wlan_serialization_command *cmd,
uint8_t is_cmd_for_active_queue);
/**
* wlan_serialization_dequeue_cmd() - dequeue the cmd to pending/active Queue
* @cmd: Command information
* @is_cmd_for_active_queue: whether command is for active queue
*
* Return: Status of the serialization request
*/
enum wlan_serialization_cmd_status
wlan_serialization_dequeue_cmd(struct wlan_serialization_command *cmd,
uint8_t is_cmd_for_active_queue);
/**
* wlan_serialization_find_and_stop_timer() - to find and stop the timer
* @psoc: pointer to psoc
* @cmd: pointer to actual command
*
* find the timer associated with command, stop it and destory it
*
* Return: QDF_STATUS
*/
QDF_STATUS
wlan_serialization_find_and_stop_timer(struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd);
/**
* wlan_serialization_find_and_stop_timer() - to find and start the timer
* @psoc: pointer to psoc
* @cmd: pointer to actual command
*
* find the free timer, initialize it, and start it
*
* Return: QDF_STATUS
*/
QDF_STATUS
wlan_serialization_find_and_start_timer(struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd);
/**
* wlan_serialization_validate_cmd() - Validate the command
* @comp_id: Component ID