qcacld-3.0: Add interface to get / set eLNA bypass
Add interface to get / set eLNA bypass from / to firmware
Change-Id: Idf5d6a838d2596767a1fb00040457af721fba69d
CRs-Fixed: 2498525
diff --git a/Kbuild b/Kbuild
index 8755980..d9bcd08 100644
--- a/Kbuild
+++ b/Kbuild
@@ -929,12 +929,25 @@
endif
######## FWOL ##########
-FWOL_DIR := components/fw_offload
-FWOL_INC := -I$(WLAN_ROOT)/$(FWOL_DIR)/core/inc \
- -I$(WLAN_ROOT)/$(FWOL_DIR)/dispatcher/inc
+FWOL_CORE_INC := components/fw_offload/core/inc
+FWOL_CORE_SRC := components/fw_offload/core/src
+FWOL_DISPATCHER_INC := components/fw_offload/dispatcher/inc
+FWOL_DISPATCHER_SRC := components/fw_offload/dispatcher/src
+FWOL_TARGET_IF_INC := components/target_if/fw_offload/inc
+FWOL_TARGET_IF_SRC := components/target_if/fw_offload/src
+FWOL_OS_IF_INC := os_if/fw_offload/inc
+FWOL_OS_IF_SRC := os_if/fw_offload/src
-FWOL_OBJS := $(FWOL_DIR)/core/src/wlan_fw_offload_main.o \
- $(FWOL_DIR)/dispatcher/src/wlan_fwol_ucfg_api.o
+FWOL_INC := -I$(WLAN_ROOT)/$(FWOL_CORE_INC) \
+ -I$(WLAN_ROOT)/$(FWOL_DISPATCHER_INC) \
+ -I$(WLAN_ROOT)/$(FWOL_TARGET_IF_INC) \
+ -I$(WLAN_ROOT)/$(FWOL_OS_IF_INC)
+
+FWOL_OBJS := $(FWOL_CORE_SRC)/wlan_fw_offload_main.o \
+ $(FWOL_DISPATCHER_SRC)/wlan_fwol_ucfg_api.o \
+ $(FWOL_DISPATCHER_SRC)/wlan_fwol_tgt_api.o \
+ $(FWOL_TARGET_IF_SRC)/target_if_fwol.o \
+ $(FWOL_OS_IF_SRC)/os_if_fwol.o
######## SM FRAMEWORK ##############
UMAC_SM_DIR := umac/cmn_services/sm_engine
@@ -1244,6 +1257,11 @@
WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_bcn_tlv.o
endif
+ifeq ($(CONFIG_WLAN_FW_OFFLOAD), y)
+WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_fwol_api.o
+WMI_OBJS += $(WMI_OBJ_DIR)/wmi_unified_fwol_tlv.o
+endif
+
########### FWLOG ###########
FWLOG_DIR := $(WLAN_COMMON_ROOT)/utils/fwlog
@@ -1980,7 +1998,9 @@
OBJS += $(UMAC_SM_OBJS)
OBJS += $(UMAC_MLME_OBJS)
OBJS += $(MLME_OBJS)
+ifeq ($(CONFIG_WLAN_FW_OFFLOAD), y)
OBJS += $(FWOL_OBJS)
+endif
OBJS += $(BLM_OBJS)
ifeq ($(CONFIG_WLAN_FEATURE_DSRC), y)
@@ -2080,6 +2100,8 @@
cppflags-$(CONFIG_FEATURE_FW_LOG_PARSING) += -DFEATURE_FW_LOG_PARSING
cppflags-$(CONFIG_FEATURE_OEM_DATA) += -DFEATURE_OEM_DATA
cppflags-$(CONFIG_FEATURE_MOTION_DETECTION) += -DWLAN_FEATURE_MOTION_DETECTION
+cppflags-$(CONFIG_WLAN_FW_OFFLOAD) += -DWLAN_FW_OFFLOAD
+cppflags-$(CONFIG_WLAN_FEATURE_ELNA) += -DWLAN_FEATURE_ELNA
cppflags-$(CONFIG_PLD_SDIO_CNSS_FLAG) += -DCONFIG_PLD_SDIO_CNSS
cppflags-$(CONFIG_PLD_PCIE_CNSS_FLAG) += -DCONFIG_PLD_PCIE_CNSS
diff --git a/components/fw_offload/core/inc/wlan_fw_offload_main.h b/components/fw_offload/core/inc/wlan_fw_offload_main.h
index 365b53d..0386ba8 100644
--- a/components/fw_offload/core/inc/wlan_fw_offload_main.h
+++ b/components/fw_offload/core/inc/wlan_fw_offload_main.h
@@ -26,8 +26,10 @@
#include <wlan_objmgr_psoc_obj.h>
#include <wlan_objmgr_global_obj.h>
#include <wlan_cmn.h>
+#include <scheduler_api.h>
#include "cfg_ucfg_api.h"
+#include "wlan_fwol_public_structs.h"
#define fwol_alert(params...) QDF_TRACE_FATAL(QDF_MODULE_ID_FWOL, params)
#define fwol_err(params...) QDF_TRACE_ERROR(QDF_MODULE_ID_FWOL, params)
@@ -47,6 +49,17 @@
QDF_TRACE_DEBUG_NO_FL(QDF_MODULE_ID_FWOL, params)
/**
+ * enum wlan_fwol_southbound_event - fw offload south bound event type
+ * @WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE: get eLNA bypass response
+ */
+enum wlan_fwol_southbound_event {
+ WLAN_FWOL_EVT_INVALID = 0,
+ WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE,
+ WLAN_FWOL_EVT_LAST,
+ WLAN_FWOL_EVT_MAX = WLAN_FWOL_EVT_LAST - 1
+};
+
+/**
* struct wlan_fwol_three_antenna_btc - Three antenna BTC config items
* @btc_mode: Config BTC mode
* @antenna_isolation: Antenna isolation
@@ -244,9 +257,31 @@
/**
* struct wlan_fwol_psoc_obj - FW offload psoc priv object
* @cfg: cfg items
+ * @cbs: callback functions
+ * @tx_ops: tx operations for target interface
+ * @rx_ops: rx operations for target interface
*/
struct wlan_fwol_psoc_obj {
struct wlan_fwol_cfg cfg;
+ struct wlan_fwol_callbacks cbs;
+ struct wlan_fwol_tx_ops tx_ops;
+ struct wlan_fwol_rx_ops rx_ops;
+};
+
+/**
+ * struct wlan_fwol_rx_event - event from south bound
+ * @psoc: psoc handle
+ * @event_id: event ID
+ * @get_elna_bypass_response: get eLNA bypass response
+ */
+struct wlan_fwol_rx_event {
+ struct wlan_objmgr_psoc *psoc;
+ enum wlan_fwol_southbound_event event_id;
+ union {
+#ifdef WLAN_FEATURE_ELNA
+ struct get_elna_bypass_response get_elna_bypass_response;
+#endif
+ };
};
/**
@@ -277,6 +312,22 @@
*/
QDF_STATUS fwol_cfg_on_psoc_disable(struct wlan_objmgr_psoc *psoc);
+/**
+ * fwol_process_event() - API to process event from south bound
+ * @msg: south bound message
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS fwol_process_event(struct scheduler_msg *msg);
+
+/*
+ * fwol_release_rx_event() - Release fw offload RX event
+ * @event: fw offload RX event
+ *
+ * Return: none
+ */
+void fwol_release_rx_event(struct wlan_fwol_rx_event *event);
+
/*
* fwol_init_neighbor_report_cfg() - Populate default neighbor report CFG values
* @psoc: pointer to the psoc object
diff --git a/components/fw_offload/core/src/wlan_fw_offload_main.c b/components/fw_offload/core/src/wlan_fw_offload_main.c
index 1e1f79c..16fcd33 100644
--- a/components/fw_offload/core/src/wlan_fw_offload_main.c
+++ b/components/fw_offload/core/src/wlan_fw_offload_main.c
@@ -543,3 +543,97 @@
/* Clear the CFG structure */
return QDF_STATUS_SUCCESS;
}
+
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * fwol_process_get_elna_bypass_resp() - Process get eLNA bypass response
+ * @event: response event
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+fwol_process_get_elna_bypass_resp(struct wlan_fwol_rx_event *event)
+{
+ QDF_STATUS status = QDF_STATUS_SUCCESS;
+ struct wlan_objmgr_psoc *psoc;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_callbacks *cbs;
+ struct get_elna_bypass_response *resp;
+
+ if (!event) {
+ fwol_err("Event buffer is NULL");
+ return QDF_STATUS_E_FAILURE;
+ }
+
+ psoc = event->psoc;
+ if (!psoc) {
+ fwol_err("psoc is NULL");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ cbs = &fwol_obj->cbs;
+ if (cbs->get_elna_bypass_callback) {
+ resp = &event->get_elna_bypass_response;
+ cbs->get_elna_bypass_callback(cbs->get_elna_bypass_context,
+ resp);
+ } else {
+ fwol_err("NULL pointer for callback");
+ status = QDF_STATUS_E_IO;
+ }
+
+ return status;
+}
+#else
+static QDF_STATUS
+fwol_process_get_elna_bypass_resp(struct wlan_fwol_rx_event *event)
+{
+ return QDF_STATUS_SUCCESS;
+}
+#endif /* WLAN_FEATURE_ELNA */
+
+QDF_STATUS fwol_process_event(struct scheduler_msg *msg)
+{
+ QDF_STATUS status;
+ struct wlan_fwol_rx_event *event;
+
+ fwol_debug("msg type %d", msg->type);
+
+ if (!(msg->bodyptr)) {
+ fwol_err("Invalid message body");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ event = msg->bodyptr;
+ msg->bodyptr = NULL;
+
+ switch (msg->type) {
+ case WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE:
+ status = fwol_process_get_elna_bypass_resp(event);
+ break;
+ default:
+ status = QDF_STATUS_E_INVAL;
+ break;
+ }
+
+ fwol_release_rx_event(event);
+
+ return status;
+}
+
+void fwol_release_rx_event(struct wlan_fwol_rx_event *event)
+{
+ if (!event) {
+ fwol_err("event is NULL");
+ return;
+ }
+
+ if (event->psoc)
+ wlan_objmgr_psoc_release_ref(event->psoc, WLAN_FWOL_SB_ID);
+ qdf_mem_free(event);
+}
diff --git a/components/fw_offload/dispatcher/inc/cfg_fwol.h b/components/fw_offload/dispatcher/inc/cfg_fwol.h
index 3e39ac4..245d3d7 100644
--- a/components/fw_offload/dispatcher/inc/cfg_fwol.h
+++ b/components/fw_offload/dispatcher/inc/cfg_fwol.h
@@ -29,6 +29,7 @@
#include "cfg_neighbor_roam.h"
#include "cfg_adaptive_dwelltime.h"
+#ifdef WLAN_FW_OFFLOAD
#define CFG_FWOL_ALL \
CFG_ADAPTIVE_DWELLTIME_ALL \
CFG_11K_ALL \
@@ -36,6 +37,9 @@
CFG_FWOL_GENERIC_ALL \
CFG_IE_WHITELIST \
CFG_THERMAL_TEMP_ALL
+#else
+#define CFG_FWOL_ALL
+#endif
#endif /* __CFG_FWOL_H */
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h b/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
new file mode 100644
index 0000000..ea0863b
--- /dev/null
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_public_structs.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019 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 fw offload structure definations
+ */
+
+#ifndef _WLAN_FWOL_PUBLIC_STRUCTS_H_
+#define _WLAN_FWOL_PUBLIC_STRUCTS_H_
+
+#include "wlan_objmgr_psoc_obj.h"
+
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * struct set_elna_bypass_request - set eLNA bypass request
+ * @vdev_id: vdev id
+ * @en_dis: 0 - disable eLNA bypass
+ * 1 - enable eLNA bypass
+ */
+struct set_elna_bypass_request {
+ uint8_t vdev_id;
+ uint8_t en_dis;
+};
+
+/**
+ * struct get_elna_bypass_request - get eLNA bypass request
+ * @vdev_id: vdev id
+ */
+struct get_elna_bypass_request {
+ uint8_t vdev_id;
+};
+
+/**
+ * struct get_elna_bypass_response - get eLNA bypass response
+ * @vdev_id: vdev id
+ * @en_dis: 0 - disable eLNA bypass
+ * 1 - enable eLNA bypass
+ */
+struct get_elna_bypass_response {
+ uint8_t vdev_id;
+ uint8_t en_dis;
+};
+#endif
+
+/**
+ * struct wlan_fwol_callbacks - fw offload callbacks
+ * @get_elna_bypass_callback: callback for get eLNA bypass
+ * @get_elna_bypass_context: context for get eLNA bypass
+ */
+struct wlan_fwol_callbacks {
+#ifdef WLAN_FEATURE_ELNA
+ void (*get_elna_bypass_callback)(void *context,
+ struct get_elna_bypass_response *response);
+ void *get_elna_bypass_context;
+#endif
+};
+
+/**
+ * struct wlan_fwol_tx_ops - structure of tx func pointers
+ * @set_elna_bypass: set eLNA bypass
+ * @get_elna_bypass: get eLNA bypass
+ * @reg_evt_handler: register event handler
+ * @unreg_evt_handler: unregister event handler
+ */
+struct wlan_fwol_tx_ops {
+#ifdef WLAN_FEATURE_ELNA
+ QDF_STATUS (*set_elna_bypass)(struct wlan_objmgr_psoc *psoc,
+ struct set_elna_bypass_request *req);
+ QDF_STATUS (*get_elna_bypass)(struct wlan_objmgr_psoc *psoc,
+ struct get_elna_bypass_request *req);
+#endif
+ QDF_STATUS (*reg_evt_handler)(struct wlan_objmgr_psoc *psoc,
+ void *arg);
+ QDF_STATUS (*unreg_evt_handler)(struct wlan_objmgr_psoc *psoc,
+ void *arg);
+};
+
+/**
+ * struct wlan_fwol_rx_ops - structure of rx func pointers
+ * @get_elna_bypass_resp: get eLNA bypass response
+ */
+struct wlan_fwol_rx_ops {
+#ifdef WLAN_FEATURE_ELNA
+ QDF_STATUS (*get_elna_bypass_resp)(struct wlan_objmgr_psoc *psoc,
+ struct get_elna_bypass_response *resp);
+#endif
+};
+
+#endif /* _WLAN_FWOL_PUBLIC_STRUCTS_H_ */
+
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_tgt_api.h b/components/fw_offload/dispatcher/inc/wlan_fwol_tgt_api.h
new file mode 100644
index 0000000..4bf88b2
--- /dev/null
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_tgt_api.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019 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: fw offload south bound interface declaration
+ */
+#ifndef _WLAN_FWOL_TGT_API_H
+#define _WLAN_FWOL_TGT_API_H
+
+#include "wlan_fwol_public_structs.h"
+
+/**
+ * tgt_fwol_register_ev_handler() - register south bound event handler
+ * @psoc: psoc handle
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS tgt_fwol_register_ev_handler(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * tgt_fwol_unregister_ev_handler() - unregister south bound event handler
+ * @psoc: psoc handle
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS tgt_fwol_unregister_ev_handler(struct wlan_objmgr_psoc *psoc);
+
+/**
+ * tgt_fwol_register_rx_ops() - register fw offload rx operations
+ * @rx_ops: fps to rx operations
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS tgt_fwol_register_rx_ops(struct wlan_fwol_rx_ops *rx_ops);
+#endif /* _WLAN_FWOL_TGT_API_H */
diff --git a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
index bccd02a..c835073 100644
--- a/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
+++ b/components/fw_offload/dispatcher/inc/wlan_fwol_ucfg_api.h
@@ -26,7 +26,9 @@
#include <wlan_objmgr_global_obj.h>
#include <wlan_cmn.h>
#include "wlan_fw_offload_main.h"
+#include "wlan_fwol_public_structs.h"
+#ifdef WLAN_FW_OFFLOAD
/**
* ucfg_fwol_psoc_open() - FWOL component Open
* @psoc: pointer to psoc object
@@ -523,4 +525,321 @@
{
return fwol_set_adaptive_dwelltime_config(dwelltime_params);
}
+
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * ucfg_fwol_set_elna_bypass() - send set eLNA bypass request
+ * @vdev: vdev handle
+ * @req: set eLNA bypass request
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS ucfg_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct set_elna_bypass_request *req);
+
+/**
+ * ucfg_fwol_get_elna_bypass() - send get eLNA bypass request
+ * @vdev: vdev handle
+ * @req: get eLNA bypass request
+ * @callback: get eLNA bypass response callback
+ * @context: request manager context
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+QDF_STATUS ucfg_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct get_elna_bypass_request *req,
+ void (*callback)(void *context,
+ struct get_elna_bypass_response *response),
+ void *context);
+#endif /* WLAN_FEATURE_ELNA */
+#else
+static inline QDF_STATUS ucfg_fwol_psoc_open(struct wlan_objmgr_psoc *psoc)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
+static inline void ucfg_fwol_psoc_close(struct wlan_objmgr_psoc *psoc)
+{
+}
+
+static inline QDF_STATUS ucfg_fwol_init(void)
+{
+ return QDF_STATUS_SUCCESS;
+}
+
+static inline void ucfg_fwol_deinit(void)
+{
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_coex_config_params(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_coex_config *coex_config)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_thermal_temp(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_thermal_temp *thermal_temp)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_neighbor_report_cfg(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_neighbor_report_cfg
+ *fwol_neighbor_report_cfg)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_is_neighbor_report_req_supported(struct wlan_objmgr_psoc *psoc,
+ bool *neighbor_report_req)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_ie_whitelist(struct wlan_objmgr_psoc *psoc, bool *ie_whitelist)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_set_ie_whitelist(struct wlan_objmgr_psoc *psoc, bool ie_whitelist)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_all_whitelist_params(struct wlan_objmgr_psoc *psoc,
+ struct wlan_fwol_ie_whitelist *whitelist)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_ani_enabled(struct wlan_objmgr_psoc *psoc,
+ bool *ani_enabled)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_enable_rts_sifsbursting(struct wlan_objmgr_psoc *psoc,
+ bool *enable_rts_sifsbursting)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_max_mpdus_inampdu(struct wlan_objmgr_psoc *psoc,
+ uint8_t *max_mpdus_inampdu)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_arp_ac_category(struct wlan_objmgr_psoc *psoc,
+ uint32_t *arp_ac_category)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_enable_phy_reg_retention(struct wlan_objmgr_psoc *psoc,
+ uint8_t *enable_phy_reg_retention)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_upper_brssi_thresh(struct wlan_objmgr_psoc *psoc,
+ uint16_t *upper_brssi_thresh)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_lower_brssi_thresh(struct wlan_objmgr_psoc *psoc,
+ uint16_t *lower_brssi_thresh)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_enable_dtim_1chrx(struct wlan_objmgr_psoc *psoc,
+ bool *enable_dtim_1chrx)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_alternative_chainmask_enabled(struct wlan_objmgr_psoc *psoc,
+ bool *alternative_chainmask_enabled)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_get_smart_chainmask_enabled(struct wlan_objmgr_psoc *psoc,
+ bool *smart_chainmask_enabled)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_rts_profile(struct wlan_objmgr_psoc *psoc,
+ uint16_t *get_rts_profile)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_enable_fw_log_level(struct wlan_objmgr_psoc *psoc,
+ uint16_t *enable_fw_log_level)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_enable_fw_log_type(struct wlan_objmgr_psoc *psoc,
+ uint16_t *enable_fw_log_type)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_enable_fw_module_log_level(
+ struct wlan_objmgr_psoc *psoc,
+ uint8_t **enable_fw_module_log_level,
+ uint8_t *enable_fw_module_log_level_num)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_tsf_gpio_pin(struct wlan_objmgr_psoc *psoc,
+ uint32_t *tsf_gpio_pin)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_tsf_ptp_options(struct wlan_objmgr_psoc *psoc,
+ uint32_t *tsf_ptp_options)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_lprx_enable(struct wlan_objmgr_psoc *psoc,
+ bool *lprx_enable)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline bool ucfg_fwol_get_sae_enable(struct wlan_objmgr_psoc *psoc)
+{
+ return false;
+}
+
+static inline bool ucfg_fwol_get_gcmp_enable(struct wlan_objmgr_psoc *psoc)
+{
+ return false;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_enable_tx_sch_delay(struct wlan_objmgr_psoc *psoc,
+ uint8_t *enable_tx_sch_delay)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_enable_secondary_rate(struct wlan_objmgr_psoc *psoc,
+ uint32_t *enable_secondary_rate)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_all_adaptive_dwelltime_params(
+ struct wlan_objmgr_psoc *psoc,
+ struct adaptive_dwelltime_params *dwelltime_params)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_adaptive_dwell_mode_enabled(struct wlan_objmgr_psoc *psoc,
+ bool *adaptive_dwell_mode_enabled)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_global_adapt_dwelltime_mode(struct wlan_objmgr_psoc *psoc,
+ uint8_t *global_adapt_dwelltime_mode)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_adapt_dwell_lpf_weight(struct wlan_objmgr_psoc *psoc,
+ uint8_t *adapt_dwell_lpf_weight)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_adapt_dwell_passive_mon_intval(
+ struct wlan_objmgr_psoc *psoc,
+ uint8_t *adapt_dwell_passive_mon_intval)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_adapt_dwell_wifi_act_threshold(
+ struct wlan_objmgr_psoc *psoc,
+ uint8_t *adapt_dwell_wifi_act_threshold)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_init_adapt_dwelltime_in_cfg(
+ struct wlan_objmgr_psoc *psoc,
+ struct adaptive_dwelltime_params *dwelltime_params)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_set_adaptive_dwelltime_config(
+ struct adaptive_dwelltime_params *dwelltime_params)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+#ifdef FEATURE_WLAN_RA_FILTERING
+static inline QDF_STATUS
+ucfg_fwol_set_is_rate_limit_enabled(struct wlan_objmgr_psoc *psoc,
+ bool is_rate_limit_enabled)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+
+static inline QDF_STATUS
+ucfg_fwol_get_is_rate_limit_enabled(struct wlan_objmgr_psoc *psoc,
+ bool *is_rate_limit_enabled)
+{
+ return QDF_STATUS_E_FAILURE;
+}
+#endif /* FEATURE_WLAN_RA_FILTERING */
+
+#endif /* WLAN_FW_OFFLOAD */
+
#endif /* _WLAN_FWOL_UCFG_API_H_ */
diff --git a/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c b/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c
new file mode 100644
index 0000000..8778fc6
--- /dev/null
+++ b/components/fw_offload/dispatcher/src/wlan_fwol_tgt_api.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019 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 fw offload south bound interface definitions
+ */
+
+#include "scheduler_api.h"
+#include "wlan_objmgr_psoc_obj.h"
+#include "wlan_objmgr_global_obj.h"
+#include "wlan_objmgr_pdev_obj.h"
+#include "wlan_fwol_public_structs.h"
+#include "wlan_fwol_ucfg_api.h"
+#include "wlan_fwol_tgt_api.h"
+#include "wlan_fw_offload_main.h"
+
+QDF_STATUS tgt_fwol_register_ev_handler(struct wlan_objmgr_psoc *psoc)
+{
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_tx_ops *tx_ops;
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+ if (!psoc) {
+ fwol_err("NULL psoc handle");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ tx_ops = &fwol_obj->tx_ops;
+ if (tx_ops->reg_evt_handler) {
+ status = tx_ops->reg_evt_handler(psoc, NULL);
+ fwol_debug("reg_evt_handler, status:%d", status);
+ } else {
+ fwol_alert("No reg_evt_handler");
+ }
+
+ return status;
+}
+
+QDF_STATUS tgt_fwol_unregister_ev_handler(struct wlan_objmgr_psoc *psoc)
+{
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_tx_ops *tx_ops;
+ QDF_STATUS status = QDF_STATUS_E_FAILURE;
+
+ if (!psoc) {
+ fwol_err("NNULL psoc handle");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ tx_ops = &fwol_obj->tx_ops;
+ if (tx_ops->unreg_evt_handler) {
+ status = tx_ops->unreg_evt_handler(psoc, NULL);
+ fwol_debug("unreg_evt_handler, status:%d", status);
+ } else {
+ fwol_alert("No unreg_evt_handler");
+ }
+
+ return status;
+}
+
+/**
+ * fwol_flush_callback() - fw offload message flush callback
+ * @msg: fw offload message
+ *
+ * Return: QDF_STATUS_SUCCESS on success.
+ */
+__attribute__((unused))
+static QDF_STATUS fwol_flush_callback(struct scheduler_msg *msg)
+{
+ struct wlan_fwol_rx_event *event;
+
+ if (!msg) {
+ fwol_err("NULL pointer for eLNA message");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ event = msg->bodyptr;
+ msg->bodyptr = NULL;
+ fwol_release_rx_event(event);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * tgt_fwol_get_elna_bypass_resp() - handler for get eLNA bypass response
+ * @psoc: psoc handle
+ * @resp: status for last channel config
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+tgt_fwol_get_elna_bypass_resp(struct wlan_objmgr_psoc *psoc,
+ struct get_elna_bypass_response *resp)
+{
+ QDF_STATUS status;
+ struct scheduler_msg msg = {0};
+ struct wlan_fwol_rx_event *event;
+
+ event = qdf_mem_malloc(sizeof(*event));
+ if (!event)
+ return QDF_STATUS_E_NOMEM;
+
+ status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_FWOL_SB_ID);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ fwol_err("Failed to get psoc ref");
+ fwol_release_rx_event(event);
+ return status;
+ }
+
+ event->psoc = psoc;
+ event->event_id = WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE;
+ event->get_elna_bypass_response = *resp;
+ msg.type = WLAN_FWOL_EVT_GET_ELNA_BYPASS_RESPONSE;
+ msg.bodyptr = event;
+ msg.callback = fwol_process_event;
+ msg.flush_callback = fwol_flush_callback;
+ status = scheduler_post_message(QDF_MODULE_ID_FWOL,
+ QDF_MODULE_ID_FWOL,
+ QDF_MODULE_ID_TARGET_IF, &msg);
+
+ if (QDF_IS_STATUS_SUCCESS(status))
+ return QDF_STATUS_SUCCESS;
+
+ fwol_err("failed to send WLAN_FWOL_GET_ELNA_BYPASS_RESPONSE msg");
+ fwol_flush_callback(&msg);
+
+ return status;
+}
+
+static void tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
+{
+ rx_ops->get_elna_bypass_resp = tgt_fwol_get_elna_bypass_resp;
+}
+#else
+static void tgt_fwol_register_elna_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
+{
+}
+#endif /* WLAN_FEATURE_ELNA */
+
+QDF_STATUS tgt_fwol_register_rx_ops(struct wlan_fwol_rx_ops *rx_ops)
+{
+ tgt_fwol_register_elna_rx_ops(rx_ops);
+
+ return QDF_STATUS_SUCCESS;
+}
diff --git a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
index 019fb5f..961f1f0 100644
--- a/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
+++ b/components/fw_offload/dispatcher/src/wlan_fwol_ucfg_api.c
@@ -20,7 +20,11 @@
*/
#include "wlan_fw_offload_main.h"
+#include "wlan_fwol_public_structs.h"
#include "wlan_fwol_ucfg_api.h"
+#include "wlan_fwol_tgt_api.h"
+#include "target_if_fwol.h"
+#include "wlan_objmgr_vdev_obj.h"
QDF_STATUS ucfg_fwol_psoc_open(struct wlan_objmgr_psoc *psoc)
{
@@ -30,12 +34,16 @@
if (QDF_IS_STATUS_ERROR(status))
fwol_err("Failed to initialize FWOL CFG");
+ tgt_fwol_register_ev_handler(psoc);
+
return status;
}
void ucfg_fwol_psoc_close(struct wlan_objmgr_psoc *psoc)
{
/* Clear the FWOL CFG Structure */
+
+ tgt_fwol_unregister_ev_handler(psoc);
}
/**
@@ -66,6 +74,9 @@
qdf_mem_free(fwol_obj);
}
+ tgt_fwol_register_rx_ops(&fwol_obj->rx_ops);
+ target_if_fwol_register_tx_ops(&fwol_obj->tx_ops);
+
return status;
}
@@ -832,3 +843,71 @@
fwol_obj->cfg.dwelltime_params.wifi_act_threshold;
return QDF_STATUS_SUCCESS;
}
+
+#ifdef WLAN_FEATURE_ELNA
+QDF_STATUS ucfg_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct set_elna_bypass_request *req)
+{
+ QDF_STATUS status;
+ struct wlan_objmgr_psoc *psoc;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_tx_ops *tx_ops;
+
+ psoc = wlan_vdev_get_psoc(vdev);
+ if (!psoc) {
+ fwol_err("NULL pointer for psoc");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ tx_ops = &fwol_obj->tx_ops;
+ if (tx_ops->set_elna_bypass)
+ status = tx_ops->set_elna_bypass(psoc, req);
+ else
+ status = QDF_STATUS_E_IO;
+
+ return status;
+}
+
+QDF_STATUS ucfg_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct get_elna_bypass_request *req,
+ void (*callback)(void *context,
+ struct get_elna_bypass_response *response),
+ void *context)
+{
+ QDF_STATUS status;
+ struct wlan_objmgr_psoc *psoc;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_tx_ops *tx_ops;
+ struct wlan_fwol_callbacks *cbs;
+
+ psoc = wlan_vdev_get_psoc(vdev);
+ if (!psoc) {
+ fwol_err("NULL pointer for psoc");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ fwol_err("Failed to get FWOL Obj");
+ return QDF_STATUS_E_INVAL;
+ }
+
+ cbs = &fwol_obj->cbs;
+ cbs->get_elna_bypass_callback = callback;
+ cbs->get_elna_bypass_context = context;
+
+ tx_ops = &fwol_obj->tx_ops;
+ if (tx_ops->get_elna_bypass)
+ status = tx_ops->get_elna_bypass(psoc, req);
+ else
+ status = QDF_STATUS_E_IO;
+
+ return status;
+}
+#endif /* WLAN_FEATURE_ELNA */
diff --git a/components/target_if/fw_offload/inc/target_if_fwol.h b/components/target_if/fw_offload/inc/target_if_fwol.h
new file mode 100644
index 0000000..7a6ab16
--- /dev/null
+++ b/components/target_if/fw_offload/inc/target_if_fwol.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 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: target interface APIs for fw offload
+ *
+ */
+
+#ifndef __TARGET_IF_FWOL_H__
+#define __TARGET_IF_FWOL_H__
+
+/**
+ * target_if_fwol_register_event_handler() - register fw offload event handler
+ * @psoc: psoc object
+ * @arg: argument passed to lmac
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS target_if_fwol_register_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg);
+
+/**
+ * target_if_fwol_unregister_event_handler() - unregister fw offload event
+ * handler
+ * @psoc: psoc object
+ * @arg: argument passed to lmac
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS
+target_if_fwol_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg);
+
+/**
+ * target_if_fwol_register_tx_ops() - register fw offload tx ops callback
+ * functions
+ * @tx_ops: fw offload tx operations
+ *
+ * Return: QDF_STATUS
+ */
+QDF_STATUS target_if_fwol_register_tx_ops(struct wlan_fwol_tx_ops *tx_ops);
+
+#endif /* __TARGET_IF_FWOL_H__ */
diff --git a/components/target_if/fw_offload/src/target_if_fwol.c b/components/target_if/fw_offload/src/target_if_fwol.c
new file mode 100644
index 0000000..276f250
--- /dev/null
+++ b/components/target_if/fw_offload/src/target_if_fwol.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2019 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: target interface APIs for fw offload
+ *
+ */
+
+#include "qdf_mem.h"
+#include "target_if.h"
+#include "qdf_status.h"
+#include "wmi_unified_api.h"
+#include "wmi_unified_priv.h"
+#include "wmi_unified_param.h"
+#include "wlan_objmgr_psoc_obj.h"
+#include "wlan_utility.h"
+#include "wlan_defs.h"
+#include "wlan_fwol_public_structs.h"
+#include "wlan_fw_offload_main.h"
+#include "target_if_fwol.h"
+
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * target_if_fwol_set_elna_bypass() - send set eLNA bypass request to FW
+ * @psoc: pointer to PSOC object
+ * @req: set eLNA bypass request
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+target_if_fwol_set_elna_bypass(struct wlan_objmgr_psoc *psoc,
+ struct set_elna_bypass_request *req)
+{
+ QDF_STATUS status;
+
+ status = wmi_unified_send_set_elna_bypass_cmd(
+ get_wmi_unified_hdl_from_psoc(psoc),
+ req);
+ if (status)
+ target_if_err("Failed to set eLNA bypass %d", status);
+
+ return status;
+}
+
+/**
+ * target_if_fwol_get_elna_bypass() - send get eLNA bypass request to FW
+ * @psoc: pointer to PSOC object
+ * @req: get eLNA bypass request
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ */
+static QDF_STATUS
+target_if_fwol_get_elna_bypass(struct wlan_objmgr_psoc *psoc,
+ struct get_elna_bypass_request *req)
+{
+ QDF_STATUS status;
+
+ status = wmi_unified_send_get_elna_bypass_cmd(
+ get_wmi_unified_hdl_from_psoc(psoc),
+ req);
+ if (status)
+ target_if_err("Failed to set eLNA bypass %d", status);
+
+ return status;
+}
+
+/**
+ * target_if_fwol_get_elna_bypass_resp() - handler for get eLNA bypass response
+ * @scn: scn handle
+ * @event_buf: pointer to the event buffer
+ * @len: length of the buffer
+ *
+ * Return: 0 on success
+ */
+static int target_if_fwol_get_elna_bypass_resp(ol_scn_t scn, uint8_t *event_buf,
+ uint32_t len)
+{
+ QDF_STATUS status;
+ struct get_elna_bypass_response resp;
+ struct wlan_objmgr_psoc *psoc;
+ struct wlan_fwol_psoc_obj *fwol_obj;
+ struct wlan_fwol_rx_ops *rx_ops;
+
+ target_if_debug("scn:%pK, data:%pK, datalen:%d", scn, event_buf, len);
+ if (!scn || !event_buf) {
+ target_if_err("scn: 0x%pK, data: 0x%pK", scn, event_buf);
+ return -EINVAL;
+ }
+
+ psoc = target_if_get_psoc_from_scn_hdl(scn);
+ if (!psoc) {
+ target_if_err("null psoc");
+ return -EINVAL;
+ }
+
+ fwol_obj = fwol_get_psoc_obj(psoc);
+ if (!fwol_obj) {
+ target_if_err("Failed to get FWOL Obj");
+ return -EINVAL;
+ }
+
+ rx_ops = &fwol_obj->rx_ops;
+ if (rx_ops->get_elna_bypass_resp) {
+ status = wmi_extract_get_elna_bypass_resp(
+ get_wmi_unified_hdl_from_psoc(psoc),
+ event_buf, &resp);
+ if (QDF_IS_STATUS_ERROR(status)) {
+ target_if_err("Failed to extract eLNA bypass");
+ return -EINVAL;
+ }
+ status = rx_ops->get_elna_bypass_resp(psoc, &resp);
+ if (status != QDF_STATUS_SUCCESS) {
+ target_if_err("get_elna_bypass_resp failed.");
+ return -EINVAL;
+ }
+ } else {
+ target_if_fatal("No get_elna_bypass_resp callback");
+ return -EINVAL;
+ }
+
+ return 0;
+};
+
+static void
+target_if_fwol_register_elna_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg)
+{
+ int rc;
+
+ rc = wmi_unified_register_event(get_wmi_unified_hdl_from_psoc(psoc),
+ wmi_get_elna_bypass_event_id,
+ target_if_fwol_get_elna_bypass_resp);
+ if (rc)
+ target_if_err("Failed to register get eLNA bypass event cb");
+}
+
+static void
+target_if_fwol_unregister_elna_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg)
+{
+ int rc;
+
+ rc = wmi_unified_unregister_event_handler(
+ get_wmi_unified_hdl_from_psoc(psoc),
+ wmi_get_elna_bypass_event_id);
+ if (rc)
+ target_if_err("Failed to unregister get eLNA bypass event cb");
+}
+
+static void
+target_if_fwol_register_elna_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+ tx_ops->set_elna_bypass = target_if_fwol_set_elna_bypass;
+ tx_ops->get_elna_bypass = target_if_fwol_get_elna_bypass;
+}
+#else
+static void
+target_if_fwol_register_elna_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg)
+{
+}
+
+static void
+target_if_fwol_unregister_elna_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg)
+{
+}
+
+static void
+target_if_fwol_register_elna_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+}
+#endif /* WLAN_FEATURE_ELNA */
+
+QDF_STATUS target_if_fwol_register_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg)
+{
+ target_if_fwol_register_elna_event_handler(psoc, arg);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS
+target_if_fwol_unregister_event_handler(struct wlan_objmgr_psoc *psoc,
+ void *arg)
+{
+ target_if_fwol_unregister_elna_event_handler(psoc, arg);
+
+ return QDF_STATUS_SUCCESS;
+}
+
+QDF_STATUS target_if_fwol_register_tx_ops(struct wlan_fwol_tx_ops *tx_ops)
+{
+ target_if_fwol_register_elna_tx_ops(tx_ops);
+
+ tx_ops->reg_evt_handler = target_if_fwol_register_event_handler;
+ tx_ops->unreg_evt_handler = target_if_fwol_unregister_event_handler;
+
+ return QDF_STATUS_SUCCESS;
+}
+
diff --git a/configs/default_defconfig b/configs/default_defconfig
index 3bd13e7..14e8155 100644
--- a/configs/default_defconfig
+++ b/configs/default_defconfig
@@ -905,6 +905,14 @@
#Enable OEM DATA feature
CONFIG_FEATURE_OEM_DATA := y
+#Enable FW Offload
+CONFIG_WLAN_FW_OFFLOAD := y
+
+#Enable eLNA bypass feature
+ifeq ($(CONFIG_WLAN_FW_OFFLOAD), y)
+CONFIG_WLAN_FEATURE_ELNA := y
+endif
+
ifeq (y,$(findstring y,$(CONFIG_ARCH_MSM) $(CONFIG_ARCH_QCOM)))
CONFIG_WLAN_FEATURE_DP_BUS_BANDWIDTH := y
endif
diff --git a/configs/genoa.common b/configs/genoa.common
index 384fedc..8e7a575 100644
--- a/configs/genoa.common
+++ b/configs/genoa.common
@@ -221,4 +221,8 @@
endif
CONFIG_SAP_DHCP_FW_IND := n
+
+#Enable FW Offload
+CONFIG_WLAN_FW_OFFLOAD := y
+
###################################
diff --git a/configs/qca6174_defconfig b/configs/qca6174_defconfig
index 10dee88..1731a86 100644
--- a/configs/qca6174_defconfig
+++ b/configs/qca6174_defconfig
@@ -716,3 +716,7 @@
endif
CONFIG_SAP_DHCP_FW_IND := y
+
+#Enable FW Offload
+CONFIG_WLAN_FW_OFFLOAD := y
+
diff --git a/configs/qca6390_defconfig b/configs/qca6390_defconfig
index dede872..5fe7ac5 100644
--- a/configs/qca6390_defconfig
+++ b/configs/qca6390_defconfig
@@ -750,3 +750,7 @@
CONFIG_FOURTH_CONNECTION := y
CONFIG_SAP_DHCP_FW_IND := y
+
+#Enable FW Offload
+CONFIG_WLAN_FW_OFFLOAD := y
+
diff --git a/configs/qcs40x.snoc.perf_defconfig b/configs/qcs40x.snoc.perf_defconfig
index 44c853c..ce77021 100644
--- a/configs/qcs40x.snoc.perf_defconfig
+++ b/configs/qcs40x.snoc.perf_defconfig
@@ -172,6 +172,9 @@
endif
endif
+#Enable FW Offload
+CONFIG_WLAN_FW_OFFLOAD := y
+
CONFIG_ENABLE_SIZE_OPTIMIZE := y
# configure log buffer size
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index c72b652..94ccdb8 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -141,6 +141,7 @@
#include "wlan_blm_ucfg_api.h"
#include "wlan_hdd_hw_capability.h"
#include "wlan_hdd_oemdata.h"
+#include "os_if_fwol.h"
#define g_mode_rates_size (12)
#define a_mode_rates_size (8)
@@ -6108,6 +6109,7 @@
[QCA_WLAN_VENDOR_ATTR_CONFIG_SCAN_ENABLE] = {.type = NLA_U8 },
[QCA_WLAN_VENDOR_ATTR_CONFIG_RSN_IE] = {.type = NLA_U8},
[QCA_WLAN_VENDOR_ATTR_CONFIG_GTX] = {.type = NLA_U8},
+ [QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS] = {.type = NLA_U8},
[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY] = {.type = NLA_U32 },
[QCA_WLAN_VENDOR_ATTR_CONFIG_ACCESS_POLICY_IE_LIST] = {
.type = NLA_BINARY,
@@ -7270,6 +7272,32 @@
return qdf_status_to_os_return(status);
}
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * hdd_set_elna_bypass() - Set eLNA bypass
+ * @adapter: Pointer to HDD adapter
+ * @attr: Pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+static int hdd_set_elna_bypass(struct hdd_adapter *adapter,
+ const struct nlattr *attr)
+{
+ int ret;
+ struct wlan_objmgr_vdev *vdev;
+
+ vdev = hdd_objmgr_get_vdev(adapter);
+ if (!vdev)
+ return -EINVAL;
+
+ ret = os_if_fwol_set_elna_bypass(vdev, attr);
+
+ hdd_objmgr_put_vdev(vdev);
+
+ return ret;
+}
+#endif
+
/**
* typedef independent_setter_fn - independent attribute handler
* @adapter: The adapter being configured
@@ -7356,8 +7384,135 @@
hdd_config_gtx},
{QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES,
hdd_config_disconnect_ies},
+#ifdef WLAN_FEATURE_ELNA
+ {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
+ hdd_set_elna_bypass},
+#endif
};
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * hdd_get_elna_bypass() - Get eLNA bypass
+ * @adapter: Pointer to HDD adapter
+ * @skb: sk buffer to hold nl80211 attributes
+ * @attr: Pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+static int hdd_get_elna_bypass(struct hdd_adapter *adapter,
+ struct sk_buff *skb,
+ const struct nlattr *attr)
+{
+ int ret;
+ struct wlan_objmgr_vdev *vdev;
+
+ vdev = hdd_objmgr_get_vdev(adapter);
+ if (!vdev)
+ return -EINVAL;
+
+ ret = os_if_fwol_get_elna_bypass(vdev, skb, attr);
+
+ hdd_objmgr_put_vdev(vdev);
+
+ return ret;
+}
+#endif
+
+/**
+ * typedef config_getter_fn - get configuration handler
+ * @adapter: The adapter being configured
+ * @skb: sk buffer to hold nl80211 attributes
+ * @attr: The nl80211 attribute being applied
+ *
+ * Defines the signature of functions in the attribute vtable
+ *
+ * Return: 0 if the attribute was handled successfully, otherwise an errno
+ */
+typedef int (*config_getter_fn)(struct hdd_adapter *adapter,
+ struct sk_buff *skb,
+ const struct nlattr *attr);
+
+/**
+ * struct config_getters
+ * @id: vendor attribute which this entry handles
+ * @cb: callback function to invoke to process the attribute when present
+ */
+struct config_getters {
+ uint32_t id;
+ size_t max_attr_len;
+ config_getter_fn cb;
+};
+
+/* vtable for config getters */
+static const struct config_getters config_getters[] = {
+#ifdef WLAN_FEATURE_ELNA
+ {QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
+ sizeof(uint8_t),
+ hdd_get_elna_bypass},
+#endif
+};
+
+/**
+ * hdd_get_configuration() - Handle get configuration
+ * @adapter: adapter upon which the vendor command was received
+ * @tb: parsed attribute array
+ *
+ * This is a table-driven function which dispatches attributes
+ * in a QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION
+ * vendor command.
+ *
+ * Return: 0 if there were no issues, otherwise errno of the last issue
+ */
+static int hdd_get_configuration(struct hdd_adapter *adapter,
+ struct nlattr **tb)
+{
+ struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ uint32_t i, id;
+ unsigned long nl_buf_len = NLMSG_HDRLEN;
+ struct sk_buff *skb;
+ struct nlattr *attr;
+ config_getter_fn cb;
+ int errno = 0;
+
+ for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
+ id = config_getters[i].id;
+ attr = tb[id];
+ if (!attr)
+ continue;
+
+ nl_buf_len += NLA_HDRLEN +
+ NLA_ALIGN(config_getters[i].max_attr_len);
+ }
+
+ skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len);
+ if (!skb) {
+ hdd_err("cfg80211_vendor_cmd_alloc_reply_skb failed");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < QDF_ARRAY_SIZE(config_getters); i++) {
+ id = config_getters[i].id;
+ attr = tb[id];
+ if (!attr)
+ continue;
+
+ cb = config_getters[i].cb;
+ errno = cb(adapter, skb, attr);
+ if (errno)
+ break;
+ }
+
+ if (errno) {
+ hdd_err("Failed to get wifi configuration, errno = %d", errno);
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+
+ cfg80211_vendor_cmd_reply(skb);
+
+ return errno;
+}
+
/**
* hdd_set_independent_configuration() - Handle independent attributes
* @adapter: adapter upon which the vendor command was received
@@ -7537,6 +7692,88 @@
}
/**
+ * __wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
+ * vendor command
+ * @wiphy: wiphy device pointer
+ * @wdev: wireless device pointer
+ * @data: Vendor command data buffer
+ * @data_len: Buffer length
+ *
+ * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
+ *
+ * Return: Error code.
+ */
+static int
+__wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ struct net_device *dev = wdev->netdev;
+ struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1];
+ int errno;
+ int ret;
+
+ hdd_enter_dev(dev);
+
+ if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
+ hdd_err("Command not allowed in FTM mode");
+ return -EPERM;
+ }
+
+ errno = wlan_hdd_validate_context(hdd_ctx);
+ if (errno)
+ return errno;
+
+ if (wlan_cfg80211_nla_parse(tb, QCA_WLAN_VENDOR_ATTR_CONFIG_MAX, data,
+ data_len, wlan_hdd_wifi_config_policy)) {
+ hdd_err("invalid attr");
+ return -EINVAL;
+ }
+
+ ret = hdd_get_configuration(adapter, tb);
+ if (ret)
+ errno = ret;
+
+ return errno;
+}
+
+/**
+ * wlan_hdd_cfg80211_wifi_configuration_get() - Wifi configuration
+ * vendor command
+ *
+ * @wiphy: wiphy device pointer
+ * @wdev: wireless device pointer
+ * @data: Vendor command data buffer
+ * @data_len: Buffer length
+ *
+ * Handles QCA_WLAN_VENDOR_ATTR_CONFIG_MAX.
+ *
+ * Return: EOK or other error codes.
+ */
+static int wlan_hdd_cfg80211_wifi_configuration_get(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ int errno;
+ struct osif_vdev_sync *vdev_sync;
+
+ errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
+ if (errno)
+ return errno;
+
+ errno = __wlan_hdd_cfg80211_wifi_configuration_get(wiphy, wdev,
+ data, data_len);
+
+ osif_vdev_sync_op_stop(vdev_sync);
+
+ return errno;
+}
+
+/**
* __wlan_hdd_cfg80211_set_wifi_test_config() - Wifi test configuration
* vendor command
*
@@ -13500,6 +13737,14 @@
},
{
.info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_CONFIGURATION,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_wifi_configuration_get
+ },
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
.info.subcmd =
QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION,
.flags = WIPHY_VENDOR_CMD_NEED_WDEV |
diff --git a/os_if/fw_offload/inc/os_if_fwol.h b/os_if/fw_offload/inc/os_if_fwol.h
new file mode 100644
index 0000000..ec8a08f
--- /dev/null
+++ b/os_if/fw_offload/inc/os_if_fwol.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2019 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: os_if_fwol.h
+ *
+ * This Header file provide declaration for OS interface API
+ */
+
+#ifndef __OS_IF_FWOL_H__
+#define __OS_IF_FWOL_H__
+
+#include "wlan_objmgr_vdev_obj.h"
+
+#ifdef WLAN_FEATURE_ELNA
+/**
+ * os_if_fwol_set_elna_bypass() - Set eLNA bypass
+ * @vdev: Pointer to vdev
+ * @attr: Pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+int os_if_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ const struct nlattr *attr);
+
+/**
+ * os_if_fwol_get_elna_bypass() - Get eLNA bypass
+ * @vdev: Pointer to vdev
+ * @skb: sk buffer to hold nl80211 attributes
+ * @attr: Pointer to struct nlattr
+ *
+ * Return: 0 on success; error number otherwise
+ */
+int os_if_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct sk_buff *skb,
+ const struct nlattr *attr);
+#else
+static inline int os_if_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ const struct nlattr *attr)
+{
+ return 0;
+}
+
+static inline int os_if_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct sk_buff *skb,
+ const struct nlattr *attr)
+{
+ return 0;
+}
+#endif /* WLAN_FEATURE_ELNA */
+
+#endif /* __OS_IF_FWOL_H__ */
diff --git a/os_if/fw_offload/src/os_if_fwol.c b/os_if/fw_offload/src/os_if_fwol.c
new file mode 100644
index 0000000..bcb4c7d
--- /dev/null
+++ b/os_if/fw_offload/src/os_if_fwol.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2019 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: defines driver functions interfacing with linux kernel
+ */
+
+#include "wlan_cfg80211.h"
+#include "wlan_osif_request_manager.h"
+#include "wlan_fwol_public_structs.h"
+#include "wlan_fwol_ucfg_api.h"
+#include "os_if_fwol.h"
+
+#ifdef WLAN_FEATURE_ELNA
+#define WLAN_WAIT_TIME_GET_ELNA_BYPASS 1500
+
+int os_if_fwol_set_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ const struct nlattr *attr)
+{
+ struct set_elna_bypass_request req;
+ QDF_STATUS status;
+
+ req.vdev_id = vdev->vdev_objmgr.vdev_id;
+ req.en_dis = nla_get_u8(attr);
+ if (req.en_dis > 1) {
+ osif_err("Invalid elna_bypass value %d", req.en_dis);
+ return -EINVAL;
+ }
+
+ status = ucfg_fwol_set_elna_bypass(vdev, &req);
+ if (!QDF_IS_STATUS_SUCCESS(status))
+ osif_err("Failed to set ELNA BYPASS, %d", status);
+
+ return qdf_status_to_os_return(status);
+}
+
+struct osif_get_elna_bypass_priv {
+ uint8_t en_dis;
+};
+
+/**
+ * os_if_fwol_get_elna_bypass_callback() - Get eLNA bypass callback
+ * @context: Call context
+ * @response: Pointer to response structure
+ *
+ * Return: void
+ */
+static void
+os_if_fwol_get_elna_bypass_callback(void *context,
+ struct get_elna_bypass_response *response)
+{
+ struct osif_request *request;
+ struct osif_get_elna_bypass_priv *priv;
+
+ request = osif_request_get(context);
+ if (!request) {
+ osif_err("Obsolete request");
+ return;
+ }
+
+ priv = osif_request_priv(request);
+ priv->en_dis = response->en_dis;
+
+ osif_request_complete(request);
+ osif_request_put(request);
+}
+
+int os_if_fwol_get_elna_bypass(struct wlan_objmgr_vdev *vdev,
+ struct sk_buff *skb,
+ const struct nlattr *attr)
+{
+ struct get_elna_bypass_request req;
+ void *cookie;
+ struct osif_request *request;
+ struct osif_get_elna_bypass_priv *priv;
+ static const struct osif_request_params params = {
+ .priv_size = sizeof(*priv),
+ .timeout_ms = WLAN_WAIT_TIME_GET_ELNA_BYPASS,
+ };
+ QDF_STATUS status;
+ int ret = 0;
+
+ req.vdev_id = vdev->vdev_objmgr.vdev_id;
+
+ request = osif_request_alloc(¶ms);
+ if (!request) {
+ osif_err("Request allocation failure");
+ return -ENOMEM;
+ }
+ cookie = osif_request_cookie(request);
+
+ status = ucfg_fwol_get_elna_bypass(vdev, &req,
+ os_if_fwol_get_elna_bypass_callback,
+ cookie);
+ if (!QDF_IS_STATUS_SUCCESS(status)) {
+ osif_err("Failed to get ELNA BYPASS, %d", status);
+ ret = qdf_status_to_os_return(status);
+ goto end;
+ }
+
+ ret = osif_request_wait_for_response(request);
+ if (ret) {
+ osif_err("Operation timed out");
+ goto end;
+ }
+
+ priv = osif_request_priv(request);
+ if (nla_put_u8(skb, QCA_WLAN_VENDOR_ATTR_CONFIG_ELNA_BYPASS,
+ priv->en_dis)) {
+ osif_err("put fail");
+ ret = -EINVAL;
+ }
+
+end:
+ osif_request_put(request);
+ return ret;
+}
+#endif /* #ifdef WLAN_FEATURE_ELNA */