blob: 98fefed8a324e9f9cf685b1d9217831e6956b4b7 [file] [log] [blame]
/*
* Copyright (c) 2017 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_api.c
* This file provides an interface for the external components
* to utilize the services provided by the serialization
* component.
*/
/* Include files */
#include "wlan_objmgr_psoc_obj.h"
#include "wlan_objmgr_pdev_obj.h"
#include "wlan_objmgr_vdev_obj.h"
#include "wlan_serialization_main_i.h"
#include "wlan_serialization_utils_i.h"
bool wlan_serialization_is_cmd_present_in_pending_queue(
struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd)
{
if (!cmd) {
serialization_err("invalid cmd");
return false;
}
return wlan_serialization_is_cmd_present_queue(cmd, false);
}
bool wlan_serialization_is_cmd_present_in_active_queue(
struct wlan_objmgr_psoc *psoc,
struct wlan_serialization_command *cmd)
{
if (!cmd) {
serialization_err("invalid cmd");
return false;
}
return wlan_serialization_is_cmd_present_queue(cmd, true);
}
QDF_STATUS
wlan_serialization_register_apply_rules_cb(struct wlan_objmgr_psoc *psoc,
enum wlan_serialization_cmd_type cmd_type,
wlan_serialization_apply_rules_cb cb)
{
struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
QDF_STATUS status;
status = wlan_serialization_validate_cmdtype(cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("invalid cmd_type %d",
cmd_type);
return status;
}
ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
if (!ser_soc_obj) {
serialization_err("invalid ser_soc_obj");
return QDF_STATUS_E_FAILURE;
}
ser_soc_obj->apply_rules_cb[cmd_type] = cb;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
wlan_serialization_deregister_apply_rules_cb(struct wlan_objmgr_psoc *psoc,
enum wlan_serialization_cmd_type cmd_type)
{
struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
QDF_STATUS status;
status = wlan_serialization_validate_cmdtype(cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("invalid cmd_type %d",
cmd_type);
return status;
}
ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
if (!ser_soc_obj) {
serialization_err("invalid ser_soc_obj");
return QDF_STATUS_E_FAILURE;
}
ser_soc_obj->apply_rules_cb[cmd_type] = NULL;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
wlan_serialization_register_comp_info_cb(struct wlan_objmgr_psoc *psoc,
enum wlan_umac_comp_id comp_id,
enum wlan_serialization_cmd_type cmd_type,
wlan_serialization_comp_info_cb cb)
{
struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
QDF_STATUS status;
status = wlan_serialization_validate_cmd(comp_id, cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("invalid comp_id %d or cmd_type %d",
comp_id, cmd_type);
return status;
}
ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
if (!ser_soc_obj) {
serialization_err("invalid ser_soc_obj");
return QDF_STATUS_E_FAILURE;
}
ser_soc_obj->comp_info_cb[cmd_type][comp_id] = cb;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS
wlan_serialization_deregister_comp_info_cb(struct wlan_objmgr_psoc *psoc,
enum wlan_umac_comp_id comp_id,
enum wlan_serialization_cmd_type cmd_type)
{
struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
QDF_STATUS status;
status = wlan_serialization_validate_cmd(comp_id, cmd_type);
if (status != QDF_STATUS_SUCCESS) {
serialization_err("invalid comp_id %d or cmd_type %d",
comp_id, cmd_type);
return status;
}
ser_soc_obj = wlan_serialization_get_psoc_priv_obj(psoc);
if (!ser_soc_obj) {
serialization_err("invalid ser_soc_obj");
return QDF_STATUS_E_FAILURE;
}
ser_soc_obj->comp_info_cb[cmd_type][comp_id] = NULL;
return QDF_STATUS_SUCCESS;
}
enum wlan_serialization_cmd_status
wlan_serialization_non_scan_cmd_status(struct wlan_objmgr_pdev *pdev,
enum wlan_serialization_cmd_type cmd_id)
{
serialization_info("pdev non cmd status entry");
return WLAN_SER_CMD_NOT_FOUND;
}
enum wlan_serialization_cmd_status
wlan_serialization_cancel_request(
struct wlan_serialization_queued_cmd_info *req)
{
QDF_STATUS status;
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;
}
enum wlan_serialization_status
wlan_serialization_request(struct wlan_serialization_command *cmd)
{
bool is_active_cmd_allowed;
QDF_STATUS status;
uint8_t comp_id;
struct wlan_serialization_psoc_priv_obj *ser_soc_obj;
union wlan_serialization_rules_info info;
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;
}
ser_soc_obj = wlan_serialization_get_obj(cmd);
/*
* Get Component Info callback by calling
* each registered module
*/
for (comp_id = 0; comp_id < WLAN_UMAC_COMP_ID_MAX; comp_id++) {
if (!ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])
continue;
(ser_soc_obj->comp_info_cb[cmd->cmd_type][comp_id])(&info);
if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type])
continue;
if (!ser_soc_obj->apply_rules_cb[cmd->cmd_type](&info, comp_id))
return WLAN_SER_CMD_DENIED_RULES_FAILED;
}
is_active_cmd_allowed = wlan_serialization_is_active_cmd_allowed(cmd);
return wlan_serialization_enqueue_cmd(cmd, is_active_cmd_allowed);
}
enum wlan_serialization_cmd_status
wlan_serialization_vdev_scan_status(struct wlan_objmgr_vdev *vdev)
{
bool cmd_in_active, cmd_in_pending;
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);
cmd_in_active =
wlan_serialization_is_cmd_in_vdev_list(
vdev, &ser_pdev_obj->active_scan_list);
cmd_in_pending =
wlan_serialization_is_cmd_in_vdev_list(
vdev, &ser_pdev_obj->pending_scan_list);
return wlan_serialization_is_cmd_in_active_pending(
cmd_in_active, cmd_in_pending);
}
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;
}
enum wlan_serialization_cmd_status
wlan_serialization_pdev_scan_status(struct wlan_objmgr_pdev *pdev)
{
bool cmd_in_active, cmd_in_pending;
struct wlan_serialization_pdev_priv_obj *ser_pdev_obj =
wlan_serialization_get_pdev_priv_obj(pdev);
cmd_in_active =
wlan_serialization_is_cmd_in_pdev_list(
pdev, &ser_pdev_obj->active_scan_list);
cmd_in_pending =
wlan_serialization_is_cmd_in_pdev_list(
pdev, &ser_pdev_obj->pending_scan_list);
return wlan_serialization_is_cmd_in_active_pending(
cmd_in_active, cmd_in_pending);
}