diff --git a/Kbuild b/Kbuild index 88c3b41aea31..77d88159455d 100644 --- a/Kbuild +++ b/Kbuild @@ -1018,11 +1018,22 @@ DISA_OBJS := $(DISA_DIR)/core/src/wlan_disa_main.o \ $(DISA_DIR)/dispatcher/src/wlan_disa_ucfg_api.o endif +######## OCB ############## +OCB_DIR := components/ocb +OCB_INC := -I$(WLAN_ROOT)/$(OCB_DIR)/core/inc \ + -I$(WLAN_ROOT)/$(OCB_DIR)/dispatcher/inc + +ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) +OCB_OBJS := $(OCB_DIR)/dispatcher/src/wlan_ocb_ucfg_api.o \ + $(OCB_DIR)/dispatcher/src/wlan_ocb_tgt_api.o \ + $(OCB_DIR)/core/src/wlan_ocb_main.o +endif + ########## CLD TARGET_IF ####### CLD_TARGET_IF_DIR := components/target_if CLD_TARGET_IF_INC := -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/pmo/inc \ - -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/pmo/src \ + -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/pmo/src CLD_TARGET_IF_OBJ := $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_arp.o \ $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_gtk.o \ @@ -1034,7 +1045,12 @@ CLD_TARGET_IF_OBJ := $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_arp.o \ $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_pkt_filter.o \ $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_static_config.o \ $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_suspend_resume.o \ - $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_wow.o \ + $(CLD_TARGET_IF_DIR)/pmo/src/target_if_pmo_wow.o + +ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) +CLD_TARGET_IF_INC += -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/ocb/inc +CLD_TARGET_IF_OBJ += $(CLD_TARGET_IF_DIR)/ocb/src/target_if_ocb.o +endif ifeq ($(CONFIG_WLAN_FEATURE_DISA), y) CLD_TARGET_IF_INC += -I$(WLAN_ROOT)/$(CLD_TARGET_IF_DIR)/disa/inc @@ -1137,6 +1153,12 @@ WMI_OBJS := $(WMI_OBJ_DIR)/wmi_unified.o \ $(WMI_OBJ_DIR)/wmi_unified_dfs_api.o \ $(WMI_OBJ_DIR)/wmi_unified_non_tlv.o +ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) +ifeq ($(CONFIG_OCB_UT_FRAMEWORK), y) +WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_ocb_ut.o +endif +endif + ########### FWLOG ########### FWLOG_DIR := $(WLAN_COMMON_ROOT)/utils/fwlog @@ -1603,6 +1625,7 @@ INCS += $(NLINK_INC) \ $(WLAN_LOGGING_INC) INCS += $(PLD_INC) +INCS += $(OCB_INC) ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) INCS += $(PKTLOG_INC) @@ -1672,6 +1695,10 @@ OBJS += $(PTT_OBJS) OBJS += $(UMAC_SER_OBJS) OBJS += $(PLD_OBJS) +ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) +OBJS += $(OCB_OBJS) +endif + ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) OBJS += $(PKTLOG_OBJS) endif @@ -2024,6 +2051,11 @@ endif ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y) CDEFINES += -DWLAN_FEATURE_DSRC + +ifeq ($(CONFIG_OCB_UT_FRAMEWORK), y) +CDEFINES += -DWLAN_OCB_UT +endif + endif ifeq ($(CONFIG_ARCH_SDX20), y) diff --git a/components/ocb/core/inc/wlan_ocb_main.h b/components/ocb/core/inc/wlan_ocb_main.h new file mode 100644 index 000000000000..af15191fa833 --- /dev/null +++ b/components/ocb/core/inc/wlan_ocb_main.h @@ -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 +#include +#include +#include +#include + +#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 diff --git a/components/ocb/dispatcher/inc/wlan_ocb_public_structs.h b/components/ocb/dispatcher/inc/wlan_ocb_public_structs.h new file mode 100644 index 000000000000..b23fe512001a --- /dev/null +++ b/components/ocb/dispatcher/inc/wlan_ocb_public_structs.h @@ -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 + +/* 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 diff --git a/components/ocb/dispatcher/inc/wlan_ocb_ucfg_api.h b/components/ocb/dispatcher/inc/wlan_ocb_ucfg_api.h new file mode 100644 index 000000000000..de90f5b2a29d --- /dev/null +++ b/components/ocb/dispatcher/inc/wlan_ocb_ucfg_api.h @@ -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 +#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 diff --git a/components/ocb/dispatcher/src/wlan_ocb_ucfg_api.c b/components/ocb/dispatcher/src/wlan_ocb_ucfg_api.c new file mode 100644 index 000000000000..de87d31e6b3f --- /dev/null +++ b/components/ocb/dispatcher/src/wlan_ocb_ucfg_api.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index ab5118506c5b..664531827641 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -68,6 +68,7 @@ #include #include "qdf_cpuhp.h" #include "target_type.h" +#include "wlan_ocb_ucfg_api.h" /* Preprocessor Definitions and Constants */ @@ -633,6 +634,7 @@ QDF_STATUS cds_open(struct wlan_objmgr_psoc *psoc) } pmo_ucfg_psoc_update_dp_handle(psoc, gp_cds_context->dp_soc); + ucfg_ocb_update_dp_handle(psoc, gp_cds_context->dp_soc); cds_set_ac_specs_params(cds_cfg); @@ -730,6 +732,7 @@ QDF_STATUS cds_dp_open(struct wlan_objmgr_psoc *psoc) } pmo_ucfg_psoc_set_txrx_handle(psoc, gp_cds_context->pdev_txrx_ctx); + ucfg_ocb_set_txrx_handle(psoc, gp_cds_context->pdev_txrx_ctx); QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, "%s: CDS successfully Opened", __func__); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 6692713578e6..edc42b197d07 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -135,6 +135,7 @@ #include #endif #include "wlan_reg_ucfg_api.h" +#include "wlan_ocb_ucfg_api.h" #include @@ -275,6 +276,7 @@ static const struct category_info cinfo[MAX_SUPPORTED_CATEGORY] = { [QDF_MODULE_ID_OBJ_MGR] = {QDF_TRACE_LEVEL_ALL}, [QDF_MODULE_ID_ROAM_DEBUG] = {QDF_TRACE_LEVEL_ALL}, [QDF_MODULE_ID_GREEN_AP] = {QDF_TRACE_LEVEL_ALL}, + [QDF_MODULE_ID_OCB] = {QDF_TRACE_LEVEL_ALL}, }; int limit_off_chan_tbl[HDD_MAX_AC][HDD_MAX_OFF_CHAN_ENTRIES] = { @@ -11695,6 +11697,7 @@ static void component_init(void) { pmo_init(); disa_init(); + ucfg_ocb_init(); } /** @@ -11704,18 +11707,21 @@ static void component_init(void) */ static void component_deinit(void) { + ucfg_ocb_deinit(); pmo_deinit(); disa_deinit(); } void hdd_component_psoc_enable(struct wlan_objmgr_psoc *psoc) { + ocb_psoc_enable(psoc); disa_psoc_enable(psoc); } void hdd_component_psoc_disable(struct wlan_objmgr_psoc *psoc) { disa_psoc_disable(psoc); + ocb_psoc_disable(psoc); } /** diff --git a/core/hdd/src/wlan_hdd_ocb.c b/core/hdd/src/wlan_hdd_ocb.c index f11292e7a977..4e71c4759036 100644 --- a/core/hdd/src/wlan_hdd_ocb.c +++ b/core/hdd/src/wlan_hdd_ocb.c @@ -43,6 +43,13 @@ #include #include #include +#include "wlan_ocb_public_structs.h" +#include "wlan_ocb_ucfg_api.h" +#include +#include +#include +#include + /* Structure definitions for WLAN_SET_DOT11P_CHANNEL_SCHED */ #define AIFSN_MIN (2) #define AIFSN_MAX (15) @@ -73,7 +80,7 @@ void hdd_set_dot11p_config(struct hdd_context *hdd_ctx) * * Return: 0 on success. error code on failure. */ -static int dot11p_validate_qos_params(struct sir_qos_params qos_params[]) +static int dot11p_validate_qos_params(struct ocb_wmm_param qos_params[]) { int i; @@ -196,7 +203,7 @@ static int dot11p_validate_channel(struct wiphy *wiphy, * Return: 0 on success. */ static int hdd_ocb_validate_config(struct hdd_adapter *adapter, - struct sir_ocb_config *config) + struct ocb_config *config) { int i; struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); @@ -291,12 +298,12 @@ static int hdd_ocb_register_sta(struct hdd_adapter *adapter) * Return: A pointer to the OCB configuration struct, NULL on failure. */ static -struct sir_ocb_config *hdd_ocb_config_new(uint32_t num_channels, - uint32_t num_schedule, - uint32_t ndl_chan_list_len, - uint32_t ndl_active_state_list_len) +struct ocb_config *hdd_ocb_config_new(uint32_t num_channels, + uint32_t num_schedule, + uint32_t ndl_chan_list_len, + uint32_t ndl_active_state_list_len) { - struct sir_ocb_config *ret = 0; + struct ocb_config *ret = 0; uint32_t len; void *cursor; @@ -305,8 +312,8 @@ struct sir_ocb_config *hdd_ocb_config_new(uint32_t num_channels, return NULL; len = sizeof(*ret) + - num_channels * sizeof(struct sir_ocb_config_channel) + - num_schedule * sizeof(struct sir_ocb_config_sched) + + num_channels * sizeof(struct ocb_config_chan) + + num_schedule * sizeof(struct ocb_config_schdl) + ndl_chan_list_len + ndl_active_state_list_len; @@ -355,7 +362,7 @@ static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr) { struct hdd_request *hdd_request; struct hdd_ocb_set_config_priv *priv; - struct sir_ocb_set_config_response *response = response_ptr; + struct ocb_set_config_response *response = response_ptr; hdd_request = hdd_request_get(context_ptr); if (!hdd_request) { @@ -367,7 +374,7 @@ static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr) if (response && response->status) hdd_warn("Operation failed: %d", response->status); - if (response && (0 == response->status)) + if (response && (response->status == OCB_CHANNEL_CONFIG_SUCCESS)) priv->status = 0; else priv->status = -EINVAL; @@ -384,11 +391,10 @@ static void hdd_ocb_set_config_callback(void *context_ptr, void *response_ptr) * Return: 0 on success. */ static int hdd_ocb_set_config_req(struct hdd_adapter *adapter, - struct sir_ocb_config *config) + struct ocb_config *config) { int rc; QDF_STATUS status; - struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter); void *cookie; struct hdd_request *hdd_request; struct hdd_ocb_set_config_priv *priv; @@ -414,11 +420,11 @@ static int hdd_ocb_set_config_req(struct hdd_adapter *adapter, WLAN_STOP_ALL_NETIF_QUEUE_N_CARRIER, WLAN_CONTROL_PATH); - /* Call the SME API to set the config */ - status = sme_ocb_set_config(hdd_ctx->hHal, cookie, - hdd_ocb_set_config_callback, config); + status = ucfg_ocb_set_channel_config(adapter->hdd_vdev, config, + hdd_ocb_set_config_callback, + cookie); if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Error calling SME function."); + hdd_err("Failed to set channel config."); rc = qdf_status_to_os_return(status); goto end; } @@ -471,10 +477,10 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, struct dot11p_channel_sched *sched; struct hdd_context *hdd_ctx; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); - struct sir_ocb_config *config = NULL; + struct ocb_config *config = NULL; uint8_t *mac_addr; int i, j; - struct sir_ocb_config_channel *curr_chan; + struct ocb_config_chan *curr_chan; ENTER_DEV(dev); @@ -503,7 +509,7 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, } /* Identify the vdev interface */ - config->session_id = adapter->session_id; + config->vdev_id = adapter->session_id; /* Release all the mac addresses used for OCB */ for (i = 0; i < adapter->ocb_mac_addr_count; i++) { @@ -522,7 +528,7 @@ static int __iw_set_dot11p_channel_sched(struct net_device *dev, curr_chan->chan_freq = sched->channels[i].channel_freq; /* * tx_power is divided by 2 because ocb_channel.tx_power is - * in half dB increments and sir_ocb_config_channel.max_pwr + * in half dB increments and ocb_config_channel.max_pwr * is in 1 dB increments. */ curr_chan->max_pwr = sched->channels[i].tx_power / 2; @@ -731,8 +737,8 @@ struct wlan_hdd_ocb_config_channel { uint32_t min_pwr; }; -static void wlan_hdd_ocb_config_channel_to_sir_ocb_config_channel( - struct sir_ocb_config_channel *dest, +static void wlan_hdd_ocb_config_channel_to_ocb_config_channel( + struct ocb_config_chan *dest, struct wlan_hdd_ocb_config_channel *src, uint32_t channel_count) { @@ -747,9 +753,9 @@ static void wlan_hdd_ocb_config_channel_to_sir_ocb_config_channel( sizeof(dest[i].qos_params)); /* * max_pwr and min_pwr are divided by 2 because - * wlan_hdd_ocb_config_channel.max_pwr and min_pwr + * ocb_channel_param.max_pwr and min_pwr * are in 1/2 dB increments and - * sir_ocb_config_channel.max_pwr and min_pwr are in + * ocb_config_channel.max_pwr and min_pwr are in * 1 dB increments. */ dest[i].max_pwr = src[i].max_pwr / 2; @@ -785,7 +791,7 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, uint32_t flags = 0; int i; uint32_t channel_count, schedule_size; - struct sir_ocb_config *config; + struct ocb_config *config; int rc = -EINVAL; uint8_t *mac_addr; @@ -869,11 +875,11 @@ static int __wlan_hdd_cfg80211_ocb_set_config(struct wiphy *wiphy, hdd_err("CHANNEL_ARRAY is not the correct size"); goto fail; } - wlan_hdd_ocb_config_channel_to_sir_ocb_config_channel( + wlan_hdd_ocb_config_channel_to_ocb_config_channel( config->channels, nla_data(channel_array), channel_count); /* Identify the vdev interface */ - config->session_id = adapter->session_id; + config->vdev_id = adapter->session_id; /* Release all the mac addresses used for OCB */ for (i = 0; i < adapter->ocb_mac_addr_count; i++) { @@ -987,7 +993,7 @@ static int __wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy *wiphy, struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_SET_UTC_TIME_MAX + 1]; struct nlattr *utc_attr; struct nlattr *time_error_attr; - struct sir_ocb_utc *utc; + struct ocb_utc_param *utc; int rc = -EINVAL; ENTER_DEV(dev); @@ -1046,7 +1052,8 @@ static int __wlan_hdd_cfg80211_ocb_set_utc_time(struct wiphy *wiphy, qdf_mem_copy(utc->time_error, nla_data(time_error_attr), SIZE_UTC_TIME_ERROR); - if (sme_ocb_set_utc_time(hdd_ctx->hHal, utc) != QDF_STATUS_SUCCESS) { + if (ucfg_ocb_set_utc_time(adapter->hdd_vdev, utc) != + QDF_STATUS_SUCCESS) { hdd_err("Error while setting UTC time"); rc = -EINVAL; } else { @@ -1099,7 +1106,7 @@ __wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy, struct net_device *dev = wdev->netdev; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_START_TIMING_ADVERT_MAX + 1]; - struct sir_ocb_timing_advert *timing_advert; + struct ocb_timing_advert_param *timing_advert; int rc = -EINVAL; ENTER_DEV(dev); @@ -1158,7 +1165,7 @@ __wlan_hdd_cfg80211_ocb_start_timing_advert(struct wiphy *wiphy, goto fail; } - if (sme_ocb_start_timing_advert(hdd_ctx->hHal, timing_advert) != + if (ucfg_ocb_start_timing_advert(adapter->hdd_vdev, timing_advert) != QDF_STATUS_SUCCESS) { hdd_err("Error while starting timing advert"); rc = -EINVAL; @@ -1216,7 +1223,7 @@ __wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, struct net_device *dev = wdev->netdev; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_MAX + 1]; - struct sir_ocb_timing_advert *timing_advert; + struct ocb_timing_advert_param *timing_advert; int rc = -EINVAL; ENTER_DEV(dev); @@ -1257,7 +1264,7 @@ __wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, timing_advert->chan_freq = nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_OCB_STOP_TIMING_ADVERT_CHANNEL_FREQ]); - if (sme_ocb_stop_timing_advert(hdd_ctx->hHal, timing_advert) != + if (ucfg_ocb_stop_timing_advert(adapter->hdd_vdev, timing_advert) != QDF_STATUS_SUCCESS) { hdd_err("Error while stopping timing advert"); rc = -EINVAL; @@ -1295,7 +1302,7 @@ int wlan_hdd_cfg80211_ocb_stop_timing_advert(struct wiphy *wiphy, } struct hdd_ocb_get_tsf_timer_priv { - struct sir_ocb_get_tsf_timer_response response; + struct ocb_get_tsf_timer_response response; int status; }; @@ -1309,7 +1316,7 @@ static void hdd_ocb_get_tsf_timer_callback(void *context_ptr, { struct hdd_request *hdd_request; struct hdd_ocb_get_tsf_timer_priv *priv; - struct sir_ocb_get_tsf_timer_response *response = response_ptr; + struct ocb_get_tsf_timer_response *response = response_ptr; hdd_request = hdd_request_get(context_ptr); if (!hdd_request) { @@ -1317,6 +1324,7 @@ static void hdd_ocb_get_tsf_timer_callback(void *context_ptr, return; } + priv = hdd_request_priv(hdd_request); if (response) { priv->response = *response; priv->status = 0; @@ -1329,7 +1337,7 @@ static void hdd_ocb_get_tsf_timer_callback(void *context_ptr, static int hdd_ocb_get_tsf_timer_reply(struct wiphy *wiphy, - struct sir_ocb_get_tsf_timer_response *response) + struct ocb_get_tsf_timer_response *response) { uint32_t nl_buf_len; struct sk_buff *nl_resp; @@ -1389,7 +1397,7 @@ __wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, struct net_device *dev = wdev->netdev; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); int rc; - struct sir_ocb_get_tsf_timer request = {0}; + struct ocb_get_tsf_timer_param request = {0}; QDF_STATUS status; void *cookie; struct hdd_request *hdd_request; @@ -1423,12 +1431,11 @@ __wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, cookie = hdd_request_cookie(hdd_request); request.vdev_id = adapter->session_id; - /* Call the SME function */ - status = sme_ocb_get_tsf_timer(hdd_ctx->hHal, cookie, - hdd_ocb_get_tsf_timer_callback, - &request); + status = ucfg_ocb_get_tsf_timer(adapter->hdd_vdev, &request, + hdd_ocb_get_tsf_timer_callback, + cookie); if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Error calling SME function."); + hdd_err("Failed to get tsf timer."); rc = qdf_status_to_os_return(status); goto end; } @@ -1489,7 +1496,7 @@ int wlan_hdd_cfg80211_ocb_get_tsf_timer(struct wiphy *wiphy, } struct hdd_dcc_stats_priv { - struct sir_dcc_get_stats_response *response; + struct ocb_dcc_get_stats_response *response; int status; }; @@ -1510,8 +1517,8 @@ static void hdd_dcc_get_stats_callback(void *context_ptr, void *response_ptr) { struct hdd_request *hdd_request; struct hdd_dcc_stats_priv *priv; - struct sir_dcc_get_stats_response *response = response_ptr; - struct sir_dcc_get_stats_response *hdd_resp; + struct ocb_dcc_get_stats_response *response = response_ptr; + struct ocb_dcc_get_stats_response *hdd_resp; hdd_request = hdd_request_get(context_ptr); if (!hdd_request) { @@ -1547,7 +1554,7 @@ end: static int hdd_dcc_get_stats_send_reply(struct wiphy *wiphy, - struct sir_dcc_get_stats_response *response) + struct ocb_dcc_get_stats_response *response) { uint32_t nl_buf_len; struct sk_buff *nl_resp; @@ -1612,7 +1619,7 @@ static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_GET_STATS_MAX + 1]; int rc; - struct sir_dcc_get_stats request = {0}; + struct ocb_dcc_get_stats_param request = {0}; QDF_STATUS status; void *cookie; struct hdd_request *hdd_request; @@ -1673,12 +1680,11 @@ static int __wlan_hdd_cfg80211_dcc_get_stats(struct wiphy *wiphy, request.request_array_len = request_array_len; request.request_array = request_array; - /* Call the SME function. */ - status = sme_dcc_get_stats(hdd_ctx->hHal, cookie, - hdd_dcc_get_stats_callback, - &request); + status = ucfg_ocb_dcc_get_stats(adapter->hdd_vdev, &request, + hdd_dcc_get_stats_callback, + cookie); if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Error calling SME function."); + hdd_err("Failed to get DCC stats."); rc = qdf_status_to_os_return(status); goto end; } @@ -1784,12 +1790,11 @@ static int __wlan_hdd_cfg80211_dcc_clear_stats(struct wiphy *wiphy, return -EINVAL; } - /* Call the SME function */ - if (sme_dcc_clear_stats(hdd_ctx->hHal, adapter->session_id, + if (ucfg_ocb_dcc_clear_stats(adapter->hdd_vdev, adapter->session_id, nla_get_u32( tb[QCA_WLAN_VENDOR_ATTR_DCC_CLEAR_STATS_BITMAP])) != QDF_STATUS_SUCCESS) { - hdd_err("Error calling SME function."); + hdd_err("Failed to clear DCC stats."); return -EINVAL; } @@ -1833,7 +1838,7 @@ static void hdd_dcc_update_ndl_callback(void *context_ptr, void *response_ptr) { struct hdd_request *hdd_request; struct hdd_dcc_update_ndl_priv *priv; - struct sir_dcc_update_ndl_response *response = response_ptr; + struct ocb_dcc_update_ndl_response *response = response_ptr; hdd_request = hdd_request_get(context_ptr); if (!hdd_request) { @@ -1868,7 +1873,7 @@ static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, struct net_device *dev = wdev->netdev; struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev); struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_DCC_UPDATE_NDL_MAX + 1]; - struct sir_dcc_update_ndl request; + struct ocb_dcc_update_ndl_param request; uint32_t channel_count; uint32_t ndl_channel_array_len; void *ndl_channel_array; @@ -1942,12 +1947,11 @@ static int __wlan_hdd_cfg80211_dcc_update_ndl(struct wiphy *wiphy, request.dcc_ndl_active_state_list_len = ndl_active_state_array_len; request.dcc_ndl_active_state_list = ndl_active_state_array; - /* Call the SME function */ - status = sme_dcc_update_ndl(hdd_ctx->hHal, cookie, - hdd_dcc_update_ndl_callback, - &request); + status = ucfg_ocb_dcc_update_ndl(adapter->hdd_vdev, &request, + hdd_dcc_update_ndl_callback, + cookie); if (QDF_IS_STATUS_ERROR(status)) { - hdd_err("Error calling SME function."); + hdd_err("Failed to update NDL."); rc = qdf_status_to_os_return(status); goto end; } @@ -2006,7 +2010,7 @@ static void wlan_hdd_dcc_stats_event_callback(void *context_ptr, void *response_ptr) { struct hdd_context *hdd_ctx = (struct hdd_context *)context_ptr; - struct sir_dcc_get_stats_response *resp = response_ptr; + struct ocb_dcc_get_stats_response *resp = response_ptr; struct sk_buff *vendor_event; ENTER(); @@ -2046,8 +2050,8 @@ void wlan_hdd_dcc_register_for_dcc_stats_event(struct hdd_context *hdd_ctx) { int rc; - rc = sme_register_for_dcc_stats_event(hdd_ctx->hHal, hdd_ctx, + rc = ucfg_ocb_register_for_dcc_stats_event(hdd_ctx->hdd_pdev, hdd_ctx, wlan_hdd_dcc_stats_event_callback); if (rc) - hdd_err("Register callback failed: %d", rc); + hdd_err("Register DCC stats callback failed: %d", rc); } diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 0c533c345e12..08121ab5e61e 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -80,6 +80,7 @@ #include "wma_he.h" #include "wlan_roam_debug.h" +#include "wlan_ocb_ucfg_api.h" /** * wma_find_vdev_by_addr() - find vdev_id from mac address @@ -1183,7 +1184,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, } wma_vdev_set_mlme_state(wma, resp_event->vdev_id, WLAN_VDEV_S_RUN); - wma_ocb_start_resp_ind_cont(wma); + ucfg_ocb_config_channel(wma->pdev); } if ((wma->interfaces[resp_event->vdev_id].type == WMI_VDEV_TYPE_AP) && diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 3e674cc20a19..ef4bf056bc53 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -3927,9 +3927,9 @@ QDF_STATUS wma_start(void) goto end; } - status = wma_ocb_register_event_handlers(wma_handle); - if (status) { - WMA_LOGE("Failed to register ocb event handlers"); + status = wma_ocb_register_callbacks(wma_handle); + if (!QDF_IS_STATUS_SUCCESS(status)) { + WMA_LOGE("Failed to register OCB callbacks"); qdf_status = QDF_STATUS_E_FAILURE; goto end; } diff --git a/core/wma/src/wma_ocb.c b/core/wma/src/wma_ocb.c index 5c49db6fdbe7..16351c11d51c 100644 --- a/core/wma/src/wma_ocb.c +++ b/core/wma/src/wma_ocb.c @@ -34,8 +34,10 @@ #include "wma_ocb.h" #include "wmi_unified_api.h" #include "cds_utils.h" +#include "cds_api.h" #include #include +#include "wlan_ocb_ucfg_api.h" /** * wma_ocb_resp() - send the OCB set config response via callback @@ -244,14 +246,14 @@ int wma_ocb_set_config(tp_wma_handle wma_handle, struct sir_ocb_config *config) { int32_t ret, i; uint32_t *ch_mhz; - struct ocb_config_param tconfig = {0}; + struct ocb_config tconfig = {0}; - tconfig.session_id = config->session_id; + tconfig.vdev_id = config->session_id; tconfig.channel_count = config->channel_count; tconfig.schedule_size = config->schedule_size; tconfig.flags = config->flags; - tconfig.channels = (struct ocb_config_channel *)config->channels; - tconfig.schedule = (struct ocb_config_sched *)config->schedule; + tconfig.channels = (struct ocb_config_chan *)config->channels; + tconfig.schedule = (struct ocb_config_schdl *)config->schedule; tconfig.dcc_ndl_chan_list_len = config->dcc_ndl_chan_list_len; tconfig.dcc_ndl_chan_list = config->dcc_ndl_chan_list; tconfig.dcc_ndl_active_state_list_len = @@ -276,8 +278,7 @@ int wma_ocb_set_config(tp_wma_handle wma_handle, struct sir_ocb_config *config) wma_handle->ocb_config_req = copy_sir_ocb_config(config); } - ret = wmi_unified_ocb_set_config(wma_handle->wmi_handle, &tconfig, - ch_mhz); + ret = wmi_unified_ocb_set_config(wma_handle->wmi_handle, &tconfig); if (ret != EOK) { if (wma_handle->ocb_config_req) { qdf_mem_free(wma_handle->ocb_config_req); @@ -409,7 +410,7 @@ int wma_ocb_get_tsf_timer(tp_wma_handle wma_handle, /* Send the WMI command */ ret = wmi_unified_ocb_get_tsf_timer(wma_handle->wmi_handle, - request->vdev_id); + (struct ocb_get_tsf_timer_param *)request); /* If there is an error, set the completion event */ if (ret != EOK) { WMA_LOGE(FL("Failed to send WMI message: %d"), ret); @@ -471,7 +472,7 @@ int wma_dcc_get_stats(tp_wma_handle wma_handle, struct sir_dcc_get_stats *get_stats_param) { int32_t ret; - struct dcc_get_stats_param cmd = {0}; + struct ocb_dcc_get_stats_param cmd = {0}; cmd.vdev_id = get_stats_param->vdev_id; cmd.channel_count = get_stats_param->channel_count; @@ -560,8 +561,7 @@ int wma_dcc_clear_stats(tp_wma_handle wma_handle, /* Send the WMI command */ ret = wmi_unified_dcc_clear_stats(wma_handle->wmi_handle, - clear_stats_param->vdev_id, - clear_stats_param->dcc_stats_bitmap); + (struct ocb_dcc_clear_stats_param *)clear_stats_param); if (ret != EOK) { WMA_LOGE(FL("Failed to send the WMI command")); return -EIO; @@ -581,9 +581,9 @@ int wma_dcc_update_ndl(tp_wma_handle wma_handle, struct sir_dcc_update_ndl *update_ndl_param) { QDF_STATUS qdf_status; - struct dcc_update_ndl_param *cmd; + struct ocb_dcc_update_ndl_param *cmd; - cmd = (struct dcc_update_ndl_param *) update_ndl_param; + cmd = (struct ocb_dcc_update_ndl_param *) update_ndl_param; /* Send the WMI command */ qdf_status = wmi_unified_dcc_update_ndl(wma_handle->wmi_handle, cmd); @@ -757,3 +757,53 @@ int wma_ocb_register_event_handlers(tp_wma_handle wma_handle) return QDF_STATUS_SUCCESS; } + +/** + * wma_start_ocb_vdev() - start OCB vdev + * @config: ocb channel config + * + * Return: QDF_STATUS_SUCCESS on success + */ +static QDF_STATUS wma_start_ocb_vdev(struct ocb_config *config) +{ + struct wma_target_req *msg; + struct wma_vdev_start_req req; + QDF_STATUS status; + tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); + + qdf_mem_zero(&req, sizeof(req)); + msg = wma_fill_vdev_req(wma, config->vdev_id, + WMA_OCB_SET_CONFIG_CMD, + WMA_TARGET_REQ_TYPE_VDEV_START, + (void *)config, 1000); + if (!msg) { + WMA_LOGE(FL("Failed to fill vdev req %d"), config->vdev_id); + + return QDF_STATUS_E_NOMEM; + } + req.chan = cds_freq_to_chan(config->channels[0].chan_freq); + req.vdev_id = msg->vdev_id; + if (cds_chan_to_band(req.chan) == CDS_BAND_2GHZ) + req.dot11_mode = WNI_CFG_DOT11_MODE_11G; + else + req.dot11_mode = WNI_CFG_DOT11_MODE_11A; + + req.preferred_rx_streams = 2; + req.preferred_tx_streams = 2; + + status = wma_vdev_start(wma, &req, false); + if (status != QDF_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, req.vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + WMA_LOGE(FL("vdev_start failed, status = %d"), status); + } + + return status; +} + +QDF_STATUS wma_ocb_register_callbacks(tp_wma_handle wma_handle) +{ + ucfg_ocb_register_vdev_start(wma_handle->pdev, wma_start_ocb_vdev); + + return QDF_STATUS_SUCCESS; +} diff --git a/core/wma/src/wma_ocb.h b/core/wma/src/wma_ocb.h index 897efa005dda..031b6aef6881 100644 --- a/core/wma/src/wma_ocb.h +++ b/core/wma/src/wma_ocb.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -65,6 +65,14 @@ int wma_dcc_update_ndl(tp_wma_handle wma_handle, struct sir_dcc_update_ndl *update_ndl_param); int wma_ocb_register_event_handlers(tp_wma_handle wma_handle); + +/** + * wma_ocb_register_callbacks() - register WMA layer callback for OCB + * @wma_handle: wma handle + * + * Return: QDF_STATUS_SUCCESS on success + */ +QDF_STATUS wma_ocb_register_callbacks(tp_wma_handle wma_handle); #else static inline int wma_ocb_set_config_resp(tp_wma_handle wma_handle, uint8_t status) @@ -141,5 +149,16 @@ static inline int wma_ocb_register_event_handlers(tp_wma_handle wma_handle) { return 0; } + +/** + * wma_ocb_register_callbacks() - register WMA layer callback for OCB + * @wma_handle: wma handle + * + * Return: QDF_STATUS_SUCCESS on success + */ +static inline QDF_STATUS wma_ocb_register_callbacks(tp_wma_handle wma_handle) +{ + return QDF_STATUS_SUCCESS; +} #endif #endif /* __WMA_OCB_H */