qcacld-3.0: Add target interfaces for OCB component
Add target interfaces and core APIs for OCB component. CRs-Fixed: 2177578 Change-Id: I76a1afa4d6f3876b0b5df89ffe4080af77cd13c4
This commit is contained in:
572
components/ocb/core/src/wlan_ocb_main.c
Normal file
572
components/ocb/core/src/wlan_ocb_main.c
Normal file
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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: contains core ocb function definitions
|
||||
*/
|
||||
|
||||
#include <qdf_status.h>
|
||||
#include "scheduler_api.h"
|
||||
#include "wlan_objmgr_cmn.h"
|
||||
#include "wlan_objmgr_global_obj.h"
|
||||
#include "wlan_objmgr_psoc_obj.h"
|
||||
#include "wlan_objmgr_pdev_obj.h"
|
||||
#include "wlan_objmgr_vdev_obj.h"
|
||||
#include <cdp_txrx_handle.h>
|
||||
#include <cdp_txrx_cmn.h>
|
||||
#include <cdp_txrx_ocb.h>
|
||||
#include "wlan_ocb_main.h"
|
||||
#include "wlan_ocb_tgt_api.h"
|
||||
#include "target_if_ocb.h"
|
||||
|
||||
/**
|
||||
* ocb_get_cmd_type_str() - parse cmd to string
|
||||
* @cmd_type: ocb cmd type
|
||||
*
|
||||
* This function parse ocb cmd to string.
|
||||
*
|
||||
* Return: command string
|
||||
*/
|
||||
static const char *ocb_get_evt_type_str(enum ocb_southbound_event evt_type)
|
||||
{
|
||||
switch (evt_type) {
|
||||
case OCB_CHANNEL_CONFIG_STATUS:
|
||||
return "OCB channel config status";
|
||||
case OCB_TSF_TIMER:
|
||||
return "OCB TSF timer";
|
||||
case OCB_DCC_STATS_RESPONSE:
|
||||
return "OCB DCC get stats response";
|
||||
case OCB_NDL_RESPONSE:
|
||||
return "OCB NDL indication";
|
||||
case OCB_DCC_INDICATION:
|
||||
return "OCB DCC stats indication";
|
||||
default:
|
||||
return "Invalid OCB command";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_set_chan_info() - Set channel info to dp
|
||||
* @dp_soc: data path soc handle
|
||||
* @dp_pdev: data path pdev handle
|
||||
* @vdev_id: OCB vdev_id
|
||||
* @config: channel config parameters
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS ocb_set_chan_info(void *dp_soc,
|
||||
void *dp_pdev,
|
||||
uint32_t vdev_id,
|
||||
struct ocb_config *config)
|
||||
{
|
||||
struct cdp_vdev *dp_vdev;
|
||||
struct ol_txrx_ocb_set_chan ocb_set_chan;
|
||||
struct ol_txrx_ocb_chan_info *ocb_channel_info;
|
||||
|
||||
if (!dp_soc || !dp_pdev) {
|
||||
ocb_err("DP global handle is null");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
dp_vdev = cdp_get_vdev_from_vdev_id(dp_soc, dp_pdev, vdev_id);
|
||||
if (!dp_vdev) {
|
||||
ocb_err("DP vdev handle is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
ocb_set_chan.ocb_channel_count = config->channel_count;
|
||||
|
||||
/* release old settings */
|
||||
ocb_channel_info = cdp_get_ocb_chan_info(dp_soc, dp_vdev);
|
||||
if (ocb_channel_info)
|
||||
qdf_mem_free(ocb_channel_info);
|
||||
|
||||
if (config->channel_count) {
|
||||
int i, buf_size;
|
||||
|
||||
buf_size = sizeof(*ocb_channel_info) * config->channel_count;
|
||||
ocb_set_chan.ocb_channel_info = qdf_mem_malloc(buf_size);
|
||||
if (!ocb_set_chan.ocb_channel_info) {
|
||||
ocb_err("Failed to allocate buffer for chan info");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
ocb_channel_info = ocb_set_chan.ocb_channel_info;
|
||||
for (i = 0; i < config->channel_count; i++) {
|
||||
ocb_channel_info[i].chan_freq =
|
||||
config->channels[i].chan_freq;
|
||||
if (config->channels[i].flags &
|
||||
OCB_CHANNEL_FLAG_DISABLE_RX_STATS_HDR)
|
||||
ocb_channel_info[i].disable_rx_stats_hdr = 1;
|
||||
}
|
||||
} else {
|
||||
ocb_debug("No channel config to dp");
|
||||
ocb_set_chan.ocb_channel_info = NULL;
|
||||
}
|
||||
ocb_debug("Sync channel config to dp");
|
||||
cdp_set_ocb_chan_info(dp_soc, dp_vdev, ocb_set_chan);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_channel_config_status() - Process set channel config response
|
||||
* @evt: response event
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS ocb_channel_config_status(struct ocb_rx_event *evt)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
uint32_t vdev_id;
|
||||
struct ocb_rx_event *event;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct ocb_pdev_obj *ocb_obj;
|
||||
struct ocb_callbacks *cbs;
|
||||
struct ocb_set_config_response config_rsp;
|
||||
|
||||
if (!evt) {
|
||||
ocb_err("Event buffer is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
event = evt;
|
||||
psoc = event->psoc;
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_OCB_SB_ID);
|
||||
if (!pdev) {
|
||||
ocb_alert("Pdev is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
|
||||
if (!ocb_obj) {
|
||||
ocb_err("Pdev object is NULL");
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
cbs = &ocb_obj->ocb_cbs;
|
||||
if (ocb_obj->channel_config) {
|
||||
vdev_id = ocb_obj->channel_config->vdev_id;
|
||||
config_rsp = event->rsp.channel_cfg_rsp;
|
||||
|
||||
/* Sync channel status to data path */
|
||||
if (config_rsp.status == OCB_CHANNEL_CONFIG_SUCCESS)
|
||||
ocb_set_chan_info(ocb_obj->dp_soc,
|
||||
ocb_obj->dp_pdev,
|
||||
vdev_id,
|
||||
ocb_obj->channel_config);
|
||||
qdf_mem_free(ocb_obj->channel_config);
|
||||
ocb_obj->channel_config = NULL;
|
||||
} else {
|
||||
ocb_err("Failed to sync channel info to DP");
|
||||
config_rsp.status = OCB_CHANNEL_CONFIG_FAIL;
|
||||
}
|
||||
|
||||
if (cbs->ocb_set_config_callback) {
|
||||
cbs->ocb_set_config_callback(cbs->ocb_set_config_context,
|
||||
&config_rsp);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
} else {
|
||||
ocb_err("ocb_set_config_resp_cb is NULL");
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
}
|
||||
exit:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_tsf_timer() - Process get TSF timer response
|
||||
* @evt: repsonse event
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS ocb_tsf_timer(struct ocb_rx_event *evt)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_rx_event *event;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct ocb_callbacks *cbs;
|
||||
struct ocb_get_tsf_timer_response *tsf_timer;
|
||||
|
||||
if (!evt) {
|
||||
ocb_err("Event buffer is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
event = evt;
|
||||
vdev = event->vdev;
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
cbs = wlan_ocb_get_callbacks(pdev);
|
||||
tsf_timer = &event->rsp.tsf_timer;
|
||||
ocb_debug("TSF timer low=%d, high=%d",
|
||||
tsf_timer->timer_low, tsf_timer->timer_high);
|
||||
if (cbs && cbs->ocb_get_tsf_timer_callback) {
|
||||
ocb_debug("%s: send TSF timer.", __func__);
|
||||
cbs->ocb_get_tsf_timer_callback(cbs->ocb_get_tsf_timer_context,
|
||||
tsf_timer);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
} else {
|
||||
ocb_err("ocb_get_tsf_timer_cb is NULL");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_dcc_stats_response() - Process get DCC stats response
|
||||
* @evt: repsonse event
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS ocb_dcc_stats_response(struct ocb_rx_event *evt)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_rx_event *event;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct ocb_callbacks *cbs;
|
||||
struct ocb_dcc_get_stats_response *dcc_stats;
|
||||
|
||||
if (!evt) {
|
||||
ocb_err("Event buffer is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
event = evt;
|
||||
vdev = event->vdev;
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
cbs = wlan_ocb_get_callbacks(pdev);
|
||||
dcc_stats = &event->rsp.dcc_stats;
|
||||
if (cbs && cbs->ocb_dcc_get_stats_callback) {
|
||||
ocb_debug("%s: send DCC stats", __func__);
|
||||
cbs->ocb_dcc_get_stats_callback(cbs->ocb_dcc_get_stats_context,
|
||||
dcc_stats);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
} else {
|
||||
ocb_err("dcc_get_stats_cb is NULL");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_ndl_response() - Process NDL update response
|
||||
* @evt: repsonse event
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS ocb_ndl_response(struct ocb_rx_event *evt)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_rx_event *event;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct ocb_callbacks *cbs;
|
||||
struct ocb_dcc_update_ndl_response *ndl;
|
||||
|
||||
if (!evt) {
|
||||
ocb_err("Event buffer is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
event = evt;
|
||||
vdev = event->vdev;
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
cbs = wlan_ocb_get_callbacks(pdev);
|
||||
ndl = &event->rsp.ndl;
|
||||
if (cbs && cbs->ocb_dcc_update_ndl_callback) {
|
||||
ocb_debug("%s: NDL update response", __func__);
|
||||
cbs->ocb_dcc_update_ndl_callback(
|
||||
cbs->ocb_dcc_update_ndl_context, ndl);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
} else {
|
||||
ocb_err("dcc_update_ndl is NULL");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_dcc_indication() - Process DCC stats indication
|
||||
* @evt: repsonse event
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS ocb_dcc_indication(struct ocb_rx_event *evt)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_rx_event *event;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
struct ocb_callbacks *cbs;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct ocb_dcc_get_stats_response *dcc_stats;
|
||||
|
||||
if (!evt) {
|
||||
ocb_err("Event buffer is NULL");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
event = evt;
|
||||
vdev = event->vdev;
|
||||
pdev = wlan_vdev_get_pdev(vdev);
|
||||
cbs = wlan_ocb_get_callbacks(pdev);
|
||||
dcc_stats = &event->rsp.dcc_stats;
|
||||
if (cbs && cbs->ocb_dcc_stats_event_callback) {
|
||||
ocb_debug("%s: DCC stats indication", __func__);
|
||||
cbs->ocb_dcc_stats_event_callback(
|
||||
cbs->ocb_dcc_stats_event_context, dcc_stats);
|
||||
status = QDF_STATUS_SUCCESS;
|
||||
} else {
|
||||
ocb_err("dcc_get_stats_cb is NULL");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_flush_start_msg() - Flush ocb start message
|
||||
* @msg: OCB start vdev message
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success.
|
||||
*/
|
||||
static QDF_STATUS ocb_flush_start_msg(struct scheduler_msg *msg)
|
||||
{
|
||||
struct ocb_pdev_obj *ocb_obj;
|
||||
|
||||
if (!msg) {
|
||||
ocb_err("Null point for OCB message");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
ocb_obj = msg->bodyptr;
|
||||
if (ocb_obj && ocb_obj->channel_config) {
|
||||
ocb_info("release the backed config parameters");
|
||||
qdf_mem_free(ocb_obj->channel_config);
|
||||
ocb_obj->channel_config = NULL;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* ocb_process_start_vdev_msg() - Handler for OCB vdev start message
|
||||
* @msg: OCB start vdev message
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success.
|
||||
*/
|
||||
static QDF_STATUS ocb_process_start_vdev_msg(struct scheduler_msg *msg)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_config *config;
|
||||
struct ocb_pdev_obj *ocb_obj;
|
||||
struct ocb_callbacks *ocb_cbs;
|
||||
struct wlan_objmgr_vdev *vdev;
|
||||
|
||||
if (!msg || !msg->bodyptr) {
|
||||
ocb_err("invalid message");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
ocb_obj = msg->bodyptr;
|
||||
ocb_cbs = &ocb_obj->ocb_cbs;
|
||||
if (!ocb_cbs->start_ocb_vdev) {
|
||||
ocb_err("No callback to start ocb vdev");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
config = ocb_obj->channel_config;
|
||||
if (!config) {
|
||||
ocb_err("NULL config parameters");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
vdev = wlan_objmgr_get_vdev_by_id_from_pdev(ocb_obj->pdev,
|
||||
config->vdev_id,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!vdev) {
|
||||
ocb_err("Cannot get vdev");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
ocb_debug("Start to send OCB vdev start cmd");
|
||||
status = ocb_cbs->start_ocb_vdev(config);
|
||||
wlan_objmgr_vdev_release_ref(vdev, WLAN_OCB_SB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
ocb_err("Failed to start OCB vdev");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS ocb_vdev_start(struct ocb_pdev_obj *ocb_obj)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct scheduler_msg msg = {0};
|
||||
|
||||
msg.bodyptr = ocb_obj;
|
||||
msg.callback = ocb_process_start_vdev_msg;
|
||||
msg.flush_callback = ocb_flush_start_msg;
|
||||
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
ocb_err("Failed to post vdev start message");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS ocb_process_evt(struct scheduler_msg *msg)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_rx_event *event;
|
||||
|
||||
ocb_debug("msg type %d, %s", msg->type,
|
||||
ocb_get_evt_type_str(msg->type));
|
||||
|
||||
if (!(msg->bodyptr)) {
|
||||
ocb_err("Invalid message body");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
event = msg->bodyptr;
|
||||
switch (msg->type) {
|
||||
case OCB_CHANNEL_CONFIG_STATUS:
|
||||
status = ocb_channel_config_status(event);
|
||||
break;
|
||||
case OCB_TSF_TIMER:
|
||||
status = ocb_tsf_timer(event);
|
||||
break;
|
||||
case OCB_DCC_STATS_RESPONSE:
|
||||
status = ocb_dcc_stats_response(event);
|
||||
break;
|
||||
case OCB_NDL_RESPONSE:
|
||||
status = ocb_ndl_response(event);
|
||||
break;
|
||||
case OCB_DCC_INDICATION:
|
||||
status = ocb_dcc_indication(event);
|
||||
break;
|
||||
default:
|
||||
status = QDF_STATUS_E_INVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
wlan_ocb_release_rx_event(event);
|
||||
msg->bodyptr = NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
struct ocb_config *ocb_copy_config(struct ocb_config *src)
|
||||
{
|
||||
struct ocb_config *dst;
|
||||
uint32_t length;
|
||||
uint8_t *cursor;
|
||||
|
||||
length = sizeof(*src) +
|
||||
src->channel_count * sizeof(*src->channels) +
|
||||
src->schedule_size * sizeof(*src->schedule) +
|
||||
src->dcc_ndl_chan_list_len +
|
||||
src->dcc_ndl_active_state_list_len;
|
||||
|
||||
dst = qdf_mem_malloc(length);
|
||||
if (!dst)
|
||||
return NULL;
|
||||
|
||||
*dst = *src;
|
||||
|
||||
cursor = (uint8_t *)dst;
|
||||
cursor += sizeof(*dst);
|
||||
dst->channels = (struct ocb_config_chan *)cursor;
|
||||
cursor += src->channel_count * sizeof(*dst->channels);
|
||||
qdf_mem_copy(dst->channels, src->channels,
|
||||
src->channel_count * sizeof(*dst->channels));
|
||||
dst->schedule = (struct ocb_config_schdl *)cursor;
|
||||
cursor += src->schedule_size * sizeof(*dst->schedule);
|
||||
qdf_mem_copy(dst->schedule, src->schedule,
|
||||
src->schedule_size * sizeof(*dst->schedule));
|
||||
dst->dcc_ndl_chan_list = cursor;
|
||||
cursor += src->dcc_ndl_chan_list_len;
|
||||
qdf_mem_copy(dst->dcc_ndl_chan_list, src->dcc_ndl_chan_list,
|
||||
src->dcc_ndl_chan_list_len);
|
||||
dst->dcc_ndl_active_state_list = cursor;
|
||||
cursor += src->dcc_ndl_active_state_list_len;
|
||||
qdf_mem_copy(dst->dcc_ndl_active_state_list,
|
||||
src->dcc_ndl_active_state_list,
|
||||
src->dcc_ndl_active_state_list_len);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
QDF_STATUS ocb_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
|
||||
void *arg_list)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_pdev_obj *ocb_obj;
|
||||
|
||||
ocb_notice("ocb pdev created");
|
||||
ocb_obj = qdf_mem_malloc(sizeof(*ocb_obj));
|
||||
if (!ocb_obj) {
|
||||
ocb_err("Failed to allocate memory for ocb pdev object");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
status = wlan_objmgr_pdev_component_obj_attach(pdev,
|
||||
WLAN_UMAC_COMP_OCB,
|
||||
(void *)ocb_obj,
|
||||
QDF_STATUS_SUCCESS);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
ocb_err("Failed to attach pdev ocb component");
|
||||
qdf_mem_free(ocb_obj);
|
||||
return status;
|
||||
}
|
||||
ocb_obj->pdev = pdev;
|
||||
|
||||
/* register OCB tx/rx ops */
|
||||
tgt_ocb_register_rx_ops(&ocb_obj->ocb_rxops);
|
||||
target_if_ocb_register_tx_ops(&ocb_obj->ocb_txops);
|
||||
ocb_notice("ocb pdev attached");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS ocb_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
|
||||
void *arg_list)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct ocb_pdev_obj *ocb_obj;
|
||||
|
||||
ocb_obj = wlan_objmgr_pdev_get_comp_private_obj(pdev,
|
||||
WLAN_UMAC_COMP_OCB);
|
||||
if (!ocb_obj) {
|
||||
ocb_err("Failed to get ocb pdev object");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
status = wlan_objmgr_pdev_component_obj_detach(pdev,
|
||||
WLAN_UMAC_COMP_OCB,
|
||||
ocb_obj);
|
||||
if (QDF_IS_STATUS_ERROR(status))
|
||||
ocb_err("Failed to detatch ocb pdev object");
|
||||
|
||||
qdf_mem_free(ocb_obj);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
49
components/ocb/dispatcher/inc/wlan_ocb_tgt_api.h
Normal file
49
components/ocb/dispatcher/inc/wlan_ocb_tgt_api.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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: OCB south bound interface declaration
|
||||
*/
|
||||
#ifndef _WLAN_OCB_TGT_API_H
|
||||
#define _WLAN_OCB_TGT_API_H
|
||||
#include <wlan_ocb_public_structs.h>
|
||||
|
||||
/**
|
||||
* tgt_ocb_register_ev_handler() - register south bound event handler
|
||||
* @pdev: pdev handle
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
QDF_STATUS tgt_ocb_register_ev_handler(struct wlan_objmgr_pdev *pdev);
|
||||
|
||||
/**
|
||||
* tgt_ocb_unregister_ev_handler() - unregister south bound event handler
|
||||
* @pdev: pdev handle
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
QDF_STATUS tgt_ocb_unregister_ev_handler(struct wlan_objmgr_pdev *pdev);
|
||||
|
||||
/**
|
||||
* tgt_ocb_register_rx_ops() - register OCB rx operations
|
||||
* @ocb_rxops: fps to rx operations
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
QDF_STATUS tgt_ocb_register_rx_ops(struct wlan_ocb_rx_ops *ocb_rxops);
|
||||
#endif
|
336
components/ocb/dispatcher/src/wlan_ocb_tgt_api.c
Normal file
336
components/ocb/dispatcher/src/wlan_ocb_tgt_api.c
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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: This file contains ocb south bound interface definitions
|
||||
*/
|
||||
|
||||
#include <scheduler_api.h>
|
||||
#include <wlan_objmgr_psoc_obj.h>
|
||||
#include <wlan_objmgr_global_obj.h>
|
||||
#include <wlan_objmgr_pdev_obj.h>
|
||||
#include <wlan_objmgr_vdev_obj.h>
|
||||
#include "wlan_ocb_public_structs.h"
|
||||
#include "wlan_ocb_ucfg_api.h"
|
||||
#include "wlan_ocb_tgt_api.h"
|
||||
#include "wlan_ocb_main.h"
|
||||
|
||||
/**
|
||||
* wlan_ocb_flush_callback() - OCB message flash callback
|
||||
* @msg: OCB message
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success.
|
||||
*/
|
||||
static QDF_STATUS wlan_ocb_flush_callback(struct scheduler_msg *msg)
|
||||
{
|
||||
struct ocb_rx_event *event;
|
||||
|
||||
if (!msg) {
|
||||
ocb_err("Null point for OCB message");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
|
||||
event = msg->bodyptr;
|
||||
wlan_ocb_release_rx_event(event);
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* tgt_ocb_channel_config_status() - handler for channel config response
|
||||
* @psoc: psoc handle
|
||||
* @status: status for last channel config
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
tgt_ocb_channel_config_status(struct wlan_objmgr_psoc *psoc,
|
||||
uint32_t status)
|
||||
{
|
||||
QDF_STATUS qdf_status;
|
||||
struct scheduler_msg msg = {0};
|
||||
struct ocb_rx_event *event;
|
||||
|
||||
event = qdf_mem_malloc(sizeof(*event));
|
||||
if (!event) {
|
||||
ocb_err("Memory malloc failed for channel config status");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
qdf_status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_OCB_SB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(qdf_status)) {
|
||||
ocb_err("Failed to get psoc ref");
|
||||
wlan_ocb_release_rx_event(event);
|
||||
return qdf_status;
|
||||
}
|
||||
event->psoc = psoc;
|
||||
event->rsp.channel_cfg_rsp.status = status;
|
||||
event->evt_id = OCB_CHANNEL_CONFIG_STATUS;
|
||||
msg.type = OCB_CHANNEL_CONFIG_STATUS;
|
||||
msg.bodyptr = event;
|
||||
msg.callback = ocb_process_evt;
|
||||
msg.flush_callback = wlan_ocb_flush_callback;
|
||||
qdf_status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
|
||||
if (QDF_IS_STATUS_SUCCESS(qdf_status))
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
ocb_err("failed to send OCB_CHANNEL_CONFIG_STATUS msg");
|
||||
wlan_ocb_release_rx_event(event);
|
||||
|
||||
return qdf_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* tgt_ocb_get_tsf_timer() - handle for TSF timer response
|
||||
* @psoc: psoc handle
|
||||
* @response: TSF timer response
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on succcess
|
||||
*/
|
||||
static QDF_STATUS
|
||||
tgt_ocb_get_tsf_timer(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_get_tsf_timer_response *response)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct scheduler_msg msg = {0};
|
||||
struct ocb_rx_event *event;
|
||||
|
||||
event = qdf_mem_malloc(sizeof(*event));
|
||||
if (!event) {
|
||||
ocb_err("Memory malloc failed for tsf timer");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_OCB_SB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
ocb_err("Failed to get psoc ref");
|
||||
goto flush_ref;
|
||||
}
|
||||
event->psoc = psoc;
|
||||
event->vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
|
||||
response->vdev_id,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!event->vdev) {
|
||||
ocb_err("Cannot get vdev handle");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto flush_ref;
|
||||
}
|
||||
|
||||
event->evt_id = OCB_TSF_TIMER;
|
||||
event->rsp.tsf_timer.vdev_id = response->vdev_id;
|
||||
event->rsp.tsf_timer.timer_high = response->timer_high;
|
||||
event->rsp.tsf_timer.timer_low = response->timer_low;
|
||||
msg.type = OCB_TSF_TIMER;
|
||||
msg.bodyptr = event;
|
||||
msg.callback = ocb_process_evt;
|
||||
msg.flush_callback = wlan_ocb_flush_callback;
|
||||
|
||||
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
ocb_err("failed to send OCB_TSF_TIMER msg");
|
||||
flush_ref:
|
||||
wlan_ocb_release_rx_event(event);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* tgt_ocb_dcc_ndl_update() - handler for NDL update response
|
||||
* @psoc: psoc handle
|
||||
* @resp: NDL update response
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
tgt_ocb_dcc_ndl_update(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_dcc_update_ndl_response *resp)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
struct scheduler_msg msg = {0};
|
||||
struct ocb_rx_event *event;
|
||||
|
||||
event = qdf_mem_malloc(sizeof(*event));
|
||||
if (!event) {
|
||||
ocb_err("Memory malloc failed for ndl update response");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
|
||||
status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_OCB_SB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
ocb_err("Failed to get psoc ref");
|
||||
goto flush_ref;
|
||||
}
|
||||
event->psoc = psoc;
|
||||
event->vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
|
||||
resp->vdev_id,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!event->vdev) {
|
||||
ocb_err("Cannot get vdev handle");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto flush_ref;
|
||||
}
|
||||
|
||||
event->evt_id = OCB_NDL_RESPONSE;
|
||||
qdf_mem_copy(&event->rsp.ndl, resp, sizeof(*resp));
|
||||
msg.type = OCB_NDL_RESPONSE;
|
||||
msg.bodyptr = event;
|
||||
msg.callback = ocb_process_evt;
|
||||
msg.flush_callback = wlan_ocb_flush_callback;
|
||||
|
||||
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
ocb_err("failed to send OCB_NDL_RESPONSE msg");
|
||||
flush_ref:
|
||||
wlan_ocb_release_rx_event(event);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* tgt_ocb_dcc_stats_indicate() - handler for DCC stats indication
|
||||
* @psoc: psoc handle
|
||||
* @response: DCC stats
|
||||
* @bool: true for active query, false for passive indicate
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
tgt_ocb_dcc_stats_indicate(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_dcc_get_stats_response *response,
|
||||
bool active)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
uint8_t *buf;
|
||||
uint32_t size;
|
||||
struct scheduler_msg msg = {0};
|
||||
struct ocb_rx_event *event;
|
||||
|
||||
size = sizeof(*event) +
|
||||
response->channel_stats_array_len;
|
||||
buf = qdf_mem_malloc(size);
|
||||
if (!buf) {
|
||||
ocb_err("Memory malloc failed for dcc indication");
|
||||
return QDF_STATUS_E_NOMEM;
|
||||
}
|
||||
event = (struct ocb_rx_event *)buf;
|
||||
status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_OCB_SB_ID);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
ocb_err("Failed to get psoc ref");
|
||||
goto flush_ref;
|
||||
}
|
||||
event->psoc = psoc;
|
||||
event->vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
|
||||
response->vdev_id,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!event->vdev) {
|
||||
ocb_err("Cannot get vdev handle");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
goto flush_ref;
|
||||
}
|
||||
|
||||
event->rsp.dcc_stats.channel_stats_array =
|
||||
(uint8_t *)&event->rsp.dcc_stats +
|
||||
sizeof(struct ocb_dcc_get_stats_response);
|
||||
event->rsp.dcc_stats.vdev_id = response->vdev_id;
|
||||
event->rsp.dcc_stats.num_channels = response->num_channels;
|
||||
event->rsp.dcc_stats.channel_stats_array_len =
|
||||
response->channel_stats_array_len;
|
||||
qdf_mem_copy(event->rsp.dcc_stats.channel_stats_array,
|
||||
response->channel_stats_array,
|
||||
response->channel_stats_array_len);
|
||||
ocb_debug("Message type is %s",
|
||||
active ? "Get stats response" : "DCC stats indication");
|
||||
if (active)
|
||||
msg.type = OCB_DCC_STATS_RESPONSE;
|
||||
else
|
||||
msg.type = OCB_DCC_INDICATION;
|
||||
event->evt_id = msg.type;
|
||||
msg.bodyptr = event;
|
||||
msg.callback = ocb_process_evt;
|
||||
msg.flush_callback = wlan_ocb_flush_callback;
|
||||
|
||||
status = scheduler_post_msg(QDF_MODULE_ID_TARGET_IF, &msg);
|
||||
if (QDF_IS_STATUS_SUCCESS(status))
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
ocb_err("failed to send DCC stats msg(%d)", msg.type);
|
||||
flush_ref:
|
||||
wlan_ocb_release_rx_event(event);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS tgt_ocb_register_ev_handler(struct wlan_objmgr_pdev *pdev)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_ocb_tx_ops *ocb_ops;
|
||||
QDF_STATUS status = QDF_STATUS_E_FAILURE;
|
||||
|
||||
psoc = wlan_pdev_get_psoc(pdev);
|
||||
if (!psoc) {
|
||||
ocb_err("Null soc handle");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
ocb_ops = wlan_pdev_get_ocb_tx_ops(pdev);
|
||||
if (ocb_ops && ocb_ops->ocb_reg_ev_handler) {
|
||||
status = ocb_ops->ocb_reg_ev_handler(psoc, NULL);
|
||||
ocb_debug("register ocb event, status:%d", status);
|
||||
} else {
|
||||
ocb_alert("No ocb objects or ocb_reg_ev_handler");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS tgt_ocb_unregister_ev_handler(struct wlan_objmgr_pdev *pdev)
|
||||
{
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_ocb_tx_ops *ocb_ops;
|
||||
QDF_STATUS status;
|
||||
|
||||
psoc = wlan_pdev_get_psoc(pdev);
|
||||
if (!psoc) {
|
||||
ocb_err("Null soc handle");
|
||||
return QDF_STATUS_E_INVAL;
|
||||
}
|
||||
ocb_ops = wlan_pdev_get_ocb_tx_ops(pdev);
|
||||
if (ocb_ops && ocb_ops->ocb_unreg_ev_handler) {
|
||||
status = ocb_ops->ocb_unreg_ev_handler(psoc, NULL);
|
||||
ocb_debug("unregister ocb event, status:%d", status);
|
||||
} else {
|
||||
ocb_alert("No ocb objects or ocb_unreg_ev_handler");
|
||||
status = QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
QDF_STATUS tgt_ocb_register_rx_ops(struct wlan_ocb_rx_ops *ocb_rxops)
|
||||
{
|
||||
ocb_rxops->ocb_set_config_status = tgt_ocb_channel_config_status;
|
||||
ocb_rxops->ocb_tsf_timer = tgt_ocb_get_tsf_timer;
|
||||
ocb_rxops->ocb_dcc_ndl_update = tgt_ocb_dcc_ndl_update;
|
||||
ocb_rxops->ocb_dcc_stats_indicate = tgt_ocb_dcc_stats_indicate;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
58
components/target_if/ocb/inc/target_if_ocb.h
Normal file
58
components/target_if/ocb/inc/target_if_ocb.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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: offload lmac interface APIs for ocb
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TARGET_IF_OCB_H__
|
||||
#define __TARGET_IF_OCB_H__
|
||||
|
||||
/**
|
||||
* target_if_ocb_register_event_handler() - lmac handler to register ocb event
|
||||
* handler
|
||||
* @psoc : psoc object
|
||||
* @arg: argument passed to lmac
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS target_if_ocb_register_event_handler(struct wlan_objmgr_psoc *psoc,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* target_if_ocb_unregister_event_handler() - lmac handler to unregister ocb
|
||||
* event handler
|
||||
* @psoc : psoc object
|
||||
* @arg: argument passed to lmac
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS target_if_ocb_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
|
||||
void *arg);
|
||||
/**
|
||||
* target_if_ocb_register_tx_ops() - lmac handler to register ocb tx ops
|
||||
* callback functions
|
||||
* @tx_ops: ocb tx operations
|
||||
*
|
||||
* Return: QDF_STATUS
|
||||
*/
|
||||
QDF_STATUS target_if_ocb_register_tx_ops(
|
||||
struct wlan_ocb_tx_ops *tx_ops);
|
||||
|
||||
#endif
|
696
components/target_if/ocb/src/target_if_ocb.c
Normal file
696
components/target_if/ocb/src/target_if_ocb.c
Normal file
@@ -0,0 +1,696 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* 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: offload lmac interface APIs for ocb
|
||||
*
|
||||
*/
|
||||
|
||||
#include <qdf_mem.h>
|
||||
#include <target_if.h>
|
||||
#include <qdf_status.h>
|
||||
#include <wmi_unified_api.h>
|
||||
#include <wmi_unified_priv.h>
|
||||
#include <wmi_unified_param.h>
|
||||
#include <wlan_objmgr_psoc_obj.h>
|
||||
#include <wlan_utility.h>
|
||||
#include <wlan_defs.h>
|
||||
#include <wlan_ocb_public_structs.h>
|
||||
#include <wlan_ocb_main.h>
|
||||
#include <target_if_ocb.h>
|
||||
|
||||
/**
|
||||
* target_if_ocb_get_rx_ops() - get target interface RX operations
|
||||
* @pdev: pdev handle
|
||||
*
|
||||
* Return: fp to target interface RX operations
|
||||
*/
|
||||
static inline struct wlan_ocb_rx_ops *
|
||||
target_if_ocb_get_rx_ops(struct wlan_objmgr_pdev *pdev)
|
||||
{
|
||||
struct ocb_pdev_obj *ocb_obj;
|
||||
|
||||
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
|
||||
|
||||
return &ocb_obj->ocb_rxops;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_ocb_set_config() - send the OCB config to the FW
|
||||
* @psoc: pointer to PSOC object
|
||||
* @config: OCB channel configuration
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS target_if_ocb_set_config(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_config *config)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = wmi_unified_ocb_set_config(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
config);
|
||||
if (status)
|
||||
target_if_err("Failed to set OCB config %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_ocb_set_utc_time() - send the UTC time to the firmware
|
||||
* @psoc: pointer to PSOC object
|
||||
* @utc: pointer to the UTC time structure
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS target_if_ocb_set_utc_time(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_utc_param *utc)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = wmi_unified_ocb_set_utc_time_cmd(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
utc);
|
||||
if (status)
|
||||
target_if_err("Failed to set OCB UTC time %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_ocb_start_timing_advert() - start sending the timing
|
||||
* advertisement frame on a channel
|
||||
* @psoc: pointer to PSOC object
|
||||
* @ta: pointer to the timing advertisement
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
target_if_ocb_start_timing_advert(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_timing_advert_param *ta)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = wmi_unified_ocb_start_timing_advert(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc), ta);
|
||||
if (status)
|
||||
target_if_err("Failed to start OCB timing advert %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_ocb_stop_timing_advert() - stop sending the timing
|
||||
* advertisement frame on a channel
|
||||
* @psoc: pointer to PSOC object
|
||||
* @ta: pointer to the timing advertisement
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
target_if_ocb_stop_timing_advert(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_timing_advert_param *ta)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status =
|
||||
wmi_unified_ocb_stop_timing_advert(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
ta);
|
||||
if (status)
|
||||
target_if_err("Failed to stop OCB timing advert %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_ocb_get_tsf_timer() - get tsf timer
|
||||
* @psoc: pointer to PSOC object
|
||||
* @request: pointer to the request
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
target_if_ocb_get_tsf_timer(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_get_tsf_timer_param *request)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = wmi_unified_ocb_get_tsf_timer(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
request);
|
||||
if (status)
|
||||
target_if_err("Failed to send get tsf timer cmd: %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_dcc_get_stats() - get the DCC channel stats
|
||||
* @psoc: pointer to PSOC object
|
||||
* @get_stats_param: pointer to the dcc stats request
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
target_if_dcc_get_stats(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_dcc_get_stats_param *get_stats_param)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = wmi_unified_dcc_get_stats_cmd(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
get_stats_param);
|
||||
if (status)
|
||||
target_if_err("Failed to send get DCC stats cmd: %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_dcc_clear_stats() - send command to clear the DCC stats
|
||||
* @psoc: pointer to PSOC object
|
||||
* @clear_stats_param: parameters to the command
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
target_if_dcc_clear_stats(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_dcc_clear_stats_param *clear_stats_param)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
status = wmi_unified_dcc_clear_stats(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
clear_stats_param);
|
||||
if (status)
|
||||
target_if_err("Failed to send clear DCC stats cmd: %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_dcc_update_ndl() - command to update the NDL data
|
||||
* @psoc: pointer to PSOC object
|
||||
* @update_ndl_param: pointer to the request parameters
|
||||
*
|
||||
* Return: QDF_STATUS_SUCCESS on success
|
||||
*/
|
||||
static QDF_STATUS
|
||||
target_if_dcc_update_ndl(struct wlan_objmgr_psoc *psoc,
|
||||
struct ocb_dcc_update_ndl_param *update_ndl_param)
|
||||
{
|
||||
QDF_STATUS status;
|
||||
|
||||
/* Send the WMI command */
|
||||
status = wmi_unified_dcc_update_ndl(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
update_ndl_param);
|
||||
if (status)
|
||||
target_if_err("Failed to send NDL update cmd: %d", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_ocb_set_config_resp() - handler for channel config response
|
||||
* @scn: scn handle
|
||||
* @event_buf: pointer to the event buffer
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int
|
||||
target_if_ocb_set_config_resp(ol_scn_t scn, uint8_t *event_buf,
|
||||
uint32_t len)
|
||||
{
|
||||
int rc;
|
||||
QDF_STATUS status;
|
||||
uint32_t resp;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct wlan_ocb_rx_ops *ocb_rx_ops;
|
||||
|
||||
target_if_debug("scn:%pK, data:%pK, datalen:%d",
|
||||
scn, event_buf, len);
|
||||
if (!scn || !event_buf) {
|
||||
target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
psoc = target_if_get_psoc_from_scn_hdl(scn);
|
||||
if (!psoc) {
|
||||
target_if_err("null psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!pdev) {
|
||||
target_if_err("pdev is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
|
||||
if (ocb_rx_ops->ocb_set_config_status) {
|
||||
status = wmi_extract_ocb_set_channel_config_resp(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
event_buf, &resp);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("Failed to extract config status");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
status = ocb_rx_ops->ocb_set_config_status(psoc, resp);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
target_if_err("ocb_set_config_status failed.");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
target_if_fatal("No ocb_set_config_status callback");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
exit:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
/**
|
||||
* target_if_ocb_get_tsf_timer_resp() - handler for TSF timer response
|
||||
* @scn: scn handle
|
||||
* @event_buf: pointer to the event buffer
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int target_if_ocb_get_tsf_timer_resp(ol_scn_t scn,
|
||||
uint8_t *event_buf,
|
||||
uint32_t len)
|
||||
{
|
||||
int rc;
|
||||
QDF_STATUS status;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct ocb_get_tsf_timer_response response;
|
||||
struct wlan_ocb_rx_ops *ocb_rx_ops;
|
||||
|
||||
target_if_debug("scn:%pK, data:%pK, datalen:%d",
|
||||
scn, event_buf, len);
|
||||
|
||||
if (!scn || !event_buf) {
|
||||
target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
psoc = target_if_get_psoc_from_scn_hdl(scn);
|
||||
if (!psoc) {
|
||||
target_if_err("null psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!pdev) {
|
||||
target_if_err("pdev is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
|
||||
if (ocb_rx_ops->ocb_tsf_timer) {
|
||||
status = wmi_extract_ocb_tsf_timer(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
event_buf, &response);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("Failed to extract tsf timer");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
status = ocb_rx_ops->ocb_tsf_timer(psoc, &response);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
target_if_err("ocb_tsf_timer failed.");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
target_if_fatal("No ocb_tsf_timer callback");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
exit:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_dcc_update_ndl_resp() - handler for update NDL response
|
||||
* @scn: scn handle
|
||||
* @event_buf: pointer to the event buffer
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int target_if_dcc_update_ndl_resp(ol_scn_t scn,
|
||||
uint8_t *event_buf,
|
||||
uint32_t len)
|
||||
{
|
||||
int rc;
|
||||
QDF_STATUS status;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct ocb_dcc_update_ndl_response *resp;
|
||||
struct wlan_ocb_rx_ops *ocb_rx_ops;
|
||||
|
||||
target_if_debug("scn:%pK, data:%pK, datalen:%d",
|
||||
scn, event_buf, len);
|
||||
|
||||
if (!scn || !event_buf) {
|
||||
target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
psoc = target_if_get_psoc_from_scn_hdl(scn);
|
||||
if (!psoc) {
|
||||
target_if_err("null psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!pdev) {
|
||||
target_if_err("pdev is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Allocate and populate the response */
|
||||
resp = qdf_mem_malloc(sizeof(*resp));
|
||||
if (!resp) {
|
||||
target_if_err("Error allocating memory for the response.");
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
|
||||
if (ocb_rx_ops->ocb_dcc_ndl_update) {
|
||||
status = wmi_extract_dcc_update_ndl_resp(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
event_buf, resp);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("Failed to extract ndl status");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
status = ocb_rx_ops->ocb_dcc_ndl_update(psoc, resp);
|
||||
if (status != QDF_STATUS_SUCCESS) {
|
||||
target_if_err("dcc_ndl_update failed.");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
target_if_fatal("No dcc_ndl_update callback");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
exit:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
|
||||
if (resp)
|
||||
qdf_mem_free(resp);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_dcc_get_stats_resp() - handler for get stats response
|
||||
* @scn: scn handle
|
||||
* @event_buf: pointer to the event buffer
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int target_if_dcc_get_stats_resp(ol_scn_t scn,
|
||||
uint8_t *event_buf,
|
||||
uint32_t len)
|
||||
{
|
||||
int rc;
|
||||
QDF_STATUS status;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct ocb_dcc_get_stats_response *response;
|
||||
struct wlan_ocb_rx_ops *ocb_rx_ops;
|
||||
|
||||
target_if_debug("scn:%pK, data:%pK, datalen:%d",
|
||||
scn, event_buf, len);
|
||||
|
||||
if (!scn || !event_buf) {
|
||||
target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
psoc = target_if_get_psoc_from_scn_hdl(scn);
|
||||
if (!psoc) {
|
||||
target_if_err("null psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!pdev) {
|
||||
target_if_err("pdev is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
|
||||
if (ocb_rx_ops->ocb_dcc_stats_indicate) {
|
||||
status = wmi_extract_dcc_stats(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
event_buf, &response);
|
||||
if (!response || QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("Cannot get DCC stats");
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = ocb_rx_ops->ocb_dcc_stats_indicate(psoc,
|
||||
response,
|
||||
true);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("dcc_stats_indicate failed.");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
target_if_fatal("No dcc_stats_indicate callback");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
exit:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
|
||||
if (response)
|
||||
qdf_mem_free(response);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* target_if_dcc_stats_resp() - handler for DCC stats indication event
|
||||
* @scn: scn handle
|
||||
* @event_buf: pointer to the event buffer
|
||||
* @len: length of the buffer
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int target_if_dcc_stats_resp(ol_scn_t scn, uint8_t *event_buf,
|
||||
uint32_t len)
|
||||
{
|
||||
int rc;
|
||||
QDF_STATUS status;
|
||||
struct wlan_objmgr_pdev *pdev;
|
||||
struct wlan_objmgr_psoc *psoc;
|
||||
struct ocb_dcc_get_stats_response *response;
|
||||
struct wlan_ocb_rx_ops *ocb_rx_ops;
|
||||
|
||||
target_if_debug("scn:%pK, data:%pK, datalen:%d",
|
||||
scn, event_buf, len);
|
||||
|
||||
if (!scn || !event_buf) {
|
||||
target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
psoc = target_if_get_psoc_from_scn_hdl(scn);
|
||||
if (!psoc) {
|
||||
target_if_err("null psoc");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
|
||||
WLAN_OCB_SB_ID);
|
||||
if (!pdev) {
|
||||
target_if_err("pdev is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ocb_rx_ops = target_if_ocb_get_rx_ops(pdev);
|
||||
if (ocb_rx_ops->ocb_dcc_stats_indicate) {
|
||||
status = wmi_extract_dcc_stats(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
event_buf, &response);
|
||||
if (!response || QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("Cannot get DCC stats");
|
||||
rc = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
status = ocb_rx_ops->ocb_dcc_stats_indicate(psoc,
|
||||
response,
|
||||
false);
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
target_if_err("dcc_stats_indicate failed.");
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
target_if_fatal("dcc_stats_indicate failed.");
|
||||
response = NULL;
|
||||
rc = -EINVAL;
|
||||
}
|
||||
exit:
|
||||
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_SB_ID);
|
||||
if (response)
|
||||
qdf_mem_free(response);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
QDF_STATUS target_if_ocb_register_event_handler(struct wlan_objmgr_psoc *psoc,
|
||||
void *arg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Initialize the members in WMA used by wma_ocb */
|
||||
rc = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_ocb_set_config_resp_event_id,
|
||||
target_if_ocb_set_config_resp);
|
||||
if (rc) {
|
||||
target_if_err("Failed to register OCB config resp event cb");
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
rc = wmi_unified_register_event(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_ocb_get_tsf_timer_resp_event_id,
|
||||
target_if_ocb_get_tsf_timer_resp);
|
||||
if (rc) {
|
||||
target_if_err("Failed to register OCB TSF resp event cb");
|
||||
goto unreg_set_config;
|
||||
}
|
||||
|
||||
rc = wmi_unified_register_event(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_get_stats_resp_event_id,
|
||||
target_if_dcc_get_stats_resp);
|
||||
if (rc) {
|
||||
target_if_err("Failed to register DCC get stats resp event cb");
|
||||
goto unreg_tsf_timer;
|
||||
}
|
||||
|
||||
rc = wmi_unified_register_event(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_update_ndl_resp_event_id,
|
||||
target_if_dcc_update_ndl_resp);
|
||||
if (rc) {
|
||||
target_if_err("Failed to register NDL update event cb");
|
||||
goto unreg_get_stats;
|
||||
}
|
||||
|
||||
rc = wmi_unified_register_event(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_stats_event_id,
|
||||
target_if_dcc_stats_resp);
|
||||
if (rc) {
|
||||
target_if_err("Failed to register DCC stats event cb");
|
||||
goto unreg_ndl;
|
||||
}
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
|
||||
unreg_ndl:
|
||||
wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_update_ndl_resp_event_id);
|
||||
unreg_get_stats:
|
||||
wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_get_stats_resp_event_id);
|
||||
unreg_tsf_timer:
|
||||
wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_ocb_get_tsf_timer_resp_event_id);
|
||||
unreg_set_config:
|
||||
wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_ocb_set_config_resp_event_id);
|
||||
|
||||
return QDF_STATUS_E_FAILURE;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
target_if_ocb_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
|
||||
void *arg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_stats_event_id);
|
||||
if (rc)
|
||||
target_if_err("Failed to unregister DCC stats event cb");
|
||||
|
||||
rc = wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_update_ndl_resp_event_id);
|
||||
if (rc)
|
||||
target_if_err("Failed to unregister NDL update event cb");
|
||||
|
||||
rc = wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_dcc_get_stats_resp_event_id);
|
||||
if (rc)
|
||||
target_if_err("Failed to unregister DCC get stats resp cb");
|
||||
|
||||
rc = wmi_unified_unregister_event_handler(
|
||||
GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_ocb_get_tsf_timer_resp_event_id);
|
||||
if (rc)
|
||||
target_if_err("Failed to unregister OCB TSF resp event cb");
|
||||
|
||||
rc = wmi_unified_unregister_event(GET_WMI_HDL_FROM_PSOC(psoc),
|
||||
wmi_ocb_set_config_resp_event_id);
|
||||
if (rc)
|
||||
target_if_err("Failed to unregister OCB config resp event cb");
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
QDF_STATUS
|
||||
target_if_ocb_register_tx_ops(struct wlan_ocb_tx_ops *ocb_txops)
|
||||
{
|
||||
ocb_txops->ocb_set_config = target_if_ocb_set_config;
|
||||
ocb_txops->ocb_set_utc_time = target_if_ocb_set_utc_time;
|
||||
ocb_txops->ocb_start_timing_advert = target_if_ocb_start_timing_advert;
|
||||
ocb_txops->ocb_stop_timing_advert = target_if_ocb_stop_timing_advert;
|
||||
ocb_txops->ocb_get_tsf_timer = target_if_ocb_get_tsf_timer;
|
||||
ocb_txops->ocb_dcc_get_stats = target_if_dcc_get_stats;
|
||||
ocb_txops->ocb_dcc_clear_stats = target_if_dcc_clear_stats;
|
||||
ocb_txops->ocb_dcc_update_ndl = target_if_dcc_update_ndl;
|
||||
ocb_txops->ocb_reg_ev_handler = target_if_ocb_register_event_handler;
|
||||
ocb_txops->ocb_unreg_ev_handler =
|
||||
target_if_ocb_unregister_event_handler;
|
||||
|
||||
return QDF_STATUS_SUCCESS;
|
||||
}
|
Reference in New Issue
Block a user