qcacld-3.0: Add UCFG APIs and public structures for OCB

Add UCFG interface and public structures for OCB feature.

CRs-Fixed: 2177578
Change-Id: Id74df706e658568a0f50a8d953eca3993451f41a
此提交包含在:
Zhang Qian
2018-01-04 15:38:38 +08:00
提交者 snandini
父節點 f610d91865
當前提交 47e22cefc3
共有 12 個檔案被更改,包括 1734 行新增85 行删除

查看文件

@@ -0,0 +1,265 @@
/*
* 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 ocb init/deinit public api
*/
#ifndef _WLAN_OCB_MAIN_API_H_
#define _WLAN_OCB_MAIN_API_H_
#include <qdf_atomic.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_pdev_obj.h>
#include <wlan_objmgr_vdev_obj.h>
#include <wlan_ocb_public_structs.h>
#define ocb_log_ratelimited(rate, level, args...) \
QDF_TRACE_RATE_LIMITED(rate, QDF_MODULE_ID_OCB, level, ## args)
#define ocb_log_ratelimited_fl(rate, level, format, args...) \
ocb_log_ratelimited(rate, level, FL(format), ## args)
#define ocb_alert_ratelimited(rate, format, args...) \
ocb_log_ratelimited_fl(rate, QDF_TRACE_LEVEL_FATAL,\
format, ## args)
#define ocb_err_ratelimited(rate, format, args...) \
ocb_log_ratelimited_fl(rate, QDF_TRACE_LEVEL_ERROR,\
format, ## args)
#define ocb_warn_ratelimited(rate, format, args...) \
ocb_log_ratelimited_fl(rate, QDF_TRACE_LEVEL_WARN,\
format, ## args)
#define ocb_notice_ratelimited(rate, format, args...) \
ocb_log_ratelimited_fl(rate, QDF_TRACE_LEVEL_INFO,\
format, ## args)
#define ocb_info_ratelimited(rate, format, args...) \
ocb_log_ratelimited_fl(rate, QDF_TRACE_LEVEL_INFO,\
format, ## args)
#define ocb_debug_ratelimited(rate, format, args...) \
ocb_log_ratelimited_fl(rate, QDF_TRACE_LEVEL_DEBUG,\
format, ## args)
#define ocb_log(level, args...) \
QDF_TRACE(QDF_MODULE_ID_OCB, level, ## args)
#define ocb_logfl(level, format, args...) \
ocb_log(level, FL(format), ## args)
#define ocb_alert(format, args...) \
ocb_logfl(QDF_TRACE_LEVEL_FATAL, format, ## args)
#define ocb_err(format, args...) \
ocb_logfl(QDF_TRACE_LEVEL_ERROR, format, ## args)
#define ocb_warn(format, args...) \
ocb_logfl(QDF_TRACE_LEVEL_WARN, format, ## args)
#define ocb_notice(format, args...) \
ocb_logfl(QDF_TRACE_LEVEL_INFO, format, ## args)
#define ocb_info(format, args...) \
ocb_logfl(QDF_TRACE_LEVEL_INFO_HIGH, format, ## args)
#define ocb_debug(format, args...) \
ocb_logfl(QDF_TRACE_LEVEL_DEBUG, format, ## args)
/**
* enum ocb_southbound_event - OCB south bound event type
* @OCB_CHANNEL_CONFIG_STATUS: set channel config response
* @OCB_TSF_TIMER: get TSF timer response
* @OCB_DCC_STATS_RESPONSE: get DCC stats response
* @OCB_NDL_RESPONSE: NDL update response
* @OCB_DCC_INDICATION: DCC stats indication
*/
enum ocb_southbound_event {
OCB_CHANNEL_CONFIG_STATUS,
OCB_TSF_TIMER,
OCB_DCC_STATS_RESPONSE,
OCB_NDL_RESPONSE,
OCB_DCC_INDICATION,
};
/**
* struct ocb_pdev_obj - ocb pdev object
* @pdev: pdev handle
* @ocb_mac: MAC address for different channels
* @ocb_channel_count: channel count
* @channel_config: current channel configurations
* @dp_soc: psoc data path handle
* @dp_pdev: pdev data path handle
* @ocb_cbs: legacy callback functions
* @ocb_txops: tx opertions for target interface
* @ocb_rxops: rx opertions for target interface
*/
struct ocb_pdev_obj {
struct wlan_objmgr_pdev *pdev;
struct qdf_mac_addr ocb_mac[QDF_MAX_CONCURRENCY_PERSONA];
uint32_t ocb_channel_count;
struct ocb_config *channel_config;
void *dp_soc;
void *dp_pdev;
struct ocb_callbacks ocb_cbs;
struct wlan_ocb_tx_ops ocb_txops;
struct wlan_ocb_rx_ops ocb_rxops;
};
/**
* struct ocb_rx_event - event from south bound
* @psoc: psoc handle
* @vdev: vdev handle
* @evt_id: event ID
* @channel_cfg_rsp: set channel config status
* @tsf_timer: get TSF timer response
* @ndl: NDL DCC response
* @dcc_stats: DCC stats
*/
struct ocb_rx_event {
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_vdev *vdev;
uint32_t evt_id;
union event {
struct ocb_set_config_response channel_cfg_rsp;
struct ocb_get_tsf_timer_response tsf_timer;
struct ocb_dcc_update_ndl_response ndl;
struct ocb_dcc_get_stats_response dcc_stats;
} rsp;
};
/**
* wlan_get_pdev_ocb_obj() - private API to get ocb pdev object
* @pdev: pdev object
*
* Return: ocb object
*/
static inline struct ocb_pdev_obj *
wlan_get_pdev_ocb_obj(struct wlan_objmgr_pdev *pdev)
{
struct ocb_pdev_obj *pdev_obj;
pdev_obj = (struct ocb_pdev_obj *)
wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_UMAC_COMP_OCB);
return pdev_obj;
}
/**
* wlan_ocb_get_callbacks() - get legacy layer callbacks
* @pdev: pdev handle
*
* Return: legacy layer callbacks
*/
static inline struct ocb_callbacks *
wlan_ocb_get_callbacks(struct wlan_objmgr_pdev *pdev)
{
struct ocb_pdev_obj *pdev_obj;
pdev_obj = wlan_get_pdev_ocb_obj(pdev);
if (pdev_obj)
return &pdev_obj->ocb_cbs;
else
return NULL;
}
/**
* wlan_pdev_get_ocb_tx_ops() - get OCB tx operations
* @pdev: pdev handle
*
* Return: fps to OCB tx operations
*/
static inline struct wlan_ocb_tx_ops *
wlan_pdev_get_ocb_tx_ops(struct wlan_objmgr_pdev *pdev)
{
struct ocb_pdev_obj *ocb_obj;
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
return &ocb_obj->ocb_txops;
}
/**
* wlan_ocb_release_rx_event() - Release OCB RX event
* @event: OCB RX event
*
* Return: none
*/
static inline void wlan_ocb_release_rx_event(struct ocb_rx_event *event)
{
if (!event) {
ocb_err("event is NULL");
return;
}
if (event->vdev)
wlan_objmgr_vdev_release_ref(event->vdev, WLAN_OCB_SB_ID);
if (event->psoc)
wlan_objmgr_psoc_release_ref(event->psoc, WLAN_OCB_SB_ID);
qdf_mem_free(event);
}
/**
* ocb_pdev_obj_create_notification() - OCB pdev object creation notification
* @pdev: pdev handle
* @arg_list: arguments list
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ocb_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
void *arg_list);
/**
* ocb_pdev_obj_destroy_notification() - OCB pdev object destroy notification
* @pdev: pdev handle
* @arg_list: arguments list
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ocb_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
void *arg_list);
/**
* ocb_config_new() - Creates a new OCB configuration
* @num_channels: the number of channels
* @num_schedule: the schedule size
* @ndl_chan_list_len: length in bytes of the NDL chan blob
* @ndl_active_state_list_len: length in bytes of the active state blob
*
* Return: A pointer to the OCB configuration struct, NULL on failure.
*/
struct ocb_config *ocb_config_new(uint32_t num_channels,
uint32_t num_schedule,
uint32_t ndl_chan_list_len,
uint32_t ndl_active_state_list_len);
/**
* ocb_copy_config() - Backup current config parameters
* @src: current config parameters
*
* Return: A pointer to the OCB configuration struct, NULL on failure.
*/
struct ocb_config *ocb_copy_config(struct ocb_config *src);
/**
* ocb_process_evt() - API to process event from south bound
* @msg: south bound message
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ocb_process_evt(struct scheduler_msg *msg);
/**
* ocb_vdev_start() - start OCB vdev
* @ocb_obj: OCB object
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ocb_vdev_start(struct ocb_pdev_obj *ocb_obj);
#endif

查看文件

@@ -0,0 +1,350 @@
/*
* 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 ocb structure definitions
*/
#ifndef _WLAN_OCB_STRUCTS_H_
#define _WLAN_OCB_STRUCTS_H_
#include <qdf_status.h>
/* number of vdevs that can support OCB */
#define OCB_VDEVS_NUM 1
/* maximum number of channels that can do OCB */
#define OCB_CHANNELS_NUM 2
/* maximum number of channels in an OCB schedule */
#define OCB_SCHEDULES_NUM 2
/* Don't add the RX stats header to packets received on this channel */
#define OCB_CHANNEL_FLAG_DISABLE_RX_STATS_HDR (1 << 0)
/* The size of the utc time in bytes. */
#define OCB_SIZE_UTC_TIME (10)
/* The size of the utc time error in bytes. */
#define OCB_SIZE_UTC_TIME_ERROR (5)
#define OCB_CHANNEL_MAX (5)
#define OCB_MAX_NUM_AC (4)
/**
* struct ocb_utc_param - parameters to set UTC time
* @vdev_id: vdev id
* @utc_time: number of nanoseconds from Jan 1st 1958
* @time_error: the error in the UTC time. All 1's for unknown
*/
struct ocb_utc_param {
uint32_t vdev_id;
uint8_t utc_time[OCB_SIZE_UTC_TIME];
uint8_t time_error[OCB_SIZE_UTC_TIME_ERROR];
};
/**
* struct ocb_timing_advert_param - parameters to start/stop
* timing advertisement
* @vdev_id: vdev id
* @chan_freq: frequency on which to advertise (unit in Mhz)
* @repeat_rate: the number of times it will send TA in 5 seconds
* @timestamp_offset: offset of the timestamp field in the TA frame
* @time_value_offset: offset of the time_value field in the TA frame
* @template_length: size in bytes of the TA frame
* @template_value: the TA frame
*/
struct ocb_timing_advert_param {
uint32_t vdev_id;
uint32_t chan_freq;
uint32_t repeat_rate;
uint32_t timestamp_offset;
uint32_t time_value_offset;
uint32_t template_length;
uint8_t *template_value;
};
/**
* struct ocb_dcc_get_stats_param - parameters to get DCC stats
* @vdev_id: vdev id
* @channel_count: number of dcc channels
* @request_array_len: size in bytes of the request array
* @request_array: the request array
*/
struct ocb_dcc_get_stats_param {
uint32_t vdev_id;
uint32_t channel_count;
uint32_t request_array_len;
void *request_array;
};
/**
* struct ocb_dcc_update_ndl_param - parameters to update NDL
* @vdev_id: vdev id
* @channel_count: number of channels to be updated
* @dcc_ndl_chan_list_len: size in bytes of the ndl_chan array
* @dcc_ndl_chan_list: the ndl_chan array
* @dcc_ndl_active_state_list_len: size in bytes of the active_state array
* @dcc_ndl_active_state_list: the active state array
*/
struct ocb_dcc_update_ndl_param {
uint32_t vdev_id;
uint32_t channel_count;
uint32_t dcc_ndl_chan_list_len;
void *dcc_ndl_chan_list;
uint32_t dcc_ndl_active_state_list_len;
void *dcc_ndl_active_state_list;
};
/**
* struct ocb_config_schdl - parameters for channel scheduling
* @chan_freq: frequency of the channel (unit in Mhz)
* @total_duration: duration of the schedule (unit in ms)
* @guard_interval: guard interval on the start of the schedule (unit in ms)
*/
struct ocb_config_schdl {
uint32_t chan_freq;
uint32_t total_duration;
uint32_t guard_interval;
};
/**
* struct ocb_wmm_param - WMM parameters
* @aifsn: AIFS number
* @cwmin: value of CWmin
* @cwmax: value of CWmax
*/
struct ocb_wmm_param {
uint8_t aifsn;
uint8_t cwmin;
uint8_t cwmax;
};
/**
* struct ocb_config_chan - parameters to configure a channel
* @chan_freq: frequency of the channel (unit in MHz)
* @bandwidth: bandwidth of the channel, either 10 or 20 MHz
* @mac_address: MAC address assigned to this channel
* @qos_params: QoS parameters
* @max_pwr: maximum transmit power of the channel (dBm)
* @min_pwr: minimum transmit power of the channel (dBm)
* @reg_pwr: maximum transmit power specified by the regulatory domain (dBm)
* @antenna_max: maximum antenna gain specified by the regulatory domain (dB)
* @flags: bit0: 0 enable RX stats on this channel; 1 disable RX stats
* bit1: flag to indicate TSF expiry time in TX control.
* 0 relative time is used. 1 absolute time is used.
* bit2: Frame mode from user layer.
* 0 for 802.3 frame, 1 for 802.11 frame.
* @ch_mode: channel mode
*/
struct ocb_config_chan {
uint32_t chan_freq;
uint32_t bandwidth;
struct qdf_mac_addr mac_address;
struct ocb_wmm_param qos_params[OCB_MAX_NUM_AC];
uint32_t max_pwr;
uint32_t min_pwr;
uint8_t reg_pwr;
uint8_t antenna_max;
uint16_t flags;
uint32_t ch_mode;
};
/**
* struct ocb_config - parameters for OCB vdev config
* @vdev_id: vdev id
* @channel_count: number of channels
* @schedule_size: size of the channel schedule
* @flags: reserved
* @channels: array of OCB channels
* @schedule: array of OCB schedule elements
* @dcc_ndl_chan_list_len: size in bytes of the ndl_chan array
* @dcc_ndl_chan_list: array of dcc channel info
* @dcc_ndl_active_state_list_len: size in bytes of the active state array
* @dcc_ndl_active_state_list: array of active states
*/
struct ocb_config {
uint32_t vdev_id;
uint32_t channel_count;
uint32_t schedule_size;
uint32_t flags;
struct ocb_config_chan *channels;
struct ocb_config_schdl *schedule;
uint32_t dcc_ndl_chan_list_len;
void *dcc_ndl_chan_list;
uint32_t dcc_ndl_active_state_list_len;
void *dcc_ndl_active_state_list;
};
/**
* enum ocb_channel_config_status - ocb config status
* @OCB_CHANNEL_CONFIG_SUCCESS: success
* @OCB_CHANNEL_CONFIG_FAIL: failure
* @OCB_CHANNEL_CONFIG_STATUS_MAX: place holder, not a real status
*/
enum ocb_channel_config_status {
OCB_CHANNEL_CONFIG_SUCCESS = 0,
OCB_CHANNEL_CONFIG_FAIL,
OCB_CHANNEL_CONFIG_STATUS_MAX
};
/**
* struct ocb_set_config_response - ocb config status
* @status: response status. OCB_CHANNEL_CONFIG_SUCCESS for success.
*/
struct ocb_set_config_response {
enum ocb_channel_config_status status;
};
/**
* struct ocb_get_tsf_timer_response - TSF timer response
* @vdev_id: vdev id
* @timer_high: higher 32-bits of the timer
* @timer_low: lower 32-bits of the timer
*/
struct ocb_get_tsf_timer_response {
uint32_t vdev_id;
uint32_t timer_high;
uint32_t timer_low;
};
/**
* struct ocb_get_tsf_timer_param - parameters to get tsf timer
* @vdev_id: vdev id
*/
struct ocb_get_tsf_timer_param {
uint32_t vdev_id;
};
/**
* struct ocb_dcc_get_stats_response - DCC stats response
* @vdev_id: vdev id
* @num_channels: number of dcc channels
* @channel_stats_array_len: size in bytes of the stats array
* @channel_stats_array: the stats array
*/
struct ocb_dcc_get_stats_response {
uint32_t vdev_id;
uint32_t num_channels;
uint32_t channel_stats_array_len;
void *channel_stats_array;
};
/**
* struct ocb_dcc_clear_stats_param - parameters to clear DCC stats
* @vdev_id: vdev id
* @dcc_stats_bitmap: bitmap of clear option
*/
struct ocb_dcc_clear_stats_param {
uint32_t vdev_id;
uint32_t dcc_stats_bitmap;
};
/**
* struct ocb_dcc_update_ndl_response - NDP update response
* @vdev_id: vdev id
* @status: response status
*/
struct ocb_dcc_update_ndl_response {
uint32_t vdev_id;
uint32_t status;
};
/**
* struct wlan_ocb_rx_ops - structure containing rx ops for OCB
* @ocb_set_config_status: fp to get channel config status
* @ocb_tsf_timer: fp to get TSF timer
* @ocb_dcc_ndl_update: fp to get NDL update status
* @ocb_dcc_stats_indicate: fp to get DCC stats
*/
struct wlan_ocb_rx_ops {
QDF_STATUS (*ocb_set_config_status)(struct wlan_objmgr_psoc *psoc,
uint32_t status);
QDF_STATUS (*ocb_tsf_timer)(struct wlan_objmgr_psoc *psoc,
struct ocb_get_tsf_timer_response *response);
QDF_STATUS (*ocb_dcc_ndl_update)(struct wlan_objmgr_psoc *psoc,
struct ocb_dcc_update_ndl_response *resp);
QDF_STATUS (*ocb_dcc_stats_indicate)(struct wlan_objmgr_psoc *psoc,
struct ocb_dcc_get_stats_response *response, bool indicate);
};
/**
* struct wlan_ocb_tx_ops - structures containing tx ops for OCB
* @ocb_set_config: fp to set channel config
* @ocb_set_utc_time: fp to set utc time
* @ocb_start_timing_advert: fp to start timing advertisement
* @ocb_stop_timing_advert: fp to stop timing advertisement
* @ocb_get_tsf_timer: fp to get tsf timer
* @ocb_dcc_get_stats: fp to get DCC stats
* @ocb_dcc_clear_stats: fp to clear DCC stats
* @ocb_dcc_update_ndl: fp to update ndl
* @ocb_reg_ev_handler: fp to register event handler
* @ocb_unreg_ev_handler: fp to unregister event handler
*/
struct wlan_ocb_tx_ops {
QDF_STATUS (*ocb_set_config)(struct wlan_objmgr_psoc *psoc,
struct ocb_config *config);
QDF_STATUS (*ocb_set_utc_time)(struct wlan_objmgr_psoc *psoc,
struct ocb_utc_param *utc);
QDF_STATUS (*ocb_start_timing_advert)(struct wlan_objmgr_psoc *psoc,
struct ocb_timing_advert_param *timing_advert);
QDF_STATUS (*ocb_stop_timing_advert)(struct wlan_objmgr_psoc *psoc,
struct ocb_timing_advert_param *timing_advert);
QDF_STATUS (*ocb_get_tsf_timer)(struct wlan_objmgr_psoc *psoc,
struct ocb_get_tsf_timer_param *request);
QDF_STATUS (*ocb_dcc_get_stats)(struct wlan_objmgr_psoc *psoc,
struct ocb_dcc_get_stats_param *get_stats_param);
QDF_STATUS (*ocb_dcc_clear_stats)(struct wlan_objmgr_psoc *psoc,
struct ocb_dcc_clear_stats_param *clear_stats);
QDF_STATUS (*ocb_dcc_update_ndl)(struct wlan_objmgr_psoc *psoc,
struct ocb_dcc_update_ndl_param *update_ndl_param);
QDF_STATUS (*ocb_reg_ev_handler)(struct wlan_objmgr_psoc *psoc,
void *arg);
QDF_STATUS (*ocb_unreg_ev_handler)(struct wlan_objmgr_psoc *psoc,
void *arg);
};
typedef void (*ocb_sync_callback)(void *context, void *response);
/**
* struct ocb_callback - structure containing callback to legacy driver
* @ocb_set_config_context: context for set channel config callback
* @ocb_set_config_callback: set channel config callback
* @ocb_get_tsf_timer_context: context for get tsf timer callback
* @ocb_get_tsf_timer_callback: get tsf timer callback
* @ocb_dcc_get_stats_context: context for get DCC stats callback
* @ocb_dcc_get_stats_callback: get DCC stats callback
* @ocb_dcc_update_ndl_context: context for NDL update callback
* @ocb_dcc_update_ndl_callback: NDL update callback
* @ocb_dcc_stats_event_context: context for DCC stats event callback
* @ocb_dcc_stats_event_callback: DCC stats event callback
* @start_ocb_vdev: start ocb callback
*/
struct ocb_callbacks {
void *ocb_set_config_context;
ocb_sync_callback ocb_set_config_callback;
void *ocb_get_tsf_timer_context;
ocb_sync_callback ocb_get_tsf_timer_callback;
void *ocb_dcc_get_stats_context;
ocb_sync_callback ocb_dcc_get_stats_callback;
void *ocb_dcc_update_ndl_context;
ocb_sync_callback ocb_dcc_update_ndl_callback;
void *ocb_dcc_stats_event_context;
ocb_sync_callback ocb_dcc_stats_event_callback;
QDF_STATUS (*start_ocb_vdev)(struct ocb_config *config);
};
#endif

查看文件

@@ -0,0 +1,290 @@
/*
* 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 OCB north bound interface definitions
*/
#ifndef _WLAN_OCB_UCFG_API_H_
#define _WLAN_OCB_UCFG_API_H_
#include <qdf_types.h>
#include "wlan_ocb_public_structs.h"
#ifdef WLAN_FEATURE_DSRC
/**
* ucfg_ocb_set_channel_config() - send OCB config request
* @vdev: vdev handle
* @config: config parameters
* @set_config_cb: callback for set channel config
* @arg: arguments for the callback
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_set_channel_config(struct wlan_objmgr_vdev *vdev,
struct ocb_config *config,
ocb_sync_callback set_config_cb,
void *arg);
/**
* ucfg_ocb_set_utc_time() - UCFG API to set UTC time
* @vdev: vdev handle
* @utc: UTC time
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_set_utc_time(struct wlan_objmgr_vdev *vdev,
struct ocb_utc_param *utc);
/**
* ucfg_ocb_start_timing_advert() - ucfg API to start TA
* @vdev: vdev handle
* @ta: timing advertisement parameters
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_start_timing_advert(struct wlan_objmgr_vdev *vdev,
struct ocb_timing_advert_param *ta);
/**
* ucfg_ocb_stop_timing_advert() - ucfg API to stop TA
* @vdev: vdev handle
* @ta: timing advertisement parameters
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_stop_timing_advert(struct wlan_objmgr_vdev *vdev,
struct ocb_timing_advert_param *ta);
/**
* ucfg_ocb_get_tsf_timer() - ucfg API to get tsf timer
* @vdev: vdev handle
* @request: request for TSF timer
* @get_tsf_cb: callback for TSF timer response
* @arg: argument for the ccallback
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_get_tsf_timer(struct wlan_objmgr_vdev *vdev,
struct ocb_get_tsf_timer_param *request,
ocb_sync_callback get_tsf_cb,
void *arg);
/**
* ucfg_ocb_dcc_get_stats() - get DCC stats
* @vdev: vdev handle
* @request: request for dcc stats
* @dcc_get_stats_cb: callback for get dcc stats response
* @arg: argument for the ccallback
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_dcc_get_stats(struct wlan_objmgr_vdev *vdev,
struct ocb_dcc_get_stats_param *request,
ocb_sync_callback dcc_get_stats_cb,
void *arg);
/**
* ucfg_ocb_dcc_clear_stats() - Clear DCC stats
* @vdev: vdev handle
* @vdev_id: vdev ID
* @bitmap: bitmap for stats to be cleared
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_dcc_clear_stats(struct wlan_objmgr_vdev *vdev,
uint16_t vdev_id,
uint32_t bitmap);
/**
* ucfg_ocb_dcc_update_ndl() - ucfg API to update NDL
* @vdev: vdev handle
* @request: request parameters
* @dcc_update_ndl_cb: callback for update resposne
* @arg: argument for the callback
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_dcc_update_ndl(struct wlan_objmgr_vdev *vdev,
struct ocb_dcc_update_ndl_param *request,
ocb_sync_callback dcc_update_ndl_cb,
void *arg);
/**
* ucfg_ocb_register_for_dcc_stats_event() - register dcc stats
* events callback
* @pdev: pdev handle
* @context: argument for the callback
* @dcc_stats_cb: callback for dcc stats event
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_register_for_dcc_stats_event(struct wlan_objmgr_pdev *pdev,
void *ctx, ocb_sync_callback dcc_stats_cb);
/**
* ucfg_ocb_init() - OCB module initialization
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_init(void);
/**
* ucfg_ocb_deinit() - OCB module deinitialization
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_deinit(void);
/**
* ucfg_ocb_config_channel() - Set channel config using after OCB started
* @pdev: pdev handle
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_config_channel(struct wlan_objmgr_pdev *pdev);
/**
* ucfg_ocb_register_vdev_start() - register callback to start ocb vdev
* @pdev: pdev handle
* @ocb_start: legacy callback to start ocb vdev
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_register_vdev_start(struct wlan_objmgr_pdev *pdev,
QDF_STATUS (*ocb_start)(struct ocb_config *));
/**
* ocb_psoc_enable() - Trigger psoc enable for ocb
* @psoc: objmgr psoc object
*
* Return: QDF status success or failure
*/
QDF_STATUS ocb_psoc_enable(struct wlan_objmgr_psoc *psoc);
/**
* ocb_psoc_disable() - Trigger psoc disable for ocb
* @psoc: objmgr psoc object
*
* Return: QDF status success or failure
*/
QDF_STATUS ocb_psoc_disable(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_ocb_update_dp_handle() - register DP handle
* @soc: soc handle
* @dp_soc: data path soc handle
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_update_dp_handle(struct wlan_objmgr_psoc *soc,
void *dp_soc);
/**
* ucfg_ocb_set_txrx_handle() - register pdev txrx handler
* @soc: soc handle
* @txrx_handle: data path pdev txrx handle
*
* Return: QDF_STATUS_SUCCESS on success
*/
QDF_STATUS ucfg_ocb_set_txrx_handle(struct wlan_objmgr_psoc *psoc,
void *txrx_handle);
#else
/**
* ucfg_ocb_init() - OCB module initialization
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline QDF_STATUS ucfg_ocb_init(void)
{
return QDF_STATUS_SUCCESS;
}
/**
* ucfg_ocb_deinit() - OCB module deinitialization
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline QDF_STATUS ucfg_ocb_deinit(void)
{
return QDF_STATUS_SUCCESS;
}
/**
* ucfg_ocb_config_channel() - Set channel config using after OCB started
* @pdev: pdev handle
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline QDF_STATUS
ucfg_ocb_config_channel(struct wlan_objmgr_pdev *pdev)
{
return QDF_STATUS_SUCCESS;
}
/**
* ocb_psoc_enable() - Trigger psoc enable for ocb
* @psoc: objmgr psoc object
*
* Return: QDF status success or failure
*/
static inline
QDF_STATUS ocb_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
/**
* ocb_psoc_disable() - Trigger psoc disable for ocb
* @psoc: objmgr psoc object
*
* Return: QDF status success or failure
*/
static inline
QDF_STATUS ocb_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
return QDF_STATUS_SUCCESS;
}
/**
* ucfg_ocb_update_dp_handle() - register DP handle
* @soc: soc handle
* @dp_soc: data path soc handle
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline
QDF_STATUS ucfg_ocb_update_dp_handle(struct wlan_objmgr_psoc *soc,
void *dp_soc)
{
return QDF_STATUS_SUCCESS;
}
/**
* ucfg_ocb_set_txrx_handle() - register pdev txrx handler
* @soc: soc handle
* @txrx_handle: data path pdev txrx handle
*
* Return: QDF_STATUS_SUCCESS on success
*/
static inline
QDF_STATUS ucfg_ocb_set_txrx_handle(struct wlan_objmgr_psoc *psoc,
void *txrx_handle)
{
return QDF_STATUS_SUCCESS;
}
#endif
#endif

查看文件

@@ -0,0 +1,629 @@
/*
* 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 north bound interface definitions
*/
#include <scheduler_api.h>
#include <wlan_defs.h>
#include <wlan_reg_services_api.h>
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_global_obj.h>
#include <wlan_ocb_public_structs.h>
#include <wlan_ocb_ucfg_api.h>
#include <wlan_ocb_tgt_api.h>
#include <wlan_lmac_if_def.h>
#include "wlan_ocb_main.h"
/**
* wlan_ocb_get_tx_ops() - get target interface tx operations
* @pdev: pdev handle
*
* Return: fp to target interface operations
*/
static struct wlan_ocb_tx_ops *
wlan_ocb_get_tx_ops(struct wlan_objmgr_pdev *pdev)
{
struct ocb_pdev_obj *ocb_obj;
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
if (!ocb_obj) {
ocb_err("failed to get OCB pdev object");
return NULL;
}
return &ocb_obj->ocb_txops;
}
QDF_STATUS ucfg_ocb_init(void)
{
QDF_STATUS status;
ocb_notice("ocb module dispatcher init");
status = wlan_objmgr_register_pdev_create_handler(WLAN_UMAC_COMP_OCB,
ocb_pdev_obj_create_notification, NULL);
if (QDF_IS_STATUS_ERROR(status)) {
ocb_err("Failed to register pdev create handler for ocb");
return status;
}
status = wlan_objmgr_register_pdev_destroy_handler(WLAN_UMAC_COMP_OCB,
ocb_pdev_obj_destroy_notification, NULL);
if (QDF_IS_STATUS_ERROR(status)) {
ocb_err("Failed to register pdev destroy handler for ocb");
goto fail_delete_pdev;
}
return status;
fail_delete_pdev:
wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_OCB,
ocb_pdev_obj_create_notification, NULL);
return status;
}
QDF_STATUS ucfg_ocb_deinit(void)
{
QDF_STATUS status;
ocb_notice("ocb module dispatcher deinit");
status = wlan_objmgr_unregister_pdev_destroy_handler(WLAN_UMAC_COMP_OCB,
ocb_pdev_obj_destroy_notification, NULL);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to unregister pdev destroy handler");
status = wlan_objmgr_unregister_pdev_create_handler(WLAN_UMAC_COMP_OCB,
ocb_pdev_obj_create_notification, NULL);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to unregister pdev create handler");
return status;
}
QDF_STATUS ocb_psoc_enable(struct wlan_objmgr_psoc *psoc)
{
struct wlan_objmgr_pdev *pdev;
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
WLAN_OCB_NB_ID);
if (!pdev) {
ocb_err("Failed to get pdev handle");
return QDF_STATUS_E_FAILURE;
}
tgt_ocb_register_ev_handler(pdev);
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ocb_psoc_disable(struct wlan_objmgr_psoc *psoc)
{
struct wlan_objmgr_pdev *pdev;
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
WLAN_OCB_NB_ID);
if (!pdev) {
ocb_err("Failed to get pdev handle");
return QDF_STATUS_E_FAILURE;
}
tgt_ocb_unregister_ev_handler(pdev);
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_ocb_set_txrx_handle(struct wlan_objmgr_psoc *psoc,
void *txrx_handle)
{
struct wlan_objmgr_pdev *pdev;
struct ocb_pdev_obj *ocb_obj;
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
WLAN_OCB_NB_ID);
if (!pdev) {
ocb_err("Failed to get pdev handle");
return QDF_STATUS_E_FAILURE;
}
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
if (!ocb_obj) {
ocb_err("OCB object is NULL");
return QDF_STATUS_E_FAILURE;
}
ocb_obj->dp_pdev = txrx_handle;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_ocb_update_dp_handle(struct wlan_objmgr_psoc *psoc,
void *dp_soc)
{
struct wlan_objmgr_pdev *pdev;
struct ocb_pdev_obj *ocb_obj;
pdev = wlan_objmgr_get_pdev_by_id(psoc, 0,
WLAN_OCB_NB_ID);
if (!pdev) {
ocb_err("Failed to get pdev handle");
return QDF_STATUS_E_FAILURE;
}
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
wlan_objmgr_pdev_release_ref(pdev, WLAN_OCB_NB_ID);
if (!ocb_obj) {
ocb_err("OCB object is NULL");
return QDF_STATUS_E_FAILURE;
}
ocb_obj->dp_soc = dp_soc;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_ocb_config_channel(struct wlan_objmgr_pdev *pdev)
{
QDF_STATUS status;
struct ocb_config *config;
struct ocb_pdev_obj *ocb_obj;
struct wlan_objmgr_psoc *psoc;
struct wlan_ocb_tx_ops *tx_ops;
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
if (!ocb_obj || !ocb_obj->channel_config) {
ocb_alert("The request could not be found");
return QDF_STATUS_E_FAILURE;
}
config = ocb_obj->channel_config;
ocb_debug("Set config to vdev%d", config->vdev_id);
psoc = wlan_pdev_get_psoc(pdev);
if (!psoc) {
ocb_err("Null pointer for psoc");
return QDF_STATUS_E_INVAL;
}
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (tx_ops && tx_ops->ocb_set_config)
status = tx_ops->ocb_set_config(psoc, ocb_obj->channel_config);
else
status = QDF_STATUS_E_IO;
if (QDF_IS_STATUS_SUCCESS(status)) {
ocb_debug("Set channel cmd is sent to southbound");
} else {
ocb_err("Failed to set channel config to southbound");
if (ocb_obj->channel_config) {
/*
* On success case, backup parameters will be released
* after channel info is synced to DP
*/
ocb_info("release the backed config parameters");
qdf_mem_free(ocb_obj->channel_config);
ocb_obj->channel_config = NULL;
}
}
return status;
}
QDF_STATUS ucfg_ocb_set_channel_config(struct wlan_objmgr_vdev *vdev,
struct ocb_config *config,
ocb_sync_callback set_config_cb,
void *arg)
{
QDF_STATUS status;
enum wlan_vdev_state state;
uint32_t i;
struct wlan_objmgr_pdev *pdev;
struct wlan_objmgr_psoc *psoc;
struct wlan_ocb_tx_ops *tx_ops;
struct ocb_pdev_obj *ocb_obj;
struct ocb_callbacks *ocb_cbs;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
ocb_obj = wlan_get_pdev_ocb_obj(pdev);
if (!ocb_obj) {
ocb_alert("Failed to get OCB vdev object");
return QDF_STATUS_E_IO;
}
if (!config) {
ocb_err("Invalid config input");
return QDF_STATUS_E_FAILURE;
}
for (i = 0; i < config->channel_count; i++) {
if (WLAN_REG_CHAN_TO_BAND(wlan_reg_freq_to_chan(pdev,
config->channels[i].chan_freq))
== BAND_2G)
config->channels[i].ch_mode = MODE_11G;
else
config->channels[i].ch_mode = MODE_11A;
}
/*
* backup the new configuration,
* it will be released after target's response
*/
ocb_obj->channel_config = ocb_copy_config(config);
if (!ocb_obj->channel_config) {
ocb_err("Failed to backup config");
return QDF_STATUS_E_NOMEM;
}
ocb_cbs = &ocb_obj->ocb_cbs;
ocb_cbs->ocb_set_config_callback = set_config_cb;
ocb_cbs->ocb_set_config_context = arg;
state = wlan_vdev_mlme_get_state(vdev);
if (state != WLAN_VDEV_S_RUN) {
/* Vdev is not started, start it */
ocb_debug("OCB vdev%d is not up", config->vdev_id);
status = ocb_vdev_start(ocb_obj);
} else {
psoc = wlan_vdev_get_psoc(vdev);
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (tx_ops && tx_ops->ocb_set_config)
status = tx_ops->ocb_set_config(psoc, config);
else
status = QDF_STATUS_E_IO;
ocb_debug("Set config to vdev%d", config->vdev_id);
if (QDF_IS_STATUS_SUCCESS(status))
ocb_debug("Set channel cmd is sent to southbound");
else
ocb_err("Failed to set channel config to southbound");
}
if (QDF_IS_STATUS_ERROR(status) && ocb_obj->channel_config) {
/*
* On success case, backup parameters will be released
* after channel info is synced to DP
*/
ocb_info("release the backed config parameters");
qdf_mem_free(ocb_obj->channel_config);
ocb_obj->channel_config = NULL;
}
return status;
}
QDF_STATUS ucfg_ocb_set_utc_time(struct wlan_objmgr_vdev *vdev,
struct ocb_utc_param *utc)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
struct wlan_ocb_tx_ops *tx_ops;
psoc = wlan_vdev_get_psoc(vdev);
pdev = wlan_vdev_get_pdev(vdev);
if (!psoc || !pdev) {
ocb_err("Null pointer for psoc/pdev");
return QDF_STATUS_E_INVAL;
}
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_set_utc_time) {
ocb_alert("ocb_set_utc_time is null");
return QDF_STATUS_E_IO;
}
status = tx_ops->ocb_set_utc_time(psoc, utc);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to set UTC time to southbound");
else
ocb_debug("UTC time is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_start_timing_advert(struct wlan_objmgr_vdev *vdev,
struct ocb_timing_advert_param *ta)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
struct wlan_ocb_tx_ops *tx_ops;
psoc = wlan_vdev_get_psoc(vdev);
pdev = wlan_vdev_get_pdev(vdev);
if (!psoc || !pdev) {
ocb_err("Null pointer for psoc/pdev");
return QDF_STATUS_E_INVAL;
}
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_start_timing_advert) {
ocb_alert("ocb_start_timing_advert is null");
return QDF_STATUS_E_IO;
}
status = tx_ops->ocb_start_timing_advert(psoc, ta);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to sent start timing advert to southbound");
else
ocb_debug("Start timing advert is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_stop_timing_advert(struct wlan_objmgr_vdev *vdev,
struct ocb_timing_advert_param *ta)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
struct wlan_ocb_tx_ops *tx_ops;
psoc = wlan_vdev_get_psoc(vdev);
pdev = wlan_vdev_get_pdev(vdev);
if (!psoc || !pdev) {
ocb_err("Null pointer for psoc/pdev");
return QDF_STATUS_E_INVAL;
}
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_stop_timing_advert) {
ocb_alert("ocb_stop_timing_advert is null");
return QDF_STATUS_E_IO;
}
status = tx_ops->ocb_stop_timing_advert(psoc, ta);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to sent start timing advert to southbound");
else
ocb_debug("Start timing advert is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_get_tsf_timer(struct wlan_objmgr_vdev *vdev,
struct ocb_get_tsf_timer_param *req,
ocb_sync_callback get_tsf_cb,
void *arg)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct ocb_get_tsf_timer_param request;
struct wlan_ocb_tx_ops *tx_ops;
struct ocb_callbacks *ocb_cbs;
struct wlan_objmgr_pdev *pdev;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_get_tsf_timer) {
ocb_alert("ocb_get_tsf_timer is null");
return QDF_STATUS_E_IO;
}
ocb_cbs = wlan_ocb_get_callbacks(pdev);
ocb_cbs->ocb_get_tsf_timer_context = arg;
ocb_cbs->ocb_get_tsf_timer_callback = get_tsf_cb;
request.vdev_id = req->vdev_id;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
ocb_err("Null pointer for psoc");
return QDF_STATUS_E_INVAL;
}
status = tx_ops->ocb_get_tsf_timer(psoc, &request);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to sent get tsf timer to southbound");
else
ocb_debug("Get tsf timer is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_dcc_get_stats(struct wlan_objmgr_vdev *vdev,
struct ocb_dcc_get_stats_param *request,
ocb_sync_callback dcc_get_stats_cb,
void *arg)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
struct ocb_callbacks *ocb_cbs;
struct wlan_ocb_tx_ops *tx_ops;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
ocb_cbs = wlan_ocb_get_callbacks(pdev);
ocb_cbs->ocb_dcc_get_stats_context = arg;
ocb_cbs->ocb_dcc_get_stats_callback = dcc_get_stats_cb;
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_dcc_get_stats) {
ocb_alert("ocb_dcc_get_stats is null");
return QDF_STATUS_E_IO;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
ocb_err("Null pointer for psoc");
return QDF_STATUS_E_INVAL;
}
status = tx_ops->ocb_dcc_get_stats(psoc, request);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to sent get dcc stats to southbound");
else
ocb_debug("Get dcc stats is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_dcc_clear_stats(struct wlan_objmgr_vdev *vdev,
uint16_t vdev_id,
uint32_t bitmap)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct wlan_objmgr_pdev *pdev;
struct wlan_ocb_tx_ops *tx_ops;
struct ocb_dcc_clear_stats_param clear_stats_param;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_dcc_clear_stats) {
ocb_alert("ocb_dcc_clear_stats is null");
return QDF_STATUS_E_IO;
}
clear_stats_param.vdev_id = vdev_id;
clear_stats_param.dcc_stats_bitmap = bitmap;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
ocb_err("Null pointer for psoc");
return QDF_STATUS_E_INVAL;
}
status = tx_ops->ocb_dcc_clear_stats(psoc, &clear_stats_param);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to sent clear dcc stats to southbound");
else
ocb_debug("clear dcc stats is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_dcc_update_ndl(struct wlan_objmgr_vdev *vdev,
struct ocb_dcc_update_ndl_param *request,
ocb_sync_callback dcc_update_ndl_cb,
void *arg)
{
QDF_STATUS status;
struct wlan_objmgr_psoc *psoc;
struct ocb_callbacks *ocb_cbs;
struct wlan_objmgr_pdev *pdev;
struct wlan_ocb_tx_ops *tx_ops;
pdev = wlan_vdev_get_pdev(vdev);
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
ocb_cbs = wlan_ocb_get_callbacks(pdev);
ocb_cbs->ocb_dcc_update_ndl_context = arg;
ocb_cbs->ocb_dcc_update_ndl_callback = dcc_update_ndl_cb;
tx_ops = wlan_ocb_get_tx_ops(pdev);
if (!tx_ops) {
ocb_alert("tx_ops is null");
return QDF_STATUS_E_IO;
}
if (!tx_ops->ocb_dcc_update_ndl) {
ocb_alert("dcc_update_ndl is null");
return QDF_STATUS_E_IO;
}
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc) {
ocb_err("Null pointer for psoc");
return QDF_STATUS_E_INVAL;
}
status = tx_ops->ocb_dcc_update_ndl(psoc, request);
if (QDF_IS_STATUS_ERROR(status))
ocb_err("Failed to sent update ndl to southbound");
else
ocb_debug("Update ndl is sent to southbound");
return status;
}
QDF_STATUS ucfg_ocb_register_for_dcc_stats_event(struct wlan_objmgr_pdev *pdev,
void *ctx, ocb_sync_callback dcc_stats_cb)
{
struct ocb_callbacks *ocb_cbs;
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
ocb_cbs = wlan_ocb_get_callbacks(pdev);
if (!ocb_cbs) {
ocb_err("Failed to register dcc stats callback");
return QDF_STATUS_E_FAILURE;
}
ocb_cbs->ocb_dcc_stats_event_context = ctx;
ocb_cbs->ocb_dcc_stats_event_callback = dcc_stats_cb;
return QDF_STATUS_SUCCESS;
}
QDF_STATUS ucfg_ocb_register_vdev_start(struct wlan_objmgr_pdev *pdev,
QDF_STATUS (*ocb_start)(struct ocb_config *))
{
struct ocb_callbacks *ocb_cbs;
if (!pdev) {
ocb_err("Null pointer for pdev");
return QDF_STATUS_E_INVAL;
}
ocb_cbs = wlan_ocb_get_callbacks(pdev);
if (!ocb_cbs) {
ocb_err("Failed to register dcc stats callback");
return QDF_STATUS_E_FAILURE;
}
ocb_cbs->start_ocb_vdev = ocb_start;
return QDF_STATUS_SUCCESS;
}