diff options
126 files changed, 8209 insertions, 2248 deletions
@@ -129,10 +129,6 @@ ifeq ($(KERNEL_BUILD), 0) CONFIG_LINUX_QCMBR :=y endif - ifeq ($(CONFIG_CNSS_EOS),y) - CONFIG_FEATURE_BMI_2 :=y - endif - CONFIG_MPC_UT_FRAMEWORK := y #Flag to enable offload packets feature @@ -377,6 +373,10 @@ ifeq ($(CONFIG_QCOM_TDLS),y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tdls.o endif +ifeq ($(CONFIG_WLAN_SYNC_TSF),y) +HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_tsf.o +endif + ifeq ($(CONFIG_MPC_UT_FRAMEWORK),y) HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_conc_ut.o endif @@ -671,11 +671,7 @@ BMI_INC := -I$(WLAN_ROOT)/$(BMI_DIR)/inc BMI_OBJS := $(BMI_DIR)/src/bmi.o \ $(BMI_DIR)/src/ol_fw.o -ifeq ($(CONFIG_FEATURE_BMI_2), y) -BMI_OBJS += $(BMI_DIR)/src/bmi_2.o -else BMI_OBJS += $(BMI_DIR)/src/bmi_1.o -endif ########### WMI ########### WMI_ROOT_DIR := wmi @@ -847,6 +843,23 @@ ifeq ($(CONFIG_MPC_UT_FRAMEWORK),y) WMA_OBJS += $(WMA_SRC_DIR)/wma_utils_ut.o endif +############## PLD ########## +PLD_DIR := core/pld +PLD_INC_DIR := $(PLD_DIR)/inc +PLD_SRC_DIR := $(PLD_DIR)/src + +PLD_INC := -I$(WLAN_ROOT)/$(PLD_INC_DIR) \ + -I$(WLAN_ROOT)/$(PLD_SRC_DIR) + +PLD_OBJS := $(PLD_SRC_DIR)/pld_common.o + +ifeq ($(CONFIG_PCI), y) +PLD_OBJS += $(PLD_SRC_DIR)/pld_pcie.o +endif +ifeq ($(CONFIG_ICNSS),y) +PLD_OBJS += $(PLD_SRC_DIR)/pld_snoc.o +endif + TARGET_INC := -I$(WLAN_ROOT)/target/inc LINUX_INC := -Iinclude/linux @@ -884,6 +897,8 @@ INCS += $(NLINK_INC) \ $(PTT_INC) \ $(WLAN_LOGGING_INC) +INCS += $(PLD_INC) + ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) INCS += $(PKTLOG_INC) endif @@ -917,6 +932,8 @@ OBJS += $(WLAN_LOGGING_OBJS) OBJS += $(NLINK_OBJS) OBJS += $(PTT_OBJS) +OBJS += $(PLD_OBJS) + ifeq ($(CONFIG_REMOVE_PKT_LOG), 0) OBJS += $(PKTLOG_OBJS) endif @@ -990,10 +1007,6 @@ CDEFINES += -DFEATURE_NAPI_DEBUG endif endif -ifeq ($(CONFIG_FEATURE_BMI_2), y) -CDEFINES += -DFEATURE_BMI_2 -endif - ifeq (y,$(findstring y,$(CONFIG_ARCH_MSM) $(CONFIG_ARCH_QCOM))) CDEFINES += -DMSM_PLATFORM endif @@ -1339,6 +1352,10 @@ ifeq ($(CONFIG_LINUX_QCMBR),y) CDEFINES += -DLINUX_QCMBR endif +# Enable featue sync tsf between multi devices +ifeq ($(CONFIG_WLAN_SYNC_TSF), y) +CDEFINES += -DWLAN_FEATURE_TSF +endif # Enable full rx re-order offload for adrastea ifeq (y, $(filter y, $(CONFIG_CNSS_ADRASTEA) $(CONFIG_ICNSS))) @@ -107,11 +107,15 @@ config WLAN_FEATURE_RX_WAKELOCK bool "Enable RX wake lock feature" default n -config FEATURE_LFR_SUBNET_DETECTION +config WLAN_SYNC_TSF + bool "Enable QCOM sync multi devices tsf feature" + default n + +config LFR_SUBNET_DETECTION bool "Enable LFR Subnet Change Detection" default n -config FEATURE_WLAN_MCC_TO_SCC_SWITCH +config MCC_TO_SCC_SWITCH bool "Enable MCC to SCC Switch Logic" default n diff --git a/config/WCNSS_qcom_cfg.ini b/config/WCNSS_qcom_cfg.ini index 8b05331feb13..da8550c68556 100644 --- a/config/WCNSS_qcom_cfg.ini +++ b/config/WCNSS_qcom_cfg.ini @@ -593,6 +593,10 @@ gEnableFastPath=1 # 1 - enable TSOEnable=1 +# Enable Large Receive Offload +# 0 - disable +# 1 - enable +LROEnable=1 END # Note: Configuration parser would not read anything past the END marker diff --git a/core/bmi/inc/ol_if_athvar.h b/core/bmi/inc/ol_if_athvar.h index cf0e1c81634c..1eb13f2f76de 100644 --- a/core/bmi/inc/ol_if_athvar.h +++ b/core/bmi/inc/ol_if_athvar.h @@ -45,7 +45,6 @@ #endif #include "ol_ctrl_addba_api.h" -typedef void *hif_handle_t; struct ol_version { uint32_t host_ver; @@ -55,13 +54,6 @@ struct ol_version { uint32_t abi_ver; }; -typedef enum _ol_target_status { - OL_TRGET_STATUS_CONNECTED = 0, /* target connected */ - OL_TRGET_STATUS_RESET, /* target got reset */ - OL_TRGET_STATUS_EJECT, /* target got ejected */ - OL_TRGET_STATUS_SUSPEND /*target got suspend */ -} ol_target_status; - enum ol_ath_tx_ecodes { TX_IN_PKT_INCR = 0, TX_OUT_HDR_COMPL, diff --git a/core/bmi/src/bmi.c b/core/bmi/src/bmi.c index 5752ccc0d6e9..fc9969d7d993 100644 --- a/core/bmi/src/bmi.c +++ b/core/bmi/src/bmi.c @@ -30,38 +30,6 @@ /* APIs visible to the driver */ -/* BMI_1 refers QCA6174 target; the ADDR is AXI addr */ -#define BMI_1_TEST_ADDR (0xa0000) -/* BMI_2 ; */ -#define BMI_2_TEST_ADDR (0x6E0000) -/* Enable BMI_TEST COMMANDs; The Value 0x09 is randomly choosen */ -#define BMI_TEST_ENABLE (0x09) - -#ifndef CONFIG_CNSS -#define SHOULD_RUN_BMI_TEST_COMMANDS false -#else -#define SHOULD_RUN_BMI_TEST_COMMANDS (BMI_TEST_ENABLE == cnss_get_bmi_setup()) -#endif - -static QDF_STATUS -bmi_command_test(uint32_t command, uint32_t address, uint8_t *data, - uint32_t length, struct ol_context *ol_ctx) -{ - switch (command) { - case BMI_NO_COMMAND: - return bmi_no_command(ol_ctx); - case BMI_WRITE_MEMORY: - return bmi_write_memory(address, data, length, ol_ctx); - case BMI_READ_MEMORY: - return bmi_read_memory(address, data, length, ol_ctx); - case BMI_EXECUTE: - return bmi_execute(address, (uint32_t *)data, ol_ctx); - default: - break; - } - return QDF_STATUS_SUCCESS; -} - QDF_STATUS bmi_init(struct ol_context *ol_ctx) { struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); @@ -214,43 +182,6 @@ bmi_get_target_info(struct bmi_target_info *targ_info, return QDF_STATUS_SUCCESS; } -#ifdef FEATURE_BMI_2 -static inline uint32_t bmi_get_test_addr(void) -{ - return BMI_2_TEST_ADDR; -} -#else -static inline uint32_t bmi_get_test_addr(void) -{ - return BMI_1_TEST_ADDR; -} -#endif - -/** - * run_bmi_test() - run some bmi tests - * @ol_ctx: bmi context - * - */ -static void run_bmi_test(struct ol_context *ol_ctx) -{ - uint8_t data[10], out[10]; - uint32_t address; - int32_t ret; - - ret = snprintf(data, 10, "ABCDEFGHI"); - BMI_DBG("ret:%d writing data:%s\n", ret, data); - address = bmi_get_test_addr(); - - if (bmi_init(ol_ctx) != QDF_STATUS_SUCCESS) { - BMI_WARN("BMI_INIT Failed; No Memory!"); - return; - } - bmi_command_test(BMI_NO_COMMAND, address, data, 9, ol_ctx); - bmi_command_test(BMI_WRITE_MEMORY, address, data, 9, ol_ctx); - bmi_command_test(BMI_READ_MEMORY, address, out, 9, ol_ctx); - BMI_DBG("Output:%s", out); -} - QDF_STATUS bmi_download_firmware(struct ol_context *ol_ctx) { struct hif_opaque_softc *scn = ol_ctx->scn; @@ -264,8 +195,6 @@ QDF_STATUS bmi_download_firmware(struct ol_context *ol_ctx) return QDF_STATUS_NOT_INITIALIZED; } - if (SHOULD_RUN_BMI_TEST_COMMANDS) - run_bmi_test(ol_ctx); return bmi_firmware_download(ol_ctx); } diff --git a/core/bmi/src/bmi_2.c b/core/bmi/src/bmi_2.c deleted file mode 100644 index 59c6dd605461..000000000000 --- a/core/bmi/src/bmi_2.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * copyright (c) 2014-2016 The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * 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. - */ - -/* - * This file was originally distributed by Qualcomm Atheros, Inc. - * under proprietary terms before Copyright ownership was assigned - * to the Linux Foundation. - */ -#include "i_bmi.h" -#include "cds_api.h" -/* This need to defined in firmware interface files. - * Defining here to address compilation issues. - * Will be deleted once firmware interface files for - * target are merged - */ -#define BMI_LOAD_IMAGE 18 - -QDF_STATUS -bmi_no_command(struct ol_context *ol_ctx) -{ - struct hif_opaque_softc *scn = ol_ctx->scn; - uint32_t cid; - int status; - uint32_t length; - uint8_t ret = 0; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - uint8_t *bmi_cmd_buff = info->bmi_cmd_buff; - uint8_t *bmi_rsp_buff = info->bmi_rsp_buff; - qdf_dma_addr_t cmd = info->bmi_cmd_da; - qdf_dma_addr_t rsp = info->bmi_rsp_da; - - if (info->bmi_done) { - BMI_ERR("Command disallowed: BMI DONE ALREADY"); - return QDF_STATUS_E_PERM; - } - - if (!bmi_cmd_buff || !bmi_rsp_buff) { - BMI_ERR("No Memory Allocated for BMI CMD/RSP Buffer"); - return QDF_STATUS_NOT_INITIALIZED; - } - cid = BMI_NO_COMMAND; - - qdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); - length = sizeof(ret); - - status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, sizeof(cid), - bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); - - if (status) { - BMI_ERR("Failed to write bmi no command status:%d", status); - return QDF_STATUS_E_FAILURE; - } - - qdf_mem_copy(&ret, bmi_rsp_buff, length); - if (ret != 0) { - BMI_ERR("bmi no command response error ret 0x%x", ret); - return QDF_STATUS_E_FAILURE; - } - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS -bmi_done_local(struct ol_context *ol_ctx) -{ - struct hif_opaque_softc *scn = ol_ctx->scn; - uint32_t cid; - int status; - uint32_t length; - uint8_t ret = 0; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - uint8_t *bmi_cmd_buff = info->bmi_cmd_buff; - uint8_t *bmi_rsp_buff = info->bmi_rsp_buff; - qdf_device_t qdf_dev = ol_ctx->qdf_dev; - qdf_dma_addr_t cmd = info->bmi_cmd_da; - qdf_dma_addr_t rsp = info->bmi_rsp_da; - - if (info->bmi_done) { - BMI_ERR("Command disallowed"); - return QDF_STATUS_E_PERM; - } - - if (!bmi_cmd_buff || !bmi_rsp_buff) { - BMI_ERR("No Memory Allocated for BMI CMD/RSP Buffer"); - return QDF_STATUS_NOT_INITIALIZED; - } - - if (!qdf_dev->dev) { - BMI_ERR("%s Invalid Device pointer", __func__); - return QDF_STATUS_NOT_INITIALIZED; - } - - cid = BMI_DONE; - - qdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); - length = sizeof(ret); - - status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, sizeof(cid), - bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); - - if (status) { - BMI_ERR("Failed to close BMI on target status:%d", status); - return QDF_STATUS_E_FAILURE; - } - qdf_mem_copy(&ret, bmi_rsp_buff, length); - - if (ret != 0) { - BMI_ERR("BMI DONE response failed:%d", ret); - return QDF_STATUS_E_FAILURE; - } - - if (info->bmi_cmd_buff) { - qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, - MAX_BMI_CMDBUF_SZ, - info->bmi_cmd_buff, info->bmi_cmd_da, 0); - info->bmi_cmd_buff = NULL; - info->bmi_cmd_da = 0; - } - - if (info->bmi_rsp_buff) { - qdf_mem_free_consistent(qdf_dev, qdf_dev->dev, - MAX_BMI_CMDBUF_SZ, - info->bmi_rsp_buff, info->bmi_rsp_da, 0); - info->bmi_rsp_buff = NULL; - info->bmi_rsp_da = 0; - } - - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS bmi_write_memory(uint32_t address, uint8_t *buffer, uint32_t length, - struct ol_context *ol_ctx) -{ - uint32_t cid; - int status; - uint32_t rsp_len; - uint8_t ret = 0; - uint32_t offset; - uint32_t remaining, txlen; - const uint32_t header = sizeof(cid) + sizeof(address) + sizeof(length); - uint8_t aligned_buffer[BMI_DATASZ_MAX]; - uint8_t *src; - struct hif_opaque_softc *scn = ol_ctx->scn; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - uint8_t *bmi_cmd_buff = info->bmi_cmd_buff; - uint8_t *bmi_rsp_buff = info->bmi_rsp_buff; - qdf_dma_addr_t cmd = info->bmi_cmd_da; - qdf_dma_addr_t rsp = info->bmi_rsp_da; - - if (info->bmi_done) { - BMI_ERR("Command disallowed"); - return QDF_STATUS_E_PERM; - } - - if (!bmi_cmd_buff || !bmi_rsp_buff) { - BMI_ERR("BMI Initialization is not happened"); - return QDF_STATUS_NOT_INITIALIZED; - } - - bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header)); - qdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + header); - - cid = BMI_WRITE_MEMORY; - rsp_len = sizeof(ret); - - remaining = length; - while (remaining) { - src = &buffer[length - remaining]; - if (remaining < (BMI_DATASZ_MAX - header)) { - if (remaining & 3) { - /* align it with 4 bytes */ - remaining = remaining + (4 - (remaining & 3)); - memcpy(aligned_buffer, src, remaining); - src = aligned_buffer; - } - txlen = remaining; - } else { - txlen = (BMI_DATASZ_MAX - header); - } - offset = 0; - qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); - offset += sizeof(cid); - qdf_mem_copy(&(bmi_cmd_buff[offset]), &address, - sizeof(address)); - offset += sizeof(address); - qdf_mem_copy(&(bmi_cmd_buff[offset]), &txlen, sizeof(txlen)); - offset += sizeof(txlen); - qdf_mem_copy(&(bmi_cmd_buff[offset]), src, txlen); - offset += txlen; - status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, - offset, bmi_rsp_buff, &rsp_len, - BMI_EXCHANGE_TIMEOUT_MS); - if (status) { - BMI_ERR("BMI Write Memory Failed status:%d", status); - return QDF_STATUS_E_FAILURE; - } - qdf_mem_copy(&ret, bmi_rsp_buff, rsp_len); - if (ret != 0) { - BMI_ERR("BMI Write memory response fail: %x", ret); - return QDF_STATUS_E_FAILURE; - } - remaining -= txlen; address += txlen; - } - - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS -bmi_read_memory(uint32_t address, uint8_t *buffer, - uint32_t length, struct ol_context *ol_ctx) -{ - struct hif_opaque_softc *scn = ol_ctx->scn; - uint32_t cid; - int status; - uint8_t ret = 0; - uint32_t offset; - uint32_t remaining, rxlen, rsp_len, total_len; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - uint8_t *bmi_cmd_buff = info->bmi_cmd_buff; - /* note we reuse the same buffer to receive on */ - uint8_t *bmi_rsp_buff = info->bmi_rsp_buff; - uint32_t size = sizeof(cid) + sizeof(address) + sizeof(length); - qdf_dma_addr_t cmd = info->bmi_cmd_da; - qdf_dma_addr_t rsp = info->bmi_rsp_da; - - if (info->bmi_done) { - BMI_ERR("Command disallowed"); - return QDF_STATUS_E_PERM; - } - if (!bmi_cmd_buff || !bmi_rsp_buff) { - BMI_ERR("BMI Initialization is not done"); - return QDF_STATUS_NOT_INITIALIZED; - } - - bmi_assert(BMI_COMMAND_FITS(BMI_DATASZ_MAX + size)); - qdf_mem_set(bmi_cmd_buff, 0, BMI_DATASZ_MAX + size); - qdf_mem_set(bmi_rsp_buff, 0, BMI_DATASZ_MAX + size); - - cid = BMI_READ_MEMORY; - rsp_len = sizeof(ret); - remaining = length; - - while (remaining) { - rxlen = (remaining < BMI_DATASZ_MAX - rsp_len) ? remaining : - (BMI_DATASZ_MAX - rsp_len); - offset = 0; - qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); - offset += sizeof(cid); - qdf_mem_copy(&(bmi_cmd_buff[offset]), &address, - sizeof(address)); - offset += sizeof(address); - qdf_mem_copy(&(bmi_cmd_buff[offset]), &rxlen, sizeof(rxlen)); - offset += sizeof(length); - - total_len = rxlen + rsp_len; - - status = hif_exchange_bmi_msg(scn, cmd, rsp, - bmi_cmd_buff, - offset, - bmi_rsp_buff, - &total_len, - BMI_EXCHANGE_TIMEOUT_MS); - - if (status) { - BMI_ERR("BMI Read memory failed status:%d", status); - return QDF_STATUS_E_FAILURE; - } - - qdf_mem_copy(&ret, bmi_rsp_buff, rsp_len); - - if (ret != 0) { - BMI_ERR("bmi read memory response fail %x", ret); - return QDF_STATUS_E_FAILURE; - } - - qdf_mem_copy(&buffer[length - remaining], - (uint8_t *)bmi_rsp_buff + rsp_len, rxlen); - remaining -= rxlen; address += rxlen; - } - - return QDF_STATUS_SUCCESS; -} - -QDF_STATUS -bmi_execute(uint32_t address, uint32_t *param, struct ol_context *ol_ctx) -{ - struct hif_opaque_softc *scn = ol_ctx->scn; - uint32_t cid; - int status; - uint32_t length; - uint8_t ret = 0; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - uint8_t *bmi_cmd_buff = info->bmi_cmd_buff; - uint8_t *bmi_rsp_buff = info->bmi_rsp_buff; - qdf_dma_addr_t cmd = info->bmi_cmd_da; - qdf_dma_addr_t rsp = info->bmi_rsp_da; - - if (info->bmi_done) { - BMI_ERR("Command disallowed"); - return QDF_STATUS_E_PERM; - } - - if (!bmi_cmd_buff || !bmi_rsp_buff) { - BMI_ERR("No Memory Allocated for bmi buffers"); - return QDF_STATUS_NOT_INITIALIZED; - } - - cid = BMI_EXECUTE; - - qdf_mem_copy(bmi_cmd_buff, &cid, sizeof(cid)); - length = sizeof(ret); - - status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, sizeof(cid), - bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); - - if (status) { - BMI_ERR("Failed to do BMI_EXECUTE status:%d", status); - return QDF_STATUS_E_FAILURE; - } - - qdf_mem_copy(&ret, bmi_rsp_buff, length); - - if (ret != 0) { - BMI_ERR("%s: ret 0x%x", __func__, ret); - return QDF_STATUS_E_FAILURE; - } - return QDF_STATUS_SUCCESS; -} - -static QDF_STATUS -bmi_load_image(dma_addr_t address, - uint32_t size, struct ol_context *ol_ctx) -{ - uint32_t cid; - QDF_STATUS status; - uint32_t offset; - uint32_t length; - uint8_t ret = 0; - struct hif_opaque_softc *scn = ol_ctx->scn; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - uint8_t *bmi_cmd_buff = info->bmi_cmd_buff; - uint8_t *bmi_rsp_buff = info->bmi_rsp_buff; - qdf_dma_addr_t cmd = info->bmi_cmd_da; - qdf_dma_addr_t rsp = info->bmi_rsp_da; - - uint32_t addr_h, addr_l; - - if (info->bmi_done) { - BMI_ERR("Command disallowed"); - return QDF_STATUS_E_PERM; - } - - if (!bmi_cmd_buff || !bmi_rsp_buff) { - BMI_ERR("No Memory Allocated for BMI CMD/RSP Buffer"); - return QDF_STATUS_NOT_INITIALIZED; - } - - bmi_assert(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address))); - qdf_mem_set(bmi_cmd_buff, 0, sizeof(cid) + sizeof(address)); - - - BMI_DBG("%s: Enter device: 0x%p, size %d", __func__, scn, size); - - cid = BMI_LOAD_IMAGE; - - offset = 0; - qdf_mem_copy(&(bmi_cmd_buff[offset]), &cid, sizeof(cid)); - offset += sizeof(cid); - addr_l = address & 0xffffffff; - addr_h = 0x00; - qdf_mem_copy(&(bmi_cmd_buff[offset]), &addr_l, sizeof(addr_l)); - offset += sizeof(addr_l); - qdf_mem_copy(&(bmi_cmd_buff[offset]), &addr_h, sizeof(addr_h)); - offset += sizeof(addr_h); - qdf_mem_copy(&(bmi_cmd_buff[offset]), &size, sizeof(size)); - offset += sizeof(size); - length = sizeof(ret); - - status = hif_exchange_bmi_msg(scn, cmd, rsp, bmi_cmd_buff, offset, - bmi_rsp_buff, &length, BMI_EXCHANGE_TIMEOUT_MS); - - if (status) { - BMI_ERR("BMI Load Image Failed; status:%d", status); - return QDF_STATUS_E_FAILURE; - } - - qdf_mem_copy(&ret, bmi_rsp_buff, length); - if (ret != 0) { - BMI_ERR("%s: ret 0x%x", __func__, ret); - return QDF_STATUS_E_FAILURE; - } - return QDF_STATUS_SUCCESS; -} - -static QDF_STATUS bmi_enable(struct ol_context *ol_ctx) -{ - struct hif_opaque_softc *scn = ol_ctx->scn; - struct bmi_target_info targ_info; - struct image_desc_info image_desc_info; - QDF_STATUS status; - struct hif_target_info *tgt_info; - struct bmi_info *info = GET_BMI_CONTEXT(ol_ctx); - - if (!scn) { - BMI_ERR("Invalid scn context"); - bmi_assert(0); - return QDF_STATUS_NOT_INITIALIZED; - } - - tgt_info = hif_get_target_info_handle(scn); - - if (info->bmi_cmd_buff == NULL || info->bmi_rsp_buff == NULL) { - BMI_ERR("bmi_open failed!"); - return QDF_STATUS_NOT_INITIALIZED; - } - - status = bmi_get_target_info(&targ_info, ol_ctx); - if (status != QDF_STATUS_SUCCESS) - return status; - - BMI_DBG("%s: target type 0x%x, target ver 0x%x", __func__, - targ_info.target_type, targ_info.target_ver); - - tgt_info->target_type = targ_info.target_type; - tgt_info->target_version = targ_info.target_ver; - - if (cnss_get_fw_image(&image_desc_info) != 0) { - BMI_ERR("Failed to get fw image"); - return QDF_STATUS_E_FAILURE; - } - - status = bmi_load_image(image_desc_info.bdata_addr, - image_desc_info.bdata_size, - ol_ctx); - if (status != QDF_STATUS_SUCCESS) { - BMI_ERR("Load board data failed! status:%d", status); - return status; - } - - status = bmi_load_image(image_desc_info.fw_addr, - image_desc_info.fw_size, - ol_ctx); - if (status != QDF_STATUS_SUCCESS) - BMI_ERR("Load fw image failed! status:%d", status); - - return status; -} - -QDF_STATUS bmi_firmware_download(struct ol_context *ol_ctx) -{ - QDF_STATUS status; - - if (NO_BMI) - return QDF_STATUS_SUCCESS; - - status = bmi_init(ol_ctx); - if (status != QDF_STATUS_SUCCESS) { - BMI_ERR("BMI_INIT Failed status:%d", status); - goto end; - } - - status = bmi_enable(ol_ctx); - if (status != QDF_STATUS_SUCCESS) { - BMI_ERR("BMI_ENABLE failed status:%d\n", status); - goto err_bmi_enable; - } - - return status; -err_bmi_enable: - bmi_cleanup(ol_ctx); -end: - return status; -} diff --git a/core/bmi/src/i_bmi.h b/core/bmi/src/i_bmi.h index ae92ca97f93b..1cdc0d2896ef 100644 --- a/core/bmi/src/i_bmi.h +++ b/core/bmi/src/i_bmi.h @@ -40,12 +40,24 @@ #include "bmi.h" #include "ol_fw.h" +#ifdef CONFIG_CNSS +#define QCA_FIRMWARE_FILE fw_files->image_file +#define QCA_UTF_FIRMWARE_FILE fw_files->utf_file +#define QCA_BOARD_DATA_FILE fw_files->board_data +#define QCA_UTF_BOARD_DATA_FILE fw_files->utf_board_data +#define QCA_OTP_FILE fw_files->otp_data +#define QCA_SETUP_FILE NULL +#define QCA_FIRMWARE_EPPING_FILE fw_files->epping_file +#else #define QCA_FIRMWARE_FILE "athwlan.bin" #define QCA_UTF_FIRMWARE_FILE "utf.bin" #define QCA_BOARD_DATA_FILE "fakeboar.bin" +#define QCA_UTF_BOARD_DATA_FILE "fakeboar.bin" #define QCA_OTP_FILE "otp.bin" #define QCA_SETUP_FILE "athsetup.bin" #define QCA_FIRMWARE_EPPING_FILE "epping.bin" +#endif + /* * Note that not all the register locations are accessible. * A list of accessible target registers are specified with @@ -187,6 +199,8 @@ QDF_STATUS bmi_firmware_download(struct ol_context *ol_ctx); QDF_STATUS bmi_done_local(struct ol_context *ol_ctx); QDF_STATUS ol_download_firmware(struct ol_context *ol_ctx); QDF_STATUS ol_configure_target(struct ol_context *ol_ctx); +QDF_STATUS bmi_sign_stream_start(uint32_t address, uint8_t *buffer, + uint32_t length, struct ol_context *ol_ctx); void ramdump_work_handler(void *arg); struct ol_config_info *ol_get_ini_handle(struct ol_context *ol_ctx); #endif diff --git a/core/bmi/src/ol_fw.c b/core/bmi/src/ol_fw.c index e47ff72fa311..3314d75c7e36 100644 --- a/core/bmi/src/ol_fw.c +++ b/core/bmi/src/ol_fw.c @@ -135,6 +135,18 @@ end: } #endif +#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT +#define SIGNED_SPLIT_BINARY_VALUE true +#else +#define SIGNED_SPLIT_BINARY_VALUE false +#endif + +#ifdef CONFIG_CNSS +#define CONFIG_CNSS_DEFINED true +#else +#define CONFIG_CNSS_DEFINED false +#endif + static int __ol_transfer_bin_file(struct ol_context *ol_ctx, ATH_BIN_FILE file, uint32_t address, bool compressed) @@ -146,15 +158,15 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, ATH_BIN_FILE file, uint32_t fw_entry_size; uint8_t *temp_eeprom; uint32_t board_data_size; -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT bool bin_sign = false; int bin_off, bin_len; SIGN_HEADER_T *sign_header; -#endif struct hif_target_info *tgt_info = hif_get_target_info_handle(scn); uint32_t target_type = tgt_info->target_type; #if defined(CONFIG_CNSS) + /* fw_files variable used in filename assignment macros */ struct bmi_info *bmi_ctx = GET_BMI_CONTEXT(ol_ctx); + struct cnss_fw_files *fw_files = &bmi_ctx->fw_files; #endif qdf_device_t qdf_dev = ol_ctx->qdf_dev; @@ -163,95 +175,69 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, ATH_BIN_FILE file, BMI_ERR("%s: Unknown file type", __func__); return -1; case ATH_OTP_FILE: -#if defined(CONFIG_CNSS) - filename = bmi_ctx->fw_files.otp_data; -#else filename = QCA_OTP_FILE; -#endif -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - bin_sign = true; -#endif + if (SIGNED_SPLIT_BINARY_VALUE) + bin_sign = true; + break; case ATH_FIRMWARE_FILE: - if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { -#if defined(CONFIG_CNSS) - filename = bmi_ctx->fw_files.epping_file; -#else + if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) { filename = QCA_FIRMWARE_EPPING_FILE; -#endif BMI_INFO("%s: Loading epping firmware file %s", __func__, filename); break; } #ifdef QCA_WIFI_FTM if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) { -#if defined(CONFIG_CNSS) - filename = bmi_ctx->fw_files.utf_file; -#else filename = QCA_UTF_FIRMWARE_FILE; -#endif -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - bin_sign = true; -#endif + if (SIGNED_SPLIT_BINARY_VALUE) + bin_sign = true; BMI_INFO("%s: Loading firmware file %s", __func__, filename); break; } #endif -#if defined(CONFIG_CNSS) - filename = bmi_ctx->fw_files.image_file; -#else filename = QCA_FIRMWARE_FILE; -#endif -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - bin_sign = true; -#endif + if (SIGNED_SPLIT_BINARY_VALUE) + bin_sign = true; break; case ATH_PATCH_FILE: BMI_INFO("%s: no Patch file defined", __func__); return 0; case ATH_BOARD_DATA_FILE: + #ifdef QCA_WIFI_FTM if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) { -#if defined(CONFIG_CNSS) - filename = bmi_ctx->fw_files.utf_board_data; -#else - filename = QCA_BOARD_DATA_FILE; -#endif -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - bin_sign = true; -#endif + filename = QCA_UTF_BOARD_DATA_FILE; + + if (SIGNED_SPLIT_BINARY_VALUE) + bin_sign = true; + BMI_INFO("%s: Loading board data file %s", __func__, filename); break; } #endif /* QCA_WIFI_FTM */ -#if defined(CONFIG_CNSS) - filename = bmi_ctx->fw_files.board_data; -#else filename = QCA_BOARD_DATA_FILE; -#endif -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - bin_sign = false; -#endif + + if (SIGNED_SPLIT_BINARY_VALUE) + bin_sign = false; + break; case ATH_SETUP_FILE: - if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE && - !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { -#ifdef CONFIG_CNSS + if (CONFIG_CNSS_DEFINED || + cds_get_conparam() == QDF_GLOBAL_FTM_MODE || + QDF_IS_EPPING_ENABLED(cds_get_conparam())) { BMI_INFO("%s: no Setup file defined", __func__); return -1; -#else + } else { filename = QCA_SETUP_FILE; -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - bin_sign = true; -#endif + + if (SIGNED_SPLIT_BINARY_VALUE) + bin_sign = true; + BMI_INFO("%s: Loading setup file %s", __func__, filename); -#endif /* CONFIG_CNSS */ - } else { - BMI_INFO("%s: no Setup file needed", __func__); - return -1; } break; } @@ -362,8 +348,8 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, ATH_BIN_FILE file, fw_entry_size = board_data_size; } } -#ifdef QCA_SIGNED_SPLIT_BINARY_SUPPORT - if (bin_sign) { + + if (bin_sign && SIGNED_SPLIT_BINARY_VALUE) { uint32_t chip_id; if (fw_entry_size < sizeof(SIGN_HEADER_T)) { @@ -417,7 +403,7 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, ATH_BIN_FILE file, } } - if (bin_sign) { + if (bin_sign && SIGNED_SPLIT_BINARY_VALUE) { bin_off += bin_len; bin_len = sign_header->total_len - sign_header->rampatch_len; @@ -429,23 +415,6 @@ __ol_transfer_bin_file(struct ol_context *ol_ctx, ATH_BIN_FILE file, BMI_ERR("sign stream error"); } } -#else - if (compressed) { - status = bmi_fast_download(address, - (uint8_t *) fw_entry->data, - fw_entry_size, ol_ctx); - } else { - if (file == ATH_BOARD_DATA_FILE && fw_entry->data) { - status = bmi_write_memory(address, - (uint8_t *) temp_eeprom, - fw_entry_size, ol_ctx); - } else { - status = bmi_write_memory(address, - (uint8_t *) fw_entry->data, - fw_entry_size, ol_ctx); - } - } -#endif /* QCA_SIGNED_SPLIT_BINARY_SUPPORT */ end: if (temp_eeprom) @@ -621,8 +590,7 @@ void ol_target_failure(void *instance, QDF_STATUS status) struct ol_config_info *ini_cfg = ol_get_ini_handle(ol_ctx); int ret; #endif - ol_target_status target_status = - hif_get_target_status(scn); + enum hif_target_status target_status = hif_get_target_status(scn); if (hif_get_bus_type(scn) == QDF_BUS_TYPE_SNOC) { BMI_ERR("SNOC doesn't suppor this code path!"); @@ -631,12 +599,12 @@ void ol_target_failure(void *instance, QDF_STATUS status) qdf_event_set(&wma->recovery_event); - if (OL_TRGET_STATUS_RESET == target_status) { + if (TARGET_STATUS_RESET == target_status) { BMI_ERR("Target is already asserted, ignore!"); return; } - hif_set_target_status(scn, OL_TRGET_STATUS_RESET); + hif_set_target_status(scn, TARGET_STATUS_RESET); if (cds_is_driver_recovering()) { BMI_ERR("%s: Recovery in progress, ignore!\n", __func__); @@ -1296,9 +1264,7 @@ QDF_STATUS ol_download_firmware(struct ol_context *ol_ctx) /* Execute the OTP code only if entry found and downloaded */ if (status == EOK) { param = 0; -#ifndef FEATURE_BMI_2 bmi_execute(address, ¶m, ol_ctx); -#endif } else if (status < 0) { return status; } @@ -1307,9 +1273,7 @@ QDF_STATUS ol_download_firmware(struct ol_context *ol_ctx) if (ol_transfer_bin_file(ol_ctx, ATH_SETUP_FILE, BMI_SEGMENTED_WRITE_ADDR, true) == EOK) { param = 0; -#ifndef FEATURE_BMI_2 bmi_execute(address, ¶m, ol_ctx); -#endif } /* Download Target firmware @@ -1332,9 +1296,7 @@ QDF_STATUS ol_download_firmware(struct ol_context *ol_ctx) (uint8_t *) &address, 4, ol_ctx); } - if (ini_cfg->enable_uart_print || - (WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && - WLAN_IS_EPPING_FW_UART(cds_get_conparam()))) { + if (ini_cfg->enable_uart_print) { switch (target_version) { case AR6004_VERSION_REV1_3: param = 11; diff --git a/core/cds/inc/cds_api.h b/core/cds/inc/cds_api.h index 103514657291..5b85fa1b0a48 100644 --- a/core/cds/inc/cds_api.h +++ b/core/cds/inc/cds_api.h @@ -231,15 +231,37 @@ void cds_set_multicast_logging(uint8_t value); uint8_t cds_is_multicast_logging(void); QDF_STATUS cds_set_log_completion(uint32_t is_fatal, uint32_t type, - uint32_t sub_type); -void cds_get_log_completion(uint32_t *is_fatal, + uint32_t sub_type, + bool recovery_needed); +void cds_get_and_reset_log_completion(uint32_t *is_fatal, uint32_t *type, - uint32_t *sub_type); + uint32_t *sub_type, + bool *recovery_needed); bool cds_is_log_report_in_progress(void); +bool cds_is_fatal_event_enabled(void); +uint32_t cds_get_log_indicator(void); +void cds_set_fatal_event(bool value); +void cds_wlan_flush_host_logs_for_fatal(void); + void cds_init_log_completion(void); void cds_deinit_log_completion(void); QDF_STATUS cds_flush_logs(uint32_t is_fatal, uint32_t indicator, - uint32_t reason_code); + uint32_t reason_code, + bool dump_mac_trace, + bool recovery_needed); void cds_logging_set_fw_flush_complete(void); + +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void cds_tdls_tx_rx_mgmt_event(uint8_t event_id, uint8_t tx_rx, + uint8_t type, uint8_t sub_type, uint8_t *peer_mac); +#else +static inline +void cds_tdls_tx_rx_mgmt_event(uint8_t event_id, uint8_t tx_rx, + uint8_t type, uint8_t sub_type, uint8_t *peer_mac) + +{ +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + #endif /* if !defined __CDS_API_H */ diff --git a/core/cds/inc/cds_concurrency.h b/core/cds/inc/cds_concurrency.h index 45e37f8b0f94..fd44258ef48f 100644 --- a/core/cds/inc/cds_concurrency.h +++ b/core/cds/inc/cds_concurrency.h @@ -172,6 +172,18 @@ enum cds_con_mode { }; /** + * enum cds_mac_use - MACs that are used + * @CDS_MAC0: Only MAC0 is used + * @CDS_MAC1: Only MAC1 is used + * @CDS_MAC0_AND_MAC1: Both MAC0 and MAC1 are used + */ +enum cds_mac_use { + CDS_MAC0 = 1, + CDS_MAC1 = 2, + CDS_MAC0_AND_MAC1 = 3 +}; + +/** * enum cds_pcl_type - Various types of Preferred channel list (PCL). * * @CDS_NONE: No channel preference @@ -481,8 +493,8 @@ enum cds_two_connection_mode { * @CDS_NOP: No action * @CDS_DBS: switch to DBS mode * @CDS_DBS_DOWNGRADE: switch to DBS mode & downgrade to 1x1 - * @CDS_MCC: switch to MCC/SCC mode - * @CDS_MCC_UPGRADE: switch to MCC/SCC mode & upgrade to 2x2 + * @CDS_SINGLE_MAC: switch to MCC/SCC mode + * @CDS_SINGLE_MAC_UPGRADE: switch to MCC/SCC mode & upgrade to 2x2 * @CDS_MAX_CONC_PRIORITY_MODE: Max place holder * * These are generic IDs that identify the various roles @@ -492,8 +504,8 @@ enum cds_conc_next_action { CDS_NOP = 0, CDS_DBS, CDS_DBS_DOWNGRADE, - CDS_MCC, - CDS_MCC_UPGRADE, + CDS_SINGLE_MAC, + CDS_SINGLE_MAC_UPGRADE, CDS_MAX_CONC_NEXT_ACTION }; @@ -540,8 +552,6 @@ struct cds_conc_connection_info { bool in_use; }; -enum cds_conc_next_action cds_get_pref_hw_mode_for_chan(uint32_t vdev_id, - uint32_t target_channel); bool cds_is_connection_in_progress(void); void cds_dump_concurrency_info(void); void cds_set_concurrency_mode(enum tQDF_ADAPTER_MODE mode); @@ -698,7 +708,7 @@ static inline struct cds_conc_connection_info *cds_get_conn_info(uint32_t *len) enum cds_con_mode cds_convert_device_mode_to_qdf_type( enum tQDF_ADAPTER_MODE device_mode); -QDF_STATUS cds_soc_set_hw_mode(uint32_t session_id, +QDF_STATUS cds_pdev_set_hw_mode(uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, @@ -746,4 +756,8 @@ QDF_STATUS cds_get_pcl_for_existing_conn(enum cds_con_mode mode, uint8_t *pcl_ch, uint32_t *len, uint8_t *weight_list, uint32_t weight_len); QDF_STATUS cds_get_valid_chan_weights(struct sir_pcl_chan_weights *weight); +QDF_STATUS cds_set_hw_mode_on_channel_switch(uint8_t session_id); +void cds_set_do_hw_mode_change_flag(bool flag); +bool cds_is_hw_mode_change_after_vdev_up(void); +void cds_dump_connection_status_info(void); #endif /* __CDS_CONCURRENCY_H */ diff --git a/core/cds/inc/cds_packet.h b/core/cds/inc/cds_packet.h index f63e9033345c..e85ebb3d34a6 100644 --- a/core/cds/inc/cds_packet.h +++ b/core/cds/inc/cds_packet.h @@ -76,42 +76,37 @@ uint8_t cds_pkt_get_proto_type (struct sk_buff *skb, uint8_t tracking_map, uint8_t dot11_type); #ifdef QCA_PKT_PROTO_TRACE -/*--------------------------------------------------------------------------- - -* brief cds_pkt_trace_buf_update() - - Update storage buffer with interest event string - -* event_string Event String may packet type or outstanding event - - ---------------------------------------------------------------------------*/ +/** + * cds_pkt_trace_buf_update() - Update storage buffer with interest event string + * @event_string: string may be a packet type or an outstanding event + * + * Return: none + */ void cds_pkt_trace_buf_update(char *event_string); -/*--------------------------------------------------------------------------- - -* brief cds_pkt_trace_buf_dump() - - Dump stored information into kernel log - - ---------------------------------------------------------------------------*/ +/** + * cds_pkt_trace_buf_dump() - Dump stored information into kernel log + * + * Return: none + */ void cds_pkt_trace_buf_dump(void); -/*--------------------------------------------------------------------------- - -* brief cds_pkt_proto_trace_init() - - Initialize protocol trace functionality, allocate required resource - - ---------------------------------------------------------------------------*/ +/** + * cds_pkt_proto_trace_init() - Initialize protocol trace functionality + * + * Return: none + */ void cds_pkt_proto_trace_init(void); -/*--------------------------------------------------------------------------- - -* brief cds_pkt_proto_trace_close() - - Free required resource - - ---------------------------------------------------------------------------*/ -void cds_pkt_proto_trace_close(void); +/** + * cds_pkt_proto_trace_deinit() - Free protocol trace buffer resource + * + * Return: none + */ +void cds_pkt_proto_trace_deinit(void); #else static inline void cds_pkt_proto_trace_init(void) { } -static inline void cds_pkt_proto_trace_close(void) {} +static inline void cds_pkt_proto_trace_deinit(void) {} #endif /* QCA_PKT_PROTO_TRACE */ /** diff --git a/core/cds/inc/cds_regdomain.h b/core/cds/inc/cds_regdomain.h index 447eec39821a..9fc4d744d63d 100644 --- a/core/cds/inc/cds_regdomain.h +++ b/core/cds/inc/cds_regdomain.h @@ -290,6 +290,7 @@ enum country_code { CTRY_JAPAN49 = 4049, CTRY_JAPAN55 = 4055, CTRY_JAPAN56 = 4056, + CTRY_XA = 4100, }; enum reg_domain { diff --git a/core/cds/inc/cds_sched.h b/core/cds/inc/cds_sched.h index 46908e6701f6..cc082411e125 100644 --- a/core/cds/inc/cds_sched.h +++ b/core/cds/inc/cds_sched.h @@ -209,6 +209,7 @@ typedef struct _cds_sched_context { * @indicator: Source of bug report * @reason_code: Reason code for bug report * @is_report_in_progress: If bug report is in progress + * @recovery_needed: if recovery is needed after report completion * * This structure internally stores the log related params */ @@ -217,6 +218,7 @@ struct cds_log_complete { uint32_t indicator; uint32_t reason_code; bool is_report_in_progress; + bool recovery_needed; }; /* @@ -291,6 +293,8 @@ typedef struct _cds_context_type { #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH void (*sap_restart_chan_switch_cb)(void *, uint32_t, uint32_t); #endif + bool do_hw_mode_change; + bool enable_fatal_event; } cds_context_type, *p_cds_contextType; /*--------------------------------------------------------------------------- diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index cc950b32ae7b..e0648122ad8d 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -130,6 +130,36 @@ void cds_deinit(void) return; } +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * cds_tdls_tx_rx_mgmt_event()- send tdls mgmt rx tx event + * @event_id: event id + * @tx_rx: tx or rx + * @type: type of frame + * @action_sub_type: action frame type + * @peer_mac: peer mac + * + * This Function sends tdls mgmt rx tx diag event + * + * Return: void. + */ +void cds_tdls_tx_rx_mgmt_event(uint8_t event_id, uint8_t tx_rx, + uint8_t type, uint8_t action_sub_type, uint8_t *peer_mac) +{ + WLAN_HOST_DIAG_EVENT_DEF(tdls_tx_rx_mgmt, + struct host_event_tdls_tx_rx_mgmt); + + tdls_tx_rx_mgmt.event_id = event_id; + tdls_tx_rx_mgmt.tx_rx = tx_rx; + tdls_tx_rx_mgmt.type = type; + tdls_tx_rx_mgmt.action_sub_type = action_sub_type; + qdf_mem_copy(tdls_tx_rx_mgmt.peer_mac, + peer_mac, CDS_MAC_ADDRESS_LEN); + WLAN_HOST_DIAG_EVENT_REPORT(&tdls_tx_rx_mgmt, + EVENT_WLAN_TDLS_TX_RX_MGMT); +} +#endif + #ifdef WLAN_FEATURE_NAN /** * cds_set_nan_enable() - set nan enable flag in mac open param @@ -193,6 +223,9 @@ QDF_STATUS cds_open(void) /* Initialize bug reporting structure */ cds_init_log_completion(); + /* Initialize protocol trace functionality */ + cds_pkt_proto_trace_init(); + /* Initialize the probe event */ if (qdf_event_create(&gp_cds_context->ProbeEvent) != QDF_STATUS_SUCCESS) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_FATAL, @@ -823,6 +856,9 @@ QDF_STATUS cds_close(v_CONTEXT_t cds_context) QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); } + /* De-Initialize protocol trace functionality */ + cds_pkt_proto_trace_deinit(); + cds_deinit_log_completion(); gp_cds_context->pHDDContext = NULL; @@ -1314,11 +1350,15 @@ QDF_STATUS cds_mq_post_message(CDS_MQ_ID msgQueueId, cds_msg_t *pMsg) if (NULL == pMsgWrapper) { debug_count = atomic_inc_return(&cds_wrapper_empty_count); - if (1 == debug_count) + if (1 == debug_count) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: CDS Core run out of message wrapper %d", __func__, debug_count); - + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_ONLY, + WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, + true, false); + } if (CDS_WRAPPER_MAX_FAIL_COUNT == debug_count) QDF_BUG(0); @@ -1548,6 +1588,9 @@ QDF_STATUS cds_get_vdev_types(enum tQDF_ADAPTER_MODE mode, uint32_t *type, case QDF_IBSS_MODE: *type = WMI_VDEV_TYPE_IBSS; break; + case QDF_MONITOR_MODE: + *type = WMI_VDEV_TYPE_MONITOR; + break; default: QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "Invalid device mode %d", mode); @@ -1565,11 +1608,7 @@ QDF_STATUS cds_get_vdev_types(enum tQDF_ADAPTER_MODE mode, uint32_t *type, */ void cds_flush_work(void *work) { -#if defined (CONFIG_CNSS) - cnss_flush_work(work); -#elif defined (WLAN_OPEN_SOURCE) cancel_work_sync(work); -#endif } /** @@ -1580,11 +1619,7 @@ void cds_flush_work(void *work) */ void cds_flush_delayed_work(void *dwork) { -#if defined (CONFIG_CNSS) - cnss_flush_delayed_work(dwork); -#elif defined (WLAN_OPEN_SOURCE) cancel_delayed_work_sync(dwork); -#endif } /** @@ -1663,15 +1698,10 @@ void cds_trigger_recovery(void) uint64_t cds_get_monotonic_boottime(void) { -#ifdef CONFIG_CNSS struct timespec ts; - cnss_get_monotonic_boottime(&ts); + get_monotonic_boottime(&ts); return ((uint64_t) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); -#else - return ((uint64_t)qdf_system_ticks_to_msecs(qdf_system_ticks()) * - 1000); -#endif } /** @@ -1891,6 +1921,7 @@ void cds_deinit_log_completion(void) * @is_fatal: Indicates if the event triggering bug report is fatal or not * @indicator: Source which trigerred the bug report * @reason_code: Reason for triggering bug report + * @recovery_needed: If recovery is needed after bug report * * This function is used to set the logging parameters based on the * caller @@ -1899,7 +1930,8 @@ void cds_deinit_log_completion(void) */ QDF_STATUS cds_set_log_completion(uint32_t is_fatal, uint32_t indicator, - uint32_t reason_code) + uint32_t reason_code, + bool recovery_needed) { p_cds_contextType p_cds_context; @@ -1914,24 +1946,27 @@ QDF_STATUS cds_set_log_completion(uint32_t is_fatal, p_cds_context->log_complete.is_fatal = is_fatal; p_cds_context->log_complete.indicator = indicator; p_cds_context->log_complete.reason_code = reason_code; + p_cds_context->log_complete.recovery_needed = recovery_needed; p_cds_context->log_complete.is_report_in_progress = true; qdf_spinlock_release(&p_cds_context->bug_report_lock); return QDF_STATUS_SUCCESS; } /** - * cds_get_log_completion() - Get the logging related params + * cds_get_and_reset_log_completion() - Get and reset logging related params * @is_fatal: Indicates if the event triggering bug report is fatal or not * @indicator: Source which trigerred the bug report * @reason_code: Reason for triggering bug report + * @recovery_needed: If recovery is needed after bug report * * This function is used to get the logging related parameters * * Return: None */ -void cds_get_log_completion(uint32_t *is_fatal, +void cds_get_and_reset_log_completion(uint32_t *is_fatal, uint32_t *indicator, - uint32_t *reason_code) + uint32_t *reason_code, + bool *recovery_needed) { p_cds_contextType p_cds_context; @@ -1946,7 +1981,14 @@ void cds_get_log_completion(uint32_t *is_fatal, *is_fatal = p_cds_context->log_complete.is_fatal; *indicator = p_cds_context->log_complete.indicator; *reason_code = p_cds_context->log_complete.reason_code; + *recovery_needed = p_cds_context->log_complete.recovery_needed; + + /* reset */ + p_cds_context->log_complete.indicator = WLAN_LOG_INDICATOR_UNUSED; + p_cds_context->log_complete.is_fatal = WLAN_LOG_TYPE_NON_FATAL; p_cds_context->log_complete.is_report_in_progress = false; + p_cds_context->log_complete.reason_code = WLAN_LOG_REASON_CODE_UNUSED; + p_cds_context->log_complete.recovery_needed = false; qdf_spinlock_release(&p_cds_context->bug_report_lock); } @@ -1971,10 +2013,79 @@ bool cds_is_log_report_in_progress(void) } /** + * cds_is_fatal_event_enabled() - Return if fatal event is enabled + * + * Return true if fatal event is enabled. + */ +bool cds_is_fatal_event_enabled(void) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return false; + } + + + return p_cds_context->enable_fatal_event; +} + +/** + * cds_get_log_indicator() - Get the log flush indicator + * + * This function is used to get the log flush indicator + * + * Return: log indicator + */ +uint32_t cds_get_log_indicator(void) +{ + p_cds_contextType p_cds_context; + uint32_t indicator; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return WLAN_LOG_INDICATOR_UNUSED; + } + + if (cds_is_load_or_unload_in_progress() || + cds_is_driver_recovering()) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: vos context initialization is in progress" + , __func__); + return WLAN_LOG_INDICATOR_UNUSED; + } + + qdf_spinlock_acquire(&p_cds_context->bug_report_lock); + indicator = p_cds_context->log_complete.indicator; + qdf_spinlock_release(&p_cds_context->bug_report_lock); + return indicator; +} + +/** + * cds_wlan_flush_host_logs_for_fatal() - Wrapper to flush host logs + * + * This function is used to send signal to the logger thread to + * flush the host logs. + * + * Return: None + * + */ +void cds_wlan_flush_host_logs_for_fatal(void) +{ + wlan_flush_host_logs_for_fatal(); +} + +/** * cds_flush_logs() - Report fatal event to userspace * @is_fatal: Indicates if the event triggering bug report is fatal or not * @indicator: Source which trigerred the bug report * @reason_code: Reason for triggering bug report + * @dump_mac_trace: If mac trace are needed in logs. + * @recovery_needed: If recovery is needed after bug report * * This function sets the log related params and send the WMI command to the * FW to flush its logs. On receiving the flush completion event from the FW @@ -1984,7 +2095,9 @@ bool cds_is_log_report_in_progress(void) */ QDF_STATUS cds_flush_logs(uint32_t is_fatal, uint32_t indicator, - uint32_t reason_code) + uint32_t reason_code, + bool dump_mac_trace, + bool recovery_needed) { uint32_t ret; QDF_STATUS status; @@ -1997,6 +2110,17 @@ QDF_STATUS cds_flush_logs(uint32_t is_fatal, "%s: cds context is Invalid", __func__); return QDF_STATUS_E_FAILURE; } + if (!p_cds_context->enable_fatal_event) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: Fatal event not enabled", __func__); + return QDF_STATUS_E_FAILURE; + } + if (cds_is_load_or_unload_in_progress() || + cds_is_driver_recovering()) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: un/Load/SSR in progress", __func__); + return QDF_STATUS_E_FAILURE; + } if (cds_is_log_report_in_progress() == true) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, @@ -2005,17 +2129,26 @@ QDF_STATUS cds_flush_logs(uint32_t is_fatal, return QDF_STATUS_E_FAILURE; } - status = cds_set_log_completion(is_fatal, indicator, reason_code); + status = cds_set_log_completion(is_fatal, indicator, + reason_code, recovery_needed); if (QDF_STATUS_SUCCESS != status) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Failed to set log trigger params", __func__); return QDF_STATUS_E_FAILURE; } - QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s: Triggering bug report: type:%d, indicator=%d reason_code=%d", __func__, is_fatal, indicator, reason_code); + if (dump_mac_trace) + qdf_trace_dump_all(p_cds_context->pMACContext, 0, 0, 500, 0); + + if (WLAN_LOG_INDICATOR_HOST_ONLY == indicator) { + cds_wlan_flush_host_logs_for_fatal(); + return QDF_STATUS_SUCCESS; + } + ret = sme_send_flush_logs_cmd_to_fw(p_cds_context->pMACContext); if (0 != ret) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, @@ -2040,3 +2173,23 @@ void cds_logging_set_fw_flush_complete(void) { wlan_logging_set_fw_flush_complete(); } + +/** + * cds_set_fatal_event() - set fatal event status + * @value: pending statue to set + * + * Return: None + */ +void cds_set_fatal_event(bool value) +{ + p_cds_contextType p_cds_context; + + p_cds_context = cds_get_global_context(); + if (!p_cds_context) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "%s: cds context is Invalid", __func__); + return; + } + p_cds_context->enable_fatal_event = value; +} + diff --git a/core/cds/src/cds_concurrency.c b/core/cds/src/cds_concurrency.c index f211ace0dfc5..bf67f59c75c2 100644 --- a/core/cds/src/cds_concurrency.c +++ b/core/cds/src/cds_concurrency.c @@ -1927,9 +1927,9 @@ bool cds_is_sta_connection_pending(void) return false; } - spin_lock(&hdd_ctx->sta_update_info_lock); + qdf_spin_lock(&hdd_ctx->sta_update_info_lock); status = hdd_ctx->is_sta_connection_pending; - spin_unlock(&hdd_ctx->sta_update_info_lock); + qdf_spin_unlock(&hdd_ctx->sta_update_info_lock); return status; } @@ -1952,9 +1952,9 @@ void cds_change_sta_conn_pending_status(bool value) return; } - spin_lock(&hdd_ctx->sta_update_info_lock); + qdf_spin_lock(&hdd_ctx->sta_update_info_lock); hdd_ctx->is_sta_connection_pending = value; - spin_unlock(&hdd_ctx->sta_update_info_lock); + qdf_spin_unlock(&hdd_ctx->sta_update_info_lock); } /** @@ -1976,9 +1976,9 @@ static bool cds_is_sap_restart_required(void) return false; } - spin_lock(&hdd_ctx->sap_update_info_lock); + qdf_spin_lock(&hdd_ctx->sap_update_info_lock); status = hdd_ctx->is_sap_restart_required; - spin_unlock(&hdd_ctx->sap_update_info_lock); + qdf_spin_unlock(&hdd_ctx->sap_update_info_lock); return status; } @@ -2001,9 +2001,9 @@ void cds_change_sap_restart_required_status(bool value) return; } - spin_lock(&hdd_ctx->sap_update_info_lock); + qdf_spin_lock(&hdd_ctx->sap_update_info_lock); hdd_ctx->is_sap_restart_required = value; - spin_unlock(&hdd_ctx->sap_update_info_lock); + qdf_spin_unlock(&hdd_ctx->sap_update_info_lock); } /** @@ -2085,6 +2085,8 @@ static void cds_update_conc_list(uint32_t conn_index, conc_connection_list[conn_index].original_nss = original_nss; conc_connection_list[conn_index].vdev_id = vdev_id; conc_connection_list[conn_index].in_use = in_use; + + cds_dump_connection_status_info(); } /** @@ -2239,6 +2241,7 @@ static void cds_update_hw_mode_conn_info(uint32_t num_vdev_mac_entries, conc_connection_list[conn_index].rx_spatial_stream); } } + cds_dump_connection_status_info(); qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); } @@ -2379,7 +2382,7 @@ void cds_set_dual_mac_fw_mode_config(uint8_t dbs, uint8_t dfs) } /** - * cds_soc_set_hw_mode_cb() - Callback for set hw mode + * cds_pdev_set_hw_mode_cb() - Callback for set hw mode * @status: Status * @cfgd_hw_mode_index: Configured HW mode index * @num_vdev_mac_entries: Number of vdev-mac id mapping that follows @@ -2391,7 +2394,7 @@ void cds_set_dual_mac_fw_mode_config(uint8_t dbs, uint8_t dfs) * * Return: None */ -static void cds_soc_set_hw_mode_cb(uint32_t status, +static void cds_pdev_set_hw_mode_cb(uint32_t status, uint32_t cfgd_hw_mode_index, uint32_t num_vdev_mac_entries, struct sir_vdev_mac_map *vdev_mac_map) @@ -2498,7 +2501,7 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, } /** - * cds_soc_set_hw_mode() - Set HW mode command to SME + * cds_pdev_set_hw_mode() - Set HW mode command to SME * @session_id: Session ID * @mac0_ss: MAC0 spatial stream configuration * @mac0_bw: MAC0 bandwidth configuration @@ -2526,7 +2529,7 @@ static void cds_hw_mode_transition_cb(uint32_t old_hw_mode_index, * * Return: Success if the message made it down to the next layer */ -QDF_STATUS cds_soc_set_hw_mode(uint32_t session_id, +QDF_STATUS cds_pdev_set_hw_mode(uint32_t session_id, enum hw_mode_ss_config mac0_ss, enum hw_mode_bandwidth mac0_bw, enum hw_mode_ss_config mac1_ss, @@ -2554,14 +2557,14 @@ QDF_STATUS cds_soc_set_hw_mode(uint32_t session_id, } msg.hw_mode_index = hw_mode_index; - msg.set_hw_mode_cb = (void *)cds_soc_set_hw_mode_cb; + msg.set_hw_mode_cb = (void *)cds_pdev_set_hw_mode_cb; msg.reason = reason; msg.session_id = session_id; cds_info("set hw mode to sme: hw_mode_index: %d session:%d reason:%d", msg.hw_mode_index, msg.session_id, msg.reason); - status = sme_soc_set_hw_mode(hdd_ctx->hHal, msg); + status = sme_pdev_set_hw_mode(hdd_ctx->hHal, msg); if (status != QDF_STATUS_SUCCESS) { cds_err("Failed to set hw mode to SME"); return status; @@ -3391,6 +3394,7 @@ void cds_set_concurrency_mode(enum tQDF_ADAPTER_MODE mode) case QDF_P2P_GO_MODE: case QDF_SAP_MODE: case QDF_IBSS_MODE: + case QDF_MONITOR_MODE: hdd_ctx->concurrency_mode |= (1 << mode); hdd_ctx->no_of_open_sessions[mode]++; break; @@ -3425,6 +3429,7 @@ void cds_clear_concurrency_mode(enum tQDF_ADAPTER_MODE mode) case QDF_P2P_CLIENT_MODE: case QDF_P2P_GO_MODE: case QDF_SAP_MODE: + case QDF_MONITOR_MODE: hdd_ctx->no_of_open_sessions[mode]--; if (!(hdd_ctx->no_of_open_sessions[mode])) hdd_ctx->concurrency_mode &= (~(1 << mode)); @@ -3588,7 +3593,7 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void) return upgrade; } - /* Are both mac's still in use*/ + /* Are both mac's still in use */ for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; conn_index++) { cds_debug("index:%d mac:%d in_use:%d chan:%d org_nss:%d", @@ -3599,13 +3604,13 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void) conc_connection_list[conn_index].original_nss); if ((conc_connection_list[conn_index].mac == 0) && conc_connection_list[conn_index].in_use) { - mac |= 1; - if (3 == mac) + mac |= CDS_MAC0; + if (CDS_MAC0_AND_MAC1 == mac) goto done; } else if ((conc_connection_list[conn_index].mac == 1) && conc_connection_list[conn_index].in_use) { - mac |= 2; - if (3 == mac) + mac |= CDS_MAC1; + if (CDS_MAC0_AND_MAC1 == mac) goto done; } } @@ -3618,13 +3623,13 @@ enum cds_conc_next_action cds_need_opportunistic_upgrade(void) } #endif /* Let's request for single MAC mode */ - upgrade = CDS_MCC; + upgrade = CDS_SINGLE_MAC; /* Is there any connection had an initial connection with 2x2 */ for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; conn_index++) { if ((conc_connection_list[conn_index].original_nss == 1) && conc_connection_list[conn_index].in_use) { - upgrade = CDS_MCC_UPGRADE; + upgrade = CDS_SINGLE_MAC_UPGRADE; goto done; } } @@ -3955,6 +3960,8 @@ QDF_STATUS cds_init_policy_mgr(void) return status; } + cds_ctx->do_hw_mode_change = false; + return QDF_STATUS_SUCCESS; } @@ -5971,12 +5978,16 @@ bool cds_wait_for_nss_update(uint8_t action) [conn_index].tx_spatial_stream == 2) && (conc_connection_list [conn_index].rx_spatial_stream == 2) && - conc_connection_list[conn_index].in_use) { + conc_connection_list[conn_index].in_use && + ((conc_connection_list[conn_index].mode == + CDS_P2P_GO_MODE) || + (conc_connection_list[conn_index].mode == + CDS_SAP_MODE))) { wait = true; break; } } - } else if (CDS_MCC == action) { + } else if (CDS_SINGLE_MAC == action) { for (conn_index = 0; conn_index < MAX_NUMBER_OF_CONC_CONNECTIONS; conn_index++) { @@ -5986,7 +5997,11 @@ bool cds_wait_for_nss_update(uint8_t action) [conn_index].tx_spatial_stream == 1) && (conc_connection_list [conn_index].rx_spatial_stream == 1) && - conc_connection_list[conn_index].in_use) { + conc_connection_list[conn_index].in_use && + ((conc_connection_list[conn_index].mode == + CDS_P2P_GO_MODE) || + (conc_connection_list[conn_index].mode == + CDS_SAP_MODE))) { wait = true; break; } @@ -6046,7 +6061,7 @@ void cds_nss_update_cb(void *context, uint8_t tx_status, uint8_t vdev_id, conc_connection_list[conn_index].rx_spatial_stream = 1; wait = cds_wait_for_nss_update(next_action); break; - case CDS_MCC: + case CDS_SINGLE_MAC: conc_connection_list[conn_index].tx_spatial_stream = 2; conc_connection_list[conn_index].rx_spatial_stream = 2; wait = cds_wait_for_nss_update(next_action); @@ -6196,8 +6211,8 @@ QDF_STATUS cds_next_actions(uint32_t session_id, */ if ((((CDS_DBS_DOWNGRADE == action) || (CDS_DBS == action)) && hw_mode.dbs_cap) || - (((CDS_MCC_UPGRADE == action) || (CDS_MCC == action)) - && !hw_mode.dbs_cap)) { + (((CDS_SINGLE_MAC_UPGRADE == action) || + (CDS_SINGLE_MAC == action)) && !hw_mode.dbs_cap)) { cds_err("driver is already in %s mode, no further action needed", (hw_mode.dbs_cap) ? "dbs" : "non dbs"); return QDF_STATUS_E_ALREADY; @@ -6214,7 +6229,7 @@ QDF_STATUS cds_next_actions(uint32_t session_id, session_id); break; case CDS_DBS: - status = cds_soc_set_hw_mode(session_id, + status = cds_pdev_set_hw_mode(session_id, HW_MODE_SS_1x1, HW_MODE_80_MHZ, HW_MODE_SS_1x1, HW_MODE_40_MHZ, @@ -6222,17 +6237,17 @@ QDF_STATUS cds_next_actions(uint32_t session_id, HW_MODE_AGILE_DFS_NONE, reason); break; - case CDS_MCC_UPGRADE: + case CDS_SINGLE_MAC_UPGRADE: /* * check if we have a beaconing entity that advertised 2x2 * intially. If yes, update the beacon template & notify FW. * Once FW confirms beacon updated, send the HW mode change req */ - status = cds_complete_action(CDS_RX_NSS_2, CDS_MCC, reason, - session_id); + status = cds_complete_action(CDS_RX_NSS_2, CDS_SINGLE_MAC, + reason, session_id); break; - case CDS_MCC: - status = cds_soc_set_hw_mode(session_id, + case CDS_SINGLE_MAC: + status = cds_pdev_set_hw_mode(session_id, HW_MODE_SS_2x2, HW_MODE_80_MHZ, HW_MODE_SS_0x0, HW_MODE_BW_NONE, @@ -6374,13 +6389,8 @@ QDF_STATUS cds_check_and_restart_sap(eCsrRoamResult roam_result, * creating workqueue then our main thread might go to sleep * which is not acceptable. */ -#ifdef CONFIG_CNSS - cnss_init_work(&hdd_ctx->sap_start_work, - cds_sap_restart_handle); -#else INIT_WORK(&hdd_ctx->sap_start_work, cds_sap_restart_handle); -#endif schedule_work(&hdd_ctx->sap_start_work); return QDF_STATUS_SUCCESS; } @@ -8073,22 +8083,19 @@ QDF_STATUS qdf_init_connection_update(void) } /** - * cds_get_pref_hw_mode_for_chan() - Get preferred hw mode for new channel - * @vdev_id: vdev id whose target channel needs to change - * @target_channel: Target channel + * cds_get_current_pref_hw_mode() - Get the current preferred hw mode * - * Get the preferred hw mode based on the vdev whose channel is going to change + * Get the preferred hw mode based on the current connection combinations * - * Return: No change (CDS_NOP), MCC (CDS_MCC_UPGRADE), DBS (CDS_DBS_DOWNGRADE) + * Return: No change (CDS_NOP), MCC (CDS_SINGLE_MAC_UPGRADE), + * DBS (CDS_DBS_DOWNGRADE) */ -enum cds_conc_next_action cds_get_pref_hw_mode_for_chan(uint32_t vdev_id, - uint32_t target_channel) +enum cds_conc_next_action cds_get_current_pref_hw_mode(void) { uint32_t num_connections; - uint32_t conn_index = 0; - bool found = false; - uint8_t old_band, new_band; -#ifdef QCA_WIFI_3_0_EMU + uint8_t band1, band2, band3; + struct sir_hw_mode_params hw_mode; + QDF_STATUS status; hdd_context_t *hdd_ctx; hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); @@ -8096,40 +8103,22 @@ enum cds_conc_next_action cds_get_pref_hw_mode_for_chan(uint32_t vdev_id, cds_err("HDD context is NULL"); return CDS_NOP; } -#endif - while (CONC_CONNECTION_LIST_VALID_INDEX(conn_index)) { - if ((vdev_id == conc_connection_list[conn_index].vdev_id) && - (conc_connection_list[conn_index].in_use == true)) { - found = true; - break; - } - conn_index++; - } - - if (!found) { - cds_err("vdev_id:%d not available in the conn info", vdev_id); + status = wma_get_current_hw_mode(&hw_mode); + if (!QDF_IS_STATUS_SUCCESS(status)) { + cds_err("wma_get_current_hw_mode failed"); return CDS_NOP; } - old_band = cds_chan_to_band(conc_connection_list[conn_index].chan); - new_band = cds_chan_to_band(target_channel); - num_connections = cds_get_connection_count(); - cds_debug("vdev_id:%d conn_index:%d target_channel:%d chan[0]:%d chan[1]:%d chan[2]:%d num_connections:%d", - vdev_id, conn_index, target_channel, + cds_debug("chan[0]:%d chan[1]:%d chan[2]:%d num_connections:%d dbs:%d", conc_connection_list[0].chan, conc_connection_list[1].chan, - conc_connection_list[2].chan, - num_connections); + conc_connection_list[2].chan, num_connections, hw_mode.dbs_cap); - /* If the band of the new channel to which the switching is done is same - * as the band of the old channel, then there is no need for a hw mode - * change. The driver would already be in the required hw mode. + /* If the band of operation of both the MACs is the same, + * single MAC is preferred, otherwise DBS is preferred. */ - if (old_band == new_band) - return CDS_NOP; - switch (num_connections) { case 1: #ifdef QCA_WIFI_3_0_EMU @@ -8137,69 +8126,33 @@ enum cds_conc_next_action cds_get_pref_hw_mode_for_chan(uint32_t vdev_id, * request DBS */ if (hdd_ctx->config->enable_m2m_limitation && - CDS_IS_CHANNEL_24GHZ(target_channel)) + CDS_IS_CHANNEL_24GHZ(conc_connection_list[0].chan)) return CDS_DBS_DOWNGRADE; #endif /* The driver would already be in the required hw mode */ return CDS_NOP; case 2: - /* If the band of the new channel, is same as that of the band - * of the channel on the other interface, the driver needs to - * move to single MAC. - * - * If the band of the new channel, is different than that of the - * band of the channel on the other interface, the driver needs - * to move to DBS. - */ - if (conn_index == 0) { - if (new_band == cds_chan_to_band( - conc_connection_list[1].chan)) - return CDS_MCC_UPGRADE; - else if (new_band != cds_chan_to_band( - conc_connection_list[1].chan)) - return CDS_DBS_DOWNGRADE; - } else { - if (new_band == cds_chan_to_band( - conc_connection_list[0].chan)) - return CDS_MCC_UPGRADE; - else if (new_band != cds_chan_to_band( - conc_connection_list[0].chan)) - return CDS_DBS_DOWNGRADE; - } + band1 = cds_chan_to_band(conc_connection_list[0].chan); + band2 = cds_chan_to_band(conc_connection_list[1].chan); + if ((band1 == band2) && (hw_mode.dbs_cap)) + return CDS_SINGLE_MAC_UPGRADE; + else if ((band1 != band2) && (!hw_mode.dbs_cap)) + return CDS_DBS_DOWNGRADE; + else + return CDS_NOP; + case 3: - /* If the band of the new channel, is same as that of the band - * of the channel on the other two interfaces, the driver needs - * to move to single MAC. - * - * If the band of the new channel, is different than that of the - * band of the channel on the other two interfaces, the driver - * needs to move to DBS. - */ - if (conn_index == 0) { - if ((new_band == cds_chan_to_band( - conc_connection_list[1].chan)) && - (new_band == cds_chan_to_band( - conc_connection_list[2].chan))) - return CDS_MCC_UPGRADE; - else - return CDS_DBS_DOWNGRADE; - } else if (conn_index == 1) { - if ((new_band == cds_chan_to_band( - conc_connection_list[0].chan)) && - (new_band == cds_chan_to_band( - conc_connection_list[2].chan))) - return CDS_MCC_UPGRADE; - else - return CDS_DBS_DOWNGRADE; - } else { - if ((new_band == cds_chan_to_band( - conc_connection_list[0].chan)) && - (new_band == cds_chan_to_band( - conc_connection_list[1].chan))) - return CDS_MCC_UPGRADE; - else - return CDS_DBS_DOWNGRADE; - } + band1 = cds_chan_to_band(conc_connection_list[0].chan); + band2 = cds_chan_to_band(conc_connection_list[1].chan); + band3 = cds_chan_to_band(conc_connection_list[2].chan); + if (((band1 == band2) && (band2 == band3)) && + (hw_mode.dbs_cap)) + return CDS_SINGLE_MAC_UPGRADE; + else if (((band1 != band2) || (band2 != band3) || + (band1 != band3)) && (!hw_mode.dbs_cap)) + return CDS_DBS_DOWNGRADE; + else + return CDS_NOP; default: cds_err("unexpected num_connections value %d", num_connections); @@ -8239,87 +8192,6 @@ QDF_STATUS cds_stop_start_opportunistic_timer(void) return status; } -/** - * cds_handle_hw_mode_change_on_csa() - handle hw mode change for csa - * @session_id: SME session id - * @channel: given channel - * @bssid: pointer to bssid - * @dst: pointer to dest buffer - * @src: pointer to src buffer - * @numbytes: number of bytes to copy from src to dst - * - * Use this function to decide whether the hw mode upgrage or downgrade - * is required based on session_id and given channel - * - * Return: QDF_STATUS - */ -QDF_STATUS cds_handle_hw_mode_change_on_csa(uint16_t session_id, - uint8_t channel, uint8_t *bssid, void *dst, void *src, - uint32_t numbytes) -{ - enum cds_conc_next_action action; - QDF_STATUS status; - - /* - * Since all the write to the policy manager table happens in the - * MC thread context and this channel change event is also processed - * in the MC thread context, explicit lock/unlock of qdf_conc_list_lock - * is not done here - */ - action = cds_get_pref_hw_mode_for_chan(session_id, channel); - - if (action == CDS_NOP) { - cds_info("no need for hw mode change"); - /* Proceed with processing csa params. So, not freeing it */ - return QDF_STATUS_SUCCESS; - } - cds_info("session:%d action:%d", session_id, action); - - /* - * 1. Start opportunistic timer - * 2. Do vdev restart on the new channel (by the caller) - * 3. PM will check if MCC upgrade can be done after timer expiry - */ - if (action == CDS_MCC_UPGRADE) { - status = cds_stop_start_opportunistic_timer(); - if (QDF_IS_STATUS_SUCCESS(status)) - cds_info("opportunistic timer for MCC upgrade"); - - /* - * After opportunistic timer is triggered, we can go ahead - * with processing the csa params. So, not freeing the memory - * through 'err' label. - */ - return QDF_STATUS_SUCCESS; - } - - /* - * CDS_DBS_DOWNGRADE: - * 1. PM will initiate HW mode change to DBS rightaway - * 2. Do vdev restart on the new channel (on getting hw mode resp) - */ - status = cds_next_actions(session_id, action, - SIR_UPDATE_REASON_CHANNEL_SWITCH_STA); - if (!QDF_IS_STATUS_SUCCESS(status)) { - cds_err("no set hw mode command was issued"); - /* Proceed with processing csa params. So, not freeing it */ - return QDF_STATUS_SUCCESS; - } else { - if ((NULL == dst) || (NULL == src)) { - cds_err("given buffers are null, can't copy csa param"); - return QDF_STATUS_E_FAILURE; - } - /* Save the csa params to be used after DBS downgrade */ - qdf_mem_copy(dst, src, numbytes); - cds_info("saved csa params for dbs downgrade for bssid %pM", - bssid); - - /* Returning error so that csa params are not processed here */ - status = QDF_STATUS_E_FAILURE; - } - return status; -} - #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH /** * cds_register_sap_restart_channel_switch_cb() - Register callback for SAP @@ -8500,3 +8372,166 @@ QDF_STATUS cds_get_valid_chan_weights(struct sir_pcl_chan_weights *weight) return QDF_STATUS_SUCCESS; } + +/** + * cds_set_hw_mode_on_channel_switch() - Set hw mode after channel switch + * @session_id: Session ID + * + * Sets hw mode after doing a channel switch + * + * Return: QDF_STATUS + */ +QDF_STATUS cds_set_hw_mode_on_channel_switch(uint8_t session_id) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE, qdf_status; + cds_context_type *cds_ctx; + enum cds_conc_next_action action; + hdd_context_t *hdd_ctx; + + hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + if (!hdd_ctx) { + cds_err("HDD context is NULL"); + return status; + } + + if (!(hdd_ctx->config->policy_manager_enabled && + wma_is_hw_dbs_capable())) { + cds_err("PM/DBS is disabled"); + return status; + } + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, + FL("Invalid CDS Context")); + return status; + } + + qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); + + action = cds_get_current_pref_hw_mode(); + + if ((action != CDS_DBS_DOWNGRADE) && + (action != CDS_SINGLE_MAC_UPGRADE)) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, + FL("Invalid action: %d"), action); + status = QDF_STATUS_SUCCESS; + goto done; + } + + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + FL("action:%d session id:%d"), + action, session_id); + + /* Opportunistic timer is started, PM will check if MCC upgrade can be + * done on timer expiry. This avoids any possible ping pong effect + * as well. + */ + if (action == CDS_SINGLE_MAC_UPGRADE) { + qdf_status = cds_stop_start_opportunistic_timer(); + if (QDF_IS_STATUS_SUCCESS(qdf_status)) + cds_info("opportunistic timer for MCC upgrade"); + goto done; + } + + /* For DBS, we want to move right away to DBS mode */ + status = cds_next_actions(session_id, action, + SIR_UPDATE_REASON_CHANNEL_SWITCH); + if (!QDF_IS_STATUS_SUCCESS(status)) { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, + FL("no set hw mode command was issued")); + goto done; + } +done: + qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); + /* success must be returned only when a set hw mode was done */ + return status; +} + +/** + * cds_dump_connection_status_info() - Dump the concurrency information + * + * Prints the concurrency information such as tx/rx spatial stream, chainmask, + * etc. + * + * Return: None + */ +void cds_dump_connection_status_info(void) +{ + cds_context_type *cds_ctx; + uint32_t i; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + + for (i = 0; i < MAX_NUMBER_OF_CONC_CONNECTIONS; i++) { + cds_debug("%d: use:%d vdev:%d tx:%d rx:%d mode:%d mac:%d chan:%d chainmask:%d orig nss:%d bw:%d", + i, conc_connection_list[i].in_use, + conc_connection_list[i].vdev_id, + conc_connection_list[i].tx_spatial_stream, + conc_connection_list[i].rx_spatial_stream, + conc_connection_list[i].mode, + conc_connection_list[i].mac, + conc_connection_list[i].chan, + conc_connection_list[i].chain_mask, + conc_connection_list[i].original_nss, + conc_connection_list[i].bw); + } +} + +/** + * cds_set_do_hw_mode_change_flag() - Set flag to indicate hw mode change + * @flag: Indicate if hw mode change is required or not + * + * Set the flag to indicate whether a hw mode change is required after a + * vdev up or not. Flag value of true indicates that a hw mode change is + * required after vdev up. + * + * Return: None + */ +void cds_set_do_hw_mode_change_flag(bool flag) +{ + cds_context_type *cds_ctx; + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return; + } + + qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); + cds_ctx->do_hw_mode_change = flag; + qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); + + cds_debug("hw_mode_change_channel:%d", flag); +} + +/** + * cds_is_hw_mode_change_after_vdev_up() - Check if hw mode change is needed + * + * Returns the flag which indicates if a hw mode change is required after + * vdev up. + * + * Return: True if hw mode change is required, false otherwise + */ +bool cds_is_hw_mode_change_after_vdev_up(void) +{ + cds_context_type *cds_ctx; + bool flag; + + cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); + + if (!cds_ctx) { + cds_err("Invalid CDS Context"); + return INVALID_CHANNEL_ID; + } + + qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); + flag = cds_ctx->do_hw_mode_change; + qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); + + return flag; +} diff --git a/core/cds/src/cds_packet.c b/core/cds/src/cds_packet.c index 38447aeef712..f8f610459f4e 100644 --- a/core/cds/src/cds_packet.c +++ b/core/cds/src/cds_packet.c @@ -181,12 +181,12 @@ uint8_t cds_pkt_get_proto_type(struct sk_buff *skb, uint8_t tracking_map, } #ifdef QCA_PKT_PROTO_TRACE -/*--------------------------------------------------------------------------- -* @brief cds_pkt_trace_buf_update() - - Update storage buffer with interest event string - -* event_string Event String may packet type or outstanding event - ---------------------------------------------------------------------------*/ +/** + * cds_pkt_trace_buf_update() - Update storage buffer with interest event string + * @event_string: string may be a packet type or an outstanding event + * + * Return: none + */ void cds_pkt_trace_buf_update(char *event_string) { uint32_t slot; @@ -194,6 +194,11 @@ void cds_pkt_trace_buf_update(char *event_string) QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO, "%s %d, %s", __func__, __LINE__, event_string); qdf_spinlock_acquire(&trace_buffer_lock); + if (!trace_buffer) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "trace_buffer is null"); + goto release_lock; + } slot = trace_buffer_order % CDS_PKT_TRAC_MAX_TRACE_BUF; trace_buffer[slot].order = trace_buffer_order; trace_buffer[slot].event_time = qdf_mc_timer_get_system_time(); @@ -204,20 +209,27 @@ void cds_pkt_trace_buf_update(char *event_string) (CDS_PKT_TRAC_MAX_STRING_LEN < strlen(event_string)) ? CDS_PKT_TRAC_MAX_STRING_LEN : strlen(event_string)); trace_buffer_order++; - qdf_spinlock_release(&trace_buffer_lock); +release_lock: + qdf_spinlock_release(&trace_buffer_lock); return; } -/*--------------------------------------------------------------------------- -* @brief cds_pkt_trace_buf_dump() - - Dump stored information into kernel log - ---------------------------------------------------------------------------*/ +/** + * cds_pkt_trace_buf_dump() - Dump stored information into kernel log + * + * Return: none + */ void cds_pkt_trace_buf_dump(void) { uint32_t slot, idx; qdf_spinlock_acquire(&trace_buffer_lock); + if (!trace_buffer) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, + "trace_buffer is null"); + goto release_lock; + } QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "PACKET TRACE DUMP START Current Timestamp %u", (unsigned int)qdf_mc_timer_get_system_time()); @@ -245,15 +257,16 @@ void cds_pkt_trace_buf_dump(void) QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "PACKET TRACE DUMP END"); +release_lock: qdf_spinlock_release(&trace_buffer_lock); - return; } -/*--------------------------------------------------------------------------- -* @brief cds_pkt_proto_trace_init() - - Initialize protocol trace functionality, allocate required resource - ---------------------------------------------------------------------------*/ +/** + * cds_pkt_proto_trace_init() - Initialize protocol trace functionality + * + * Return: none + */ void cds_pkt_proto_trace_init(void) { /* Init spin lock to protect global memory */ @@ -269,17 +282,18 @@ void cds_pkt_proto_trace_init(void) return; } -/*--------------------------------------------------------------------------- -* @brief cds_pkt_proto_trace_close() - - Free required resource - ---------------------------------------------------------------------------*/ -void cds_pkt_proto_trace_close(void) +/** + * cds_pkt_proto_trace_deinit() - Free trace_buffer resource + * + * Return: none + */ +void cds_pkt_proto_trace_deinit(void) { QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR, "%s %d", __func__, __LINE__); qdf_mem_free(trace_buffer); + trace_buffer = NULL; qdf_spinlock_destroy(&trace_buffer_lock); - return; } #endif /* QCA_PKT_PROTO_TRACE */ diff --git a/core/cds/src/cds_reg_service.c b/core/cds/src/cds_reg_service.c index cd0ed13839c2..dcdc20031e6c 100644 --- a/core/cds/src/cds_reg_service.c +++ b/core/cds/src/cds_reg_service.c @@ -450,7 +450,7 @@ static void cds_set_5g_channel_params(uint16_t oper_ch, enum channel_state chan_state2 = CHANNEL_STATE_ENABLE; const struct bonded_chan *bonded_chan_ptr; - if (CH_WIDTH_MAX >= ch_params->ch_width) + if (CH_WIDTH_MAX <= ch_params->ch_width) ch_params->ch_width = CH_WIDTH_80P80MHZ; while (ch_params->ch_width != CH_WIDTH_INVALID) { @@ -506,8 +506,8 @@ static void cds_set_2g_channel_params(uint16_t oper_ch, { enum channel_state chan_state = CHANNEL_STATE_ENABLE; - if (CH_WIDTH_MAX >= ch_params->ch_width) - ch_params->ch_width = CH_WIDTH_80P80MHZ; + if (CH_WIDTH_MAX <= ch_params->ch_width) + ch_params->ch_width = CH_WIDTH_40MHZ; while (ch_params->ch_width != CH_WIDTH_INVALID) { chan_state = cds_get_2g_bonded_channel_state(oper_ch, diff --git a/core/cds/src/cds_regdomain.c b/core/cds/src/cds_regdomain.c index a7e8e3ec1e41..5fffb2d6de2d 100644 --- a/core/cds/src/cds_regdomain.c +++ b/core/cds/src/cds_regdomain.c @@ -379,7 +379,8 @@ static const struct country_code_to_reg_dmn g_all_countries[] = { {CTRY_WALLIS_AND_FUTUNA, ETSI1_WORLD, "WF" "WALLIS"}, {CTRY_YEMEN, NULL1_WORLD, "YE", "YEMEN"}, {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW", "ZIMBABWE"}, - {CTRY_JAPAN14, MKK5_MKKA, "JP", "JAPAN"} + {CTRY_JAPAN14, MKK5_MKKA2, "JP", "JAPAN"}, + {CTRY_XA, MKK5_MKKA2, "XA", "JAPAN PASSIVE"} }; static const struct reg_dmn g_reg_dmns[] = { diff --git a/core/cds/src/cds_sched.c b/core/cds/src/cds_sched.c index bbf9b754d775..4f9a39c5fe2b 100644 --- a/core/cds/src/cds_sched.c +++ b/core/cds/src/cds_sched.c @@ -46,9 +46,6 @@ #include <linux/spinlock.h> #include <linux/kthread.h> #include <linux/cpu.h> -#if defined(QCA_CONFIG_SMP) && defined(CONFIG_CNSS) -#include <net/cnss.h> -#endif /* Preprocessor Definitions and Constants */ #define CDS_SCHED_THREAD_HEART_BEAT INFINITE /* Milli seconds to delay SSR thread when an Entry point is Active */ @@ -89,13 +86,7 @@ static QDF_STATUS cds_alloc_ol_rx_pkt_freeq(p_cds_sched_context pSchedContext); #define CDS_CORE_PER_CLUSTER (4) static int cds_set_cpus_allowed_ptr(struct task_struct *task, unsigned long cpu) { -#ifdef WLAN_OPEN_SOURCE return set_cpus_allowed_ptr(task, cpumask_of(cpu)); -#elif defined(CONFIG_CNSS) - return cnss_set_cpus_allowed_ptr(task, cpu); -#else - return 0; -#endif } /** diff --git a/core/dp/htt/htt.c b/core/dp/htt/htt.c index 1672a39c2ea5..fe30c3405d3a 100644 --- a/core/dp/htt/htt.c +++ b/core/dp/htt/htt.c @@ -137,6 +137,14 @@ void htt_htc_misc_pkt_pool_free(struct htt_pdev_t *pdev) } #endif + +/* AR6004 don't need HTT layer. */ +#ifdef AR6004_HW +#define NO_HTT_NEEDED true +#else +#define NO_HTT_NEEDED false +#endif + /** * htt_pdev_alloc() - allocate HTT pdev * @txrx_pdev: txrx pdev @@ -152,6 +160,10 @@ htt_pdev_alloc(ol_txrx_pdev_handle txrx_pdev, HTC_HANDLE htc_pdev, qdf_device_t osdev) { struct htt_pdev_t *pdev; + struct hif_opaque_softc *osc = cds_get_context(QDF_MODULE_ID_HIF); + + if (!osc) + goto fail1; pdev = qdf_mem_malloc(sizeof(*pdev)); if (!pdev) @@ -186,14 +198,14 @@ htt_pdev_alloc(ol_txrx_pdev_handle txrx_pdev, HTT_SET_WIFI_IP(pdev, 2, 0); #endif /* defined(HELIUMPLUS_PADDR64) */ + if (NO_HTT_NEEDED) + goto success; /* * Connect to HTC service. * This has to be done before calling htt_rx_attach, * since htt_rx_attach involves sending a rx ring configure * message to the target. */ -/* AR6004 don't need HTT layer. */ -#ifndef AR6004_HW if (htt_htc_attach(pdev, HTT_DATA_MSG_SVC)) goto fail2; if (htt_htc_attach(pdev, HTT_DATA2_MSG_SVC)) @@ -204,11 +216,10 @@ htt_pdev_alloc(ol_txrx_pdev_handle txrx_pdev, ; /* TODO: enable the following line once FW is ready */ /* goto fail2; */ - if (hif_ce_fastpath_cb_register(htt_t2h_msg_handler_fast, pdev)) + if (hif_ce_fastpath_cb_register(osc, htt_t2h_msg_handler_fast, pdev)) qdf_print("failed to register fastpath callback\n"); -#endif - +success: return pdev; fail2: diff --git a/core/dp/htt/htt_h2t.c b/core/dp/htt/htt_h2t.c index 9662eb4d6980..c7aeb9f70006 100644 --- a/core/dp/htt/htt_h2t.c +++ b/core/dp/htt/htt_h2t.c @@ -51,6 +51,7 @@ #include <ol_htt_tx_api.h> #include <htt_internal.h> +#include <cds_concurrency.h> #define HTT_MSG_BUF_SIZE(msg_bytes) \ ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING) @@ -356,6 +357,18 @@ A_STATUS htt_h2t_rx_ring_cfg_msg_ll(struct htt_pdev_t *pdev) enable_ppdu_start = 0; enable_ppdu_end = 0; #endif + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) { + enable_ctrl_data = 1; + enable_mgmt_data = 1; + enable_null_data = 1; + enable_phy_data = 1; + enable_hdr = 1; + enable_ppdu_start = 1; + enable_ppdu_end = 1; + /* Disable ASPM for monitor mode */ + qdf_print("Monitor mode is enabled\n"); + } + HTT_RX_RING_CFG_ENABLED_802_11_HDR_SET(*msg_word, enable_hdr); HTT_RX_RING_CFG_ENABLED_MSDU_PAYLD_SET(*msg_word, 1); HTT_RX_RING_CFG_ENABLED_PPDU_START_SET(*msg_word, enable_ppdu_start); diff --git a/core/dp/htt/htt_internal.h b/core/dp/htt/htt_internal.h index 7d3ffbddafcb..271e77eec211 100644 --- a/core/dp/htt/htt_internal.h +++ b/core/dp/htt/htt_internal.h @@ -331,6 +331,7 @@ static inline void htt_print_rx_desc(struct htt_host_rx_desc_base *rx_desc) * rounded up to a cache line size. */ #define HTT_RX_BUF_SIZE 1920 +#define MAX_RX_PAYLOAD_SZ (HTT_RX_BUF_SIZE - RX_STD_DESC_SIZE) /* * DMA_MAP expects the buffer to be an integral number of cache lines. * Rather than checking the actual cache line size, this code makes a diff --git a/core/dp/htt/htt_rx.c b/core/dp/htt/htt_rx.c index 0064a8f282d6..b5d8667c5f3a 100644 --- a/core/dp/htt/htt_rx.c +++ b/core/dp/htt/htt_rx.c @@ -53,12 +53,20 @@ #include <cds_ieee80211_common.h> /* ieee80211_frame, ieee80211_qoscntl */ #include <cds_ieee80211_defines.h> /* ieee80211_rx_status */ +#include <cds_utils.h> +#include <cds_concurrency.h> #ifdef DEBUG_DMA_DONE #include <asm/barrier.h> #include <wma_api.h> #endif +#ifdef HTT_DEBUG_DATA +#define HTT_PKT_DUMP(x) x +#else +#define HTT_PKT_DUMP(x) /* no-op */ +#endif + /* AR9888v1 WORKAROUND for EV#112367 */ /* FIX THIS - remove this WAR when the bug is fixed */ #define PEREGRINE_1_0_ZERO_LEN_PHY_ERR_WAR @@ -81,8 +89,9 @@ #define HTT_RX_HOST_LATENCY_MAX_MS 20 /* ms */ /* very conservative */ #endif + /* very conservative to ensure enough buffers are allocated */ #ifndef HTT_RX_HOST_LATENCY_WORST_LIKELY_MS -#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 10 /* ms */ /* conservative */ +#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 20 #endif #ifndef HTT_RX_RING_REFILL_RETRY_TIME_MS @@ -203,7 +212,9 @@ static int htt_rx_ring_fill_level(struct htt_pdev_t *pdev) size = ol_cfg_max_thruput_mbps(pdev->ctrl_pdev) * 1000 /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */ / - 8 * HTT_RX_AVG_FRM_BYTES * HTT_RX_HOST_LATENCY_WORST_LIKELY_MS; + (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_WORST_LIKELY_MS; + + size = qdf_get_pwr2(size); /* * Make sure the fill level is at least 1 less than the ring size. * Leaving 1 element empty allows the SW to easily distinguish @@ -1148,8 +1159,313 @@ htt_rx_offload_paddr_msdu_pop_ll(htt_pdev_handle pdev, return 0; } -extern void -dump_pkt(qdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len); +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#if HTT_PADDR64 +#define NEXT_FIELD_OFFSET_IN32 2 +#else /* ! HTT_PADDR64 */ +#define NEXT_FIELD_OFFSET_IN32 1 +#endif /* HTT_PADDR64 */ + +/** + * htt_mon_rx_handle_amsdu_packet() - Handle consecutive fragments of amsdu + * @msdu: pointer to first msdu of amsdu + * @pdev: Handle to htt_pdev_handle + * @msg_word: Input and output variable, so pointer to HTT msg pointer + * @amsdu_len: remaining length of all N-1 msdu msdu's + * + * This function handles the (N-1) msdu's of amsdu, N'th msdu is already + * handled by calling function. N-1 msdu's are tied using frags_list. + * msdu_info field updated by FW indicates if this is last msdu. All the + * msdu's before last msdu will be of MAX payload. + * + * Return: 1 on success and 0 on failure. + */ +int htt_mon_rx_handle_amsdu_packet(qdf_nbuf_t msdu, htt_pdev_handle pdev, + uint32_t **msg_word, uint32_t amsdu_len) +{ + qdf_nbuf_t frag_nbuf; + qdf_nbuf_t prev_frag_nbuf; + uint32_t len; + uint32_t last_frag; + + *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(**msg_word)); + if (qdf_unlikely(NULL == frag_nbuf)) { + qdf_print("%s: netbuf pop failed!\n", __func__); + return 0; + } + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *)*msg_word)-> + msdu_info; + qdf_nbuf_append_ext_list(msdu, frag_nbuf, amsdu_len); + qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); + qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); + /* For msdu's other than parent will not have htt_host_rx_desc_base */ + len = MIN(amsdu_len, HTT_RX_BUF_SIZE); + amsdu_len -= len; + qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); + + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_FATAL, + qdf_nbuf_data(frag_nbuf), + qdf_nbuf_len(frag_nbuf))); + prev_frag_nbuf = frag_nbuf; + while (!last_frag) { + *msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + frag_nbuf = htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(**msg_word)); + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) + *msg_word)->msdu_info; + + if (qdf_unlikely(NULL == frag_nbuf)) { + qdf_print("%s: netbuf pop failed!\n", __func__); + prev_frag_nbuf->next = NULL; + return 0; + } + qdf_nbuf_set_pktlen(frag_nbuf, HTT_RX_BUF_SIZE); + qdf_nbuf_unmap(pdev->osdev, frag_nbuf, QDF_DMA_FROM_DEVICE); + + len = MIN(amsdu_len, HTT_RX_BUF_SIZE); + amsdu_len -= len; + qdf_nbuf_trim_tail(frag_nbuf, HTT_RX_BUF_SIZE - len); + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_FATAL, + qdf_nbuf_data(frag_nbuf), + qdf_nbuf_len(frag_nbuf))); + + qdf_nbuf_set_next(prev_frag_nbuf, frag_nbuf); + prev_frag_nbuf = frag_nbuf; + } + qdf_nbuf_set_next(prev_frag_nbuf, NULL); + return 1; +} + +/** + * htt_mon_rx_get_phy_info() - Get rate interms of 500Kbps. + * @rx_desc: Pointer to struct htt_host_rx_desc_base + * @rx_status: Return variable updated with phy_info in rx_status + * + * If l_sig_rate_select is 0: + * 0x8: OFDM 48 Mbps + * 0x9: OFDM 24 Mbps + * 0xA: OFDM 12 Mbps + * 0xB: OFDM 6 Mbps + * 0xC: OFDM 54 Mbps + * 0xD: OFDM 36 Mbps + * 0xE: OFDM 18 Mbps + * 0xF: OFDM 9 Mbps + * If l_sig_rate_select is 1: + * 0x8: CCK 11 Mbps long preamble + * 0x9: CCK 5.5 Mbps long preamble + * 0xA: CCK 2 Mbps long preamble + * 0xB: CCK 1 Mbps long preamble + * 0xC: CCK 11 Mbps short preamble + * 0xD: CCK 5.5 Mbps short preamble + * 0xE: CCK 2 Mbps short preamble + * + * Return: None + */ +static void htt_mon_rx_get_phy_info(struct htt_host_rx_desc_base *rx_desc, + struct mon_rx_status *rx_status) +{ +#define SHORT_PREAMBLE 1 +#define LONG_PREAMBLE 0 + char rate = 0x0; + uint8_t preamble = SHORT_PREAMBLE; + uint8_t preamble_type = rx_desc->ppdu_start.preamble_type; + uint8_t mcs = 0, nss = 0, sgi = 0, bw = 0, beamformed = 0; + uint16_t vht_flags = 0; + uint32_t l_sig_rate_select = rx_desc->ppdu_start.l_sig_rate_select; + uint32_t l_sig_rate = rx_desc->ppdu_start.l_sig_rate; + bool is_stbc = 0, ldpc = 0; + + if (l_sig_rate_select == 0) { + switch (l_sig_rate) { + case 0x8: + rate = 0x60; + break; + case 0x9: + rate = 0x30; + break; + case 0xA: + rate = 0x18; + break; + case 0xB: + rate = 0x0c; + break; + case 0xC: + rate = 0x6c; + break; + case 0xD: + rate = 0x48; + break; + case 0xE: + rate = 0x24; + break; + case 0xF: + rate = 0x12; + break; + default: + break; + } + } else if (l_sig_rate_select == 1) { + switch (l_sig_rate) { + case 0x8: + rate = 0x16; + preamble = LONG_PREAMBLE; + break; + case 0x9: + rate = 0x0B; + preamble = LONG_PREAMBLE; + break; + case 0xA: + rate = 0x04; + preamble = LONG_PREAMBLE; + break; + case 0xB: + rate = 0x02; + preamble = LONG_PREAMBLE; + break; + case 0xC: + rate = 0x16; + break; + case 0xD: + rate = 0x0B; + break; + case 0xE: + rate = 0x04; + break; + default: + break; + } + } else { + qdf_print("Invalid rate info\n"); + } + + switch (preamble_type) { + case 8: + is_stbc = ((VHT_SIG_A_2(rx_desc) >> 4) & 3); + /* fallthrough */ + case 9: + vht_flags = 1; + sgi = (VHT_SIG_A_2(rx_desc) >> 7) & 0x01; + bw = (VHT_SIG_A_1(rx_desc) >> 7) & 0x01; + mcs = (VHT_SIG_A_1(rx_desc) & 0x7f); + nss = mcs>>3; + beamformed = + (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; + break; + case 0x0c: + vht_flags = 1; + is_stbc = (VHT_SIG_A_2(rx_desc) >> 3) & 1; + ldpc = (VHT_SIG_A_2(rx_desc) >> 2) & 1; + /* fallthrough */ + case 0x0d: + { + uint8_t gid_in_sig = ((VHT_SIG_A_1(rx_desc) >> 4) & 0x3f); + + vht_flags = 1; + sgi = VHT_SIG_A_2(rx_desc) & 0x01; + bw = (VHT_SIG_A_1(rx_desc) & 0x03); + if (gid_in_sig == 0 || gid_in_sig == 63) { + /* SU case */ + mcs = (VHT_SIG_A_2(rx_desc) >> 4) & + 0xf; + nss = (VHT_SIG_A_1(rx_desc) >> 10) & + 0x7; + } else { + /* SU case */ + uint8_t sta_user_pos = + (uint8_t)((rx_desc->ppdu_start.reserved_4a >> 8) + & 0x3); + mcs = (rx_desc->ppdu_start.vht_sig_b >> 16); + if (bw >= 2) + mcs >>= 3; + else if (bw > 0) + mcs >>= 1; + mcs &= 0xf; + nss = (((VHT_SIG_A_1(rx_desc) >> 10) + + sta_user_pos * 3) & 0x7); + } + beamformed = (VHT_SIG_A_2(rx_desc) >> 8) & 0x1; + } + /* fallthrough */ + default: + break; + } + + rx_status->mcs = mcs; + rx_status->nr_ant = nss; + rx_status->is_stbc = is_stbc; + rx_status->sgi = sgi; + rx_status->ldpc = ldpc; + rx_status->beamformed = beamformed; + rx_status->vht_flag_values3[0] = mcs << 0x4; + rx_status->rate = rate; + rx_status->vht_flags = vht_flags; + rx_status->rtap_flags |= ((preamble == SHORT_PREAMBLE) ? BIT(1) : 0); + rx_status->vht_flag_values2 = 0x01 < bw; +} + +/** + * htt_mon_rx_get_rtap_flags() - Get radiotap flags + * @rx_desc: Pointer to struct htt_host_rx_desc_base + * + * Return: Bitmapped radiotap flags. + */ +static uint8_t htt_mon_rx_get_rtap_flags(struct htt_host_rx_desc_base *rx_desc) +{ + uint8_t rtap_flags = 0; + + /* WEP40 || WEP104 || WEP128 */ + if (rx_desc->mpdu_start.encrypt_type == 0 || + rx_desc->mpdu_start.encrypt_type == 1 || + rx_desc->mpdu_start.encrypt_type == 3) + rtap_flags |= BIT(2); + + /* IEEE80211_RADIOTAP_F_FRAG */ + if (rx_desc->attention.fragment) + rtap_flags |= BIT(3); + + /* IEEE80211_RADIOTAP_F_FCS */ + rtap_flags |= BIT(4); + + /* IEEE80211_RADIOTAP_F_BADFCS */ + if (rx_desc->mpdu_end.fcs_err) + rtap_flags |= BIT(6); + + return rtap_flags; +} + +/** + * htt_rx_mon_get_rx_status() - Update information about the rx status, + * which is used later for radiotap updation. + * @rx_desc: Pointer to struct htt_host_rx_desc_base + * @rx_status: Return variable updated with rx_status + * + * Return: None + */ +void htt_rx_mon_get_rx_status(htt_pdev_handle pdev, + struct htt_host_rx_desc_base *rx_desc, + struct mon_rx_status *rx_status) +{ + uint16_t channel_flags = 0; + struct mon_channel *ch_info = &pdev->mon_ch_info; + + rx_status->tsft = (u_int64_t)TSF_TIMESTAMP(rx_desc); + rx_status->chan_freq = ch_info->ch_freq; + rx_status->chan_num = ch_info->ch_num; + htt_mon_rx_get_phy_info(rx_desc, rx_status); + rx_status->rtap_flags |= htt_mon_rx_get_rtap_flags(rx_desc); + channel_flags |= rx_desc->ppdu_start.l_sig_rate_select ? + IEEE80211_CHAN_CCK : IEEE80211_CHAN_OFDM; + channel_flags |= + (cds_chan_to_band(ch_info->ch_num) == CDS_BAND_2GHZ ? + IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); + + rx_status->chan_flags = channel_flags; + rx_status->ant_signal_db = rx_desc->ppdu_start.rssi_comb; +} #ifdef RX_HASH_DEBUG #define HTT_RX_CHECK_MSDU_COUNT(msdu_count) HTT_ASSERT_ALWAYS(msdu_count) @@ -1157,6 +1473,164 @@ dump_pkt(qdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len); #define HTT_RX_CHECK_MSDU_COUNT(msdu_count) /* no-op */ #endif +/** + * htt_rx_mon_amsdu_rx_in_order_pop_ll() - Monitor mode HTT Rx in order pop + * function + * @pdev: Handle to htt_pdev_handle + * @rx_ind_msg: In order indication message. + * @head_msdu: Return variable pointing to head msdu. + * @tail_msdu: Return variable pointing to tail msdu. + * + * This function pops the msdu based on paddr:length of inorder indication + * message. + * + * Return: 1 for success, 0 on failure. + */ +int htt_rx_mon_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, + qdf_nbuf_t rx_ind_msg, + qdf_nbuf_t *head_msdu, + qdf_nbuf_t *tail_msdu) +{ + qdf_nbuf_t msdu, next; + uint8_t *rx_ind_data; + uint32_t *msg_word; + uint32_t msdu_count; + struct htt_host_rx_desc_base *rx_desc; + struct mon_rx_status rx_status = {0}; + uint32_t amsdu_len; + uint32_t len; + uint32_t last_frag; + + HTT_ASSERT1(htt_rx_in_order_ring_elems(pdev) != 0); + + rx_ind_data = qdf_nbuf_data(rx_ind_msg); + msg_word = (uint32_t *)rx_ind_data; + + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_FATAL, + (void *)rx_ind_data, + (int)qdf_nbuf_len(rx_ind_msg))); + + /* Get the total number of MSDUs */ + msdu_count = HTT_RX_IN_ORD_PADDR_IND_MSDU_CNT_GET(*(msg_word + 1)); + HTT_RX_CHECK_MSDU_COUNT(msdu_count); + + msg_word = (uint32_t *)(rx_ind_data + + HTT_RX_IN_ORD_PADDR_IND_HDR_BYTES); + + (*head_msdu) = msdu = htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word)); + + if (qdf_unlikely(NULL == msdu)) { + qdf_print("%s: netbuf pop failed!\n", __func__); + *tail_msdu = NULL; + return 0; + } + while (msdu_count > 0) { + + msdu_count--; + /* + * Set the netbuf length to be the entire buffer length + * initially, so the unmap will unmap the entire buffer. + */ + qdf_nbuf_set_pktlen(msdu, HTT_RX_BUF_SIZE); + qdf_nbuf_unmap(pdev->osdev, msdu, QDF_DMA_FROM_DEVICE); + + /* + * cache consistency has been taken care of by the + * qdf_nbuf_unmap + */ + rx_desc = htt_rx_desc(msdu); + HTT_PKT_DUMP(htt_print_rx_desc(rx_desc)); + /* + * Make the netbuf's data pointer point to the payload rather + * than the descriptor. + */ + htt_rx_mon_get_rx_status(pdev, rx_desc, &rx_status); + /* + * 350 bytes of RX_STD_DESC size should be sufficient for + * radiotap. + */ + qdf_nbuf_update_radiotap(&rx_status, msdu, + HTT_RX_STD_DESC_RESERVATION); + amsdu_len = HTT_RX_IN_ORD_PADDR_IND_MSDU_LEN_GET(*(msg_word + + NEXT_FIELD_OFFSET_IN32)); + + /* + * MAX_RX_PAYLOAD_SZ when we have AMSDU packet. amsdu_len in + * which case is the total length of sum of all AMSDU's + */ + len = MIN(amsdu_len, MAX_RX_PAYLOAD_SZ); + amsdu_len -= len; + qdf_nbuf_trim_tail(msdu, + HTT_RX_BUF_SIZE - + (RX_STD_DESC_SIZE + len)); + + + HTT_PKT_DUMP(qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, + QDF_TRACE_LEVEL_FATAL, + qdf_nbuf_data(msdu), + qdf_nbuf_len(msdu))); + last_frag = ((struct htt_rx_in_ord_paddr_ind_msdu_t *) + msg_word)->msdu_info; + +#undef NEXT_FIELD_OFFSET_IN32 + /* Handle amsdu packet */ + if (!last_frag) { + /* + * For AMSDU packet msdu->len is sum of all the msdu's + * length, msdu->data_len is sum of length's of + * remaining msdu's other than parent. + */ + if (!htt_mon_rx_handle_amsdu_packet(msdu, pdev, + &msg_word, + amsdu_len)) { + qdf_print("%s: failed to handle amsdu packet\n", + __func__); + return 0; + } + } + /* check if this is the last msdu */ + if (msdu_count) { + msg_word += HTT_RX_IN_ORD_PADDR_IND_MSDU_DWORDS; + next = htt_rx_in_order_netbuf_pop(pdev, + HTT_RX_IN_ORD_PADDR_IND_PADDR_GET(*msg_word)); + if (qdf_unlikely(NULL == next)) { + qdf_print("%s: netbuf pop failed!\n", + __func__); + *tail_msdu = NULL; + return 0; + } + qdf_nbuf_set_next(msdu, next); + msdu = next; + } else { + *tail_msdu = msdu; + qdf_nbuf_set_next(msdu, NULL); + } + } + + return 1; +} + +/** + * htt_rx_mon_note_capture_channel() - Make note of channel to update in + * radiotap + * @pdev: handle to htt_pdev + * @mon_ch: capture channel number. + * + * Return: None + */ +void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch) +{ + struct mon_channel *ch_info = &pdev->mon_ch_info; + + ch_info->ch_num = mon_ch; + ch_info->ch_freq = cds_chan_to_freq(mon_ch); +} + +extern void +dump_pkt(qdf_nbuf_t nbuf, uint32_t nbuf_paddr, int len); + /* Return values: 1 - success, 0 - failure */ int htt_rx_amsdu_rx_in_order_pop_ll(htt_pdev_handle pdev, @@ -2228,6 +2702,9 @@ int htt_rx_attach(struct htt_pdev_t *pdev) htt_rx_mpdu_desc_list_next = htt_rx_mpdu_desc_list_next_ll; } + if (cds_get_conparam() == QDF_GLOBAL_MONITOR_MODE) + htt_rx_amsdu_pop = htt_rx_mon_amsdu_rx_in_order_pop_ll; + htt_rx_offload_msdu_pop = htt_rx_offload_msdu_pop_ll; htt_rx_mpdu_desc_retry = htt_rx_mpdu_desc_retry_ll; htt_rx_mpdu_desc_seq_num = htt_rx_mpdu_desc_seq_num_ll; diff --git a/core/dp/htt/htt_types.h b/core/dp/htt/htt_types.h index b0bcf811a926..7900d1c6f9e2 100644 --- a/core/dp/htt/htt_types.h +++ b/core/dp/htt/htt_types.h @@ -211,6 +211,16 @@ struct msdu_ext_desc_t { }; #endif /* defined(HELIUMPLUS_PADDR64) */ +/** + * struct mon_channel + * @ch_num: Monitor mode capture channel number + * @ch_freq: channel frequency. + */ +struct mon_channel { + uint32_t ch_num; + uint32_t ch_freq; +}; + struct htt_pdev_t { ol_pdev_handle ctrl_pdev; ol_txrx_pdev_handle txrx_pdev; @@ -385,6 +395,7 @@ struct htt_pdev_t { struct rx_buf_debug *rx_buff_list; int rx_buff_index; #endif + struct mon_channel mon_ch_info; }; #define HTT_EPID_GET(_htt_pdev_hdl) \ diff --git a/core/dp/htt/rx_desc.h b/core/dp/htt/rx_desc.h index 66963d1e2b30..fc1b39ac52f7 100644 --- a/core/dp/htt/rx_desc.h +++ b/core/dp/htt/rx_desc.h @@ -257,6 +257,12 @@ struct rx_ppdu_start { uint32_t service:16, /* [15:0] */ reserved_9:16; /* [31:16] */ }; + +#define VHT_SIG_A_1(rx_desc) ((rx_desc)->ppdu_start.ht_sig_vht_sig_ah_sig_a_1) +#define VHT_SIG_A_2(rx_desc) ((rx_desc)->ppdu_start.ht_sig_vht_sig_ah_sig_a_2) +#define TSF_TIMESTAMP(rx_desc) \ +((rx_desc)->ppdu_end.rx_pkt_end.phy_timestamp_1_lower_32) + struct rx_location_info { volatile uint32_t rtt_fac_legacy:14, /* [13:0] */ @@ -469,6 +475,10 @@ struct rx_ppdu_start { reserved_9:16; /* [31:16] */ }; +#define VHT_SIG_A_1(rx_desc) ((rx_desc)->ppdu_start.ht_sig_vht_sig_a_1) +#define VHT_SIG_A_2(rx_desc) ((rx_desc)->ppdu_start.ht_sig_vht_sig_a_2) + +#define TSF_TIMESTAMP(rx_desc) ((rx_desc)->ppdu_end.tsf_timestamp) struct rx_mpdu_start { volatile diff --git a/core/dp/ol/inc/ol_htt_api.h b/core/dp/ol/inc/ol_htt_api.h index f55ddfb730ec..371af50bfa20 100644 --- a/core/dp/ol/inc/ol_htt_api.h +++ b/core/dp/ol/inc/ol_htt_api.h @@ -362,4 +362,7 @@ static inline void htt_ipa_uc_detach(struct htt_pdev_t *pdev) } #endif /* IPA_OFFLOAD */ +void htt_rx_mon_note_capture_channel(htt_pdev_handle pdev, int mon_ch); + +void ol_htt_mon_note_chan(ol_txrx_pdev_handle pdev, int mon_ch); #endif /* _OL_HTT_API__H_ */ diff --git a/core/dp/txrx/ol_rx.c b/core/dp/txrx/ol_rx.c index 350d4c7a298d..eea89ab5570a 100644 --- a/core/dp/txrx/ol_rx.c +++ b/core/dp/txrx/ol_rx.c @@ -57,6 +57,7 @@ #include <ipv6_defs.h> /* IPv6 header defs */ #include <ol_vowext_dbg_defs.h> #include <wma.h> +#include <cds_concurrency.h> #ifdef HTT_RX_RESTORE #if defined(CONFIG_CNSS) @@ -1243,7 +1244,10 @@ ol_rx_in_order_indication_handler(ol_txrx_pdev_handle pdev, qdf_nbuf_t head_msdu, tail_msdu = NULL; if (pdev) { - peer = ol_txrx_peer_find_by_id(pdev, peer_id); + if (qdf_unlikely(QDF_GLOBAL_MONITOR_MODE == cds_get_conparam())) + peer = pdev->self_peer; + else + peer = ol_txrx_peer_find_by_id(pdev, peer_id); htt_pdev = pdev->htt_pdev; } else { TXRX_PRINT(TXRX_PRINT_LEVEL_ERR, @@ -1374,6 +1378,17 @@ ol_rx_offload_paddr_deliver_ind_handler(htt_pdev_handle htt_pdev, htt_rx_msdu_buff_replenish(htt_pdev); } +/** + * ol_htt_mon_note_chan() - Update monitor channel information + * @pdev: handle to the physical device + * @mon_ch: Monitor channel + * + * Return: None + */ +void ol_htt_mon_note_chan(ol_txrx_pdev_handle pdev, int mon_ch) +{ + htt_rx_mon_note_capture_channel(pdev->htt_pdev, mon_ch); +} #ifdef NEVERDEFINED /** diff --git a/core/dp/txrx/ol_txrx.c b/core/dp/txrx/ol_txrx.c index ff9f0a8180ce..c2b2490960dc 100644 --- a/core/dp/txrx/ol_txrx.c +++ b/core/dp/txrx/ol_txrx.c @@ -470,7 +470,7 @@ void htt_pkt_log_init(struct ol_txrx_pdev_t *handle, void *scn) return; if (cds_get_conparam() != QDF_GLOBAL_FTM_MODE && - !WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + !QDF_IS_EPPING_ENABLED(cds_get_conparam())) { ol_pl_sethandle(&handle->pl_dev, scn); if (pktlogmod_init(scn)) qdf_print("%s: pktlogmod_init failed", __func__); @@ -489,7 +489,7 @@ void htt_pkt_log_init(struct ol_txrx_pdev_t *handle, void *scn) void htt_pktlogmod_exit(struct ol_txrx_pdev_t *handle, void *scn) { if (scn && cds_get_conparam() != QDF_GLOBAL_FTM_MODE && - !WLAN_IS_EPPING_ENABLED(cds_get_conparam()) && + !QDF_IS_EPPING_ENABLED(cds_get_conparam()) && handle->pkt_log_init) { pktlogmod_exit(scn); handle->pkt_log_init = false; @@ -1569,6 +1569,15 @@ ol_txrx_peer_attach(ol_txrx_vdev_handle vdev, uint8_t *peer_mac_addr) #ifdef QCA_SUPPORT_PEER_DATA_RX_RSSI peer->rssi_dbm = HTT_RSSI_INVALID; #endif + if ((QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) && + !pdev->self_peer) { + pdev->self_peer = peer; + /* + * No Tx in monitor mode, otherwise results in target assert. + * Setting disable_intrabss_fwd to true + */ + ol_vdev_rx_set_intrabss_fwd(vdev, true); + } ol_txrx_local_peer_id_alloc(pdev, peer); diff --git a/core/dp/txrx/ol_txrx_types.h b/core/dp/txrx/ol_txrx_types.h index a36346e63f1c..42d7b368427b 100644 --- a/core/dp/txrx/ol_txrx_types.h +++ b/core/dp/txrx/ol_txrx_types.h @@ -767,6 +767,7 @@ struct ol_txrx_pdev_t { void *lro_data; void (*lro_flush_cb)(void *); } lro_info; + struct ol_txrx_peer_t *self_peer; }; struct ol_txrx_ocb_chan_info { diff --git a/core/hdd/inc/qc_sap_ioctl.h b/core/hdd/inc/qc_sap_ioctl.h index 5a1bfbef9f48..232a1d1c6f6e 100644 --- a/core/hdd/inc/qc_sap_ioctl.h +++ b/core/hdd/inc/qc_sap_ioctl.h @@ -131,42 +131,43 @@ typedef struct { * (regardless of the incorrect comment in wireless.h!) */ -#define QCSAP_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0) -#define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1) +#define QCSAP_IOCTL_SETPARAM (SIOCIWFIRSTPRIV + 0) +#define QCSAP_IOCTL_GETPARAM (SIOCIWFIRSTPRIV + 1) /* (SIOCIWFIRSTPRIV+2) is unused */ -/* (SIOCIWFIRSTPRIV+3) is unused */ -#define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV+4) -#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV+5) -#define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV+6) -#define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV+7) -#define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV+8) -#define QCSAP_IOCTL_GET_CHANNEL (SIOCIWFIRSTPRIV+9) -#define QCSAP_IOCTL_ASSOC_STA_MACADDR (SIOCIWFIRSTPRIV+10) -#define QCSAP_IOCTL_DISASSOC_STA (SIOCIWFIRSTPRIV+11) +#define QCSAP_IOCTL_SET_NONE_GET_THREE (SIOCIWFIRSTPRIV + 3) +#define WE_GET_TSF 1 +#define QCSAP_IOCTL_GET_STAWPAIE (SIOCIWFIRSTPRIV + 4) +#define QCSAP_IOCTL_SETWPAIE (SIOCIWFIRSTPRIV + 5) +#define QCSAP_IOCTL_STOPBSS (SIOCIWFIRSTPRIV + 6) +#define QCSAP_IOCTL_VERSION (SIOCIWFIRSTPRIV + 7) +#define QCSAP_IOCTL_GET_WPS_PBC_PROBE_REQ_IES (SIOCIWFIRSTPRIV + 8) +#define QCSAP_IOCTL_GET_CHANNEL (SIOCIWFIRSTPRIV + 9) +#define QCSAP_IOCTL_ASSOC_STA_MACADDR (SIOCIWFIRSTPRIV + 10) +#define QCSAP_IOCTL_DISASSOC_STA (SIOCIWFIRSTPRIV + 11) /* (SIOCIWFIRSTPRIV+12) is unused */ /* Private ioctls and their sub-ioctls */ #define QCSAP_PRIV_GET_CHAR_SET_NONE (SIOCIWFIRSTPRIV + 13) #define QCSAP_GET_STATS 1 #define QCSAP_LIST_FW_PROFILE 2 -#define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV+14) +#define QCSAP_IOCTL_CLR_STATS (SIOCIWFIRSTPRIV + 14) -#define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV+15) +#define QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE (SIOCIWFIRSTPRIV + 15) #define WE_SET_WLAN_DBG 1 #define WE_SET_DP_TRACE 2 #define WE_SET_SAP_CHANNELS 3 -#define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV+16) +#define QCSAP_IOCTL_PRIV_SET_VAR_INT_GET_NONE (SIOCIWFIRSTPRIV + 16) #define WE_UNIT_TEST_CMD 7 -#define QCSAP_IOCTL_SET_CHANNEL_RANGE (SIOCIWFIRSTPRIV+17) +#define QCSAP_IOCTL_SET_CHANNEL_RANGE (SIOCIWFIRSTPRIV + 17) #define WE_P2P_NOA_CMD 2 -#define QCSAP_IOCTL_MODIFY_ACL (SIOCIWFIRSTPRIV+18) -#define QCSAP_IOCTL_GET_CHANNEL_LIST (SIOCIWFIRSTPRIV+19) -#define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV+20) -#define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV+21) -#define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV+22) -#define QCSAP_IOCTL_GET_INI_CFG (SIOCIWFIRSTPRIV+25) -#define QCSAP_IOCTL_SET_INI_CFG (SIOCIWFIRSTPRIV+26) +#define QCSAP_IOCTL_MODIFY_ACL (SIOCIWFIRSTPRIV + 18) +#define QCSAP_IOCTL_GET_CHANNEL_LIST (SIOCIWFIRSTPRIV + 19) +#define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV + 20) +#define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV + 21) +#define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV + 22) +#define QCSAP_IOCTL_GET_INI_CFG (SIOCIWFIRSTPRIV + 25) +#define QCSAP_IOCTL_SET_INI_CFG (SIOCIWFIRSTPRIV + 26) #define QCSAP_IOCTL_SET_TWO_INT_GET_NONE (SIOCIWFIRSTPRIV + 28) #ifdef DEBUG #define QCSAP_IOCTL_SET_FW_CRASH_INJECT 1 @@ -241,7 +242,10 @@ enum { QCASAP_CLEAR_STATS, QCASAP_SET_RADAR_DBG, QCSAP_GET_FW_PROFILE_DATA, - QCSAP_START_FW_PROFILING + QCSAP_START_FW_PROFILING, + QCSAP_CAP_TSF, + QCSAP_GET_TSF, + QCSAP_PARAM_CONC_SYSTEM_PREF }; int iw_softap_get_channel_list(struct net_device *dev, diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 98c9f9a35855..10b6c72a8331 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -463,6 +463,25 @@ typedef enum { #define CFG_REST_TIME_CONC_MAX (10000) #define CFG_REST_TIME_CONC_DEFAULT (100) +/* Mininum time spent on home channel before moving to a new channel to scan */ +#define CFG_MIN_REST_TIME_NAME "gMinRestTimeConc" +#define CFG_MIN_REST_TIME_MIN (0) +#define CFG_MIN_REST_TIME_MAX (50) +#define CFG_MIN_REST_TIME_DEFAULT (50) + +/* Data inactivity time in msec on bss channel that will be used + * by scan engine in firmware. + * for example if this value is 25ms then firmware will check for + * data inactivity every 25ms till gRestTimeConc is reached. + * If inactive then scan engine will move from home channel to + * scan the next frequency. + */ +#define CFG_IDLE_TIME_NAME "gIdleTimeConc" +#define CFG_IDLE_TIME_MIN (0) +#define CFG_IDLE_TIME_MAX (25) +#define CFG_IDLE_TIME_DEFAULT (25) + + #define CFG_NUM_STA_CHAN_COMBINED_CONC_NAME "gNumStaChanCombinedConc" #define CFG_NUM_STA_CHAN_COMBINED_CONC_MIN (1) #define CFG_NUM_STA_CHAN_COMBINED_CONC_MAX (255) @@ -2911,6 +2930,12 @@ enum dot11p_mode { #define CFG_INFORM_BSS_RSSI_RAW_MAX (1) #define CFG_INFORM_BSS_RSSI_RAW_DEFAULT (1) +/* GPIO pin to toggle when capture tsf */ +#define CFG_SET_TSF_GPIO_PIN_NAME "gtsf_gpio_pin" +#define CFG_SET_TSF_GPIO_PIN_MIN (0) +#define CFG_SET_TSF_GPIO_PIN_MAX (254) +#define TSF_GPIO_PIN_INVALID (255) +#define CFG_SET_TSF_GPIO_PIN_DEFAULT (TSF_GPIO_PIN_INVALID) /* * OBSS scan parameters @@ -2989,6 +3014,15 @@ enum dot11p_mode { #define CFG_ROAM_DENSE_MIN_APS_MAX (5) #define CFG_ROAM_DENSE_MIN_APS_DEFAULT (1) +/* + * Enable/Disable to initiate BUG report in case of fatal event + * Default: Enable + */ +#define CFG_ENABLE_FATAL_EVENT_TRIGGER "gEnableFatalEvent" +#define CFG_ENABLE_FATAL_EVENT_TRIGGER_MIN (0) +#define CFG_ENABLE_FATAL_EVENT_TRIGGER_MAX (1) +#define CFG_ENABLE_FATAL_EVENT_TRIGGER_DEFAULT (1) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -3096,6 +3130,10 @@ struct hdd_config { uint32_t nActiveMinChnTimeConc; /* in units of milliseconds */ uint32_t nActiveMaxChnTimeConc; /* in units of milliseconds */ uint32_t nRestTimeConc; /* in units of milliseconds */ + /* In units of milliseconds */ + uint32_t min_rest_time_conc; + /* In units of milliseconds */ + uint32_t idle_time_conc; uint8_t nNumStaChanCombinedConc; /* number of channels combined for */ /* STA in each split scan operation */ uint8_t nNumP2PChanCombinedConc; /* number of channels combined for */ @@ -3579,6 +3617,9 @@ struct hdd_config { uint16_t obss_passive_dwelltime; uint16_t obss_width_trigger_interval; uint8_t inform_bss_rssi_raw; +#ifdef WLAN_FEATURE_TSF + uint32_t tsf_gpio_pin; +#endif #ifdef QCA_WIFI_3_0_EMU bool enable_m2m_limitation; #endif @@ -3586,6 +3627,8 @@ struct hdd_config { uint32_t roam_dense_rssi_thresh_offset; bool ignore_peer_ht_opmode; uint32_t roam_dense_min_aps; + bool enable_fatal_event; + bool bpf_enabled; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/inc/wlan_hdd_host_offload.h b/core/hdd/inc/wlan_hdd_host_offload.h index 79d52ab3dbc9..873b6a73d1e3 100644 --- a/core/hdd/inc/wlan_hdd_host_offload.h +++ b/core/hdd/inc/wlan_hdd_host_offload.h @@ -57,4 +57,13 @@ typedef struct { struct qdf_mac_addr bssId; } tHostOffloadRequest, *tpHostOffloadRequest; +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void hdd_wlan_offload_event(uint8_t type, uint8_t state); +#else +static inline +void hdd_wlan_offload_event(uint8_t type, uint8_t state) +{ +} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + #endif /* __WLAN_HDD_HOST_OFFLOAD_H__ */ diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 39fe7e1a7d97..cdd77891d7e1 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -57,6 +57,7 @@ #ifdef FEATURE_WLAN_TDLS #include "wlan_hdd_tdls.h" #endif +#include "wlan_hdd_tsf.h" #include "wlan_hdd_cfg80211.h" #include <qdf_defer.h> #ifdef WLAN_FEATURE_MBSSID @@ -149,6 +150,8 @@ #define WLAN_WAIT_TIME_ANTENNA_MODE_REQ 3000 #define WLAN_WAIT_TIME_SET_DUAL_MAC_CFG 1500 +#define WLAN_WAIT_TIME_BPF 1000 + #define MAX_NUMBER_OF_ADAPTERS 4 #define MAX_CFG_STRING_LEN 255 @@ -244,12 +247,6 @@ */ #define WLAN_TFC_IPAUC_TX_DESC_RESERVE 100 -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) -#ifdef CONFIG_CNSS -#define cfg80211_vendor_cmd_reply(skb) cnss_vendor_cmd_reply(skb) -#endif -#endif - /* * NET_NAME_UNKNOWN is only introduced after Kernel 3.17, to have a macro * here if the Kernel version is less than 3.17 to avoid the interleave @@ -314,6 +311,7 @@ extern spinlock_t hdd_context_lock; #define LINK_CONTEXT_MAGIC 0x4C494E4B /* LINKSPEED */ #define LINK_STATUS_MAGIC 0x4C4B5354 /* LINKSTATUS(LNST) */ #define TEMP_CONTEXT_MAGIC 0x74656d70 /* TEMP (temperature) */ +#define BPF_CONTEXT_MAGIC 0x4575354 /* BPF */ /* MAX OS Q block time value in msec * Prevent from permanent stall, resume OS Q if timer expired */ @@ -627,6 +625,20 @@ typedef struct hdd_cfg80211_state_s { eP2PActionFrameState actionFrmState; } hdd_cfg80211_state_t; +/** + * struct hdd_mon_set_ch_info - Holds monitor mode channel switch params + * @channel: Channel number. + * @cb_mode: Channel bonding + * @channel_width: Channel width 0/1/2 for 20/40/80MHz respectively. + * @phy_mode: PHY mode + */ +struct hdd_mon_set_ch_info { + uint8_t channel; + uint8_t cb_mode; + uint32_t channel_width; + eCsrPhyMode phy_mode; +}; + struct hdd_station_ctx { /** Handle to the Wireless Extension State */ hdd_wext_state_t WextState; @@ -661,6 +673,8 @@ struct hdd_station_ctx { int staDebugState; uint8_t broadcast_ibss_staid; + + struct hdd_mon_set_ch_info ch_info; }; #define BSS_STOP 0 @@ -940,6 +954,14 @@ struct hdd_adapter_s { hdd_ap_ctx_t ap; } sessionCtx; +#ifdef WLAN_FEATURE_TSF + /* tsf value received from firmware */ + uint32_t tsf_low; + uint32_t tsf_high; + /* TSF capture state */ + enum hdd_tsf_capture_state tsf_state; +#endif + hdd_cfg80211_state_t cfg80211State; #ifdef WLAN_FEATURE_PACKET_FILTERING @@ -1123,6 +1145,18 @@ struct hdd_offloaded_packets_ctx { }; #endif +/** + * struct hdd_bpf_context - hdd Context for bpf + * @magic: magic number + * @completion: Completion variable for BPF Get Capability + * @capability_response: capabilities response received from fw + */ +struct hdd_bpf_context { + unsigned int magic; + struct completion completion; + struct sir_bpf_get_offload capability_response; +}; + /** Adapter structure definition */ struct hdd_context_s { @@ -1286,8 +1320,8 @@ struct hdd_context_s { struct work_struct sap_start_work; bool is_sap_restart_required; bool is_sta_connection_pending; - spinlock_t sap_update_info_lock; - spinlock_t sta_update_info_lock; + qdf_spinlock_t sap_update_info_lock; + qdf_spinlock_t sta_update_info_lock; uint8_t dev_dfs_cac_status; @@ -1364,6 +1398,7 @@ struct hdd_context_s { struct completion set_antenna_mode_cmpl; /* Current number of TX X RX chains being used */ enum antenna_mode current_antenna_mode; + bool bpf_enabled; }; /*--------------------------------------------------------------------------- @@ -1588,6 +1623,9 @@ uint8_t wlan_hdd_find_opclass(tHalHandle hal, uint8_t channel, uint8_t bw_offset); void hdd_update_config(hdd_context_t *hdd_ctx); +QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter, + struct net_device *dev, uint8_t oper_chan); + #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void); #else diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h index 3cc7dc7c0d18..9fcf9ecc2fed 100644 --- a/core/hdd/inc/wlan_hdd_p2p.h +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -51,6 +51,9 @@ #define WLAN_HDD_80211_FRM_DA_OFFSET 4 #define P2P_WILDCARD_SSID_LEN 7 #define P2P_WILDCARD_SSID "DIRECT-" +#define WLAN_HDD_80211_PEER_ADDR_OFFSET (WLAN_HDD_80211_FRM_DA_OFFSET + \ + MAC_ADDR_LEN) + #ifdef QCA_WIFI_3_0_EMU #define P2P_ROC_DURATION_MULTIPLIER_GO_PRESENT 2 diff --git a/core/hdd/inc/wlan_hdd_power.h b/core/hdd/inc/wlan_hdd_power.h index 2ce7f2dd2957..d872fae107ac 100644 --- a/core/hdd/inc/wlan_hdd_power.h +++ b/core/hdd/inc/wlan_hdd_power.h @@ -126,6 +126,22 @@ struct pkt_filter_cfg { #endif +/** + * enum suspend_resume_state - Suspend resume state + * @HDD_WLAN_EARLY_SUSPEND: Early suspend state. + * @HDD_WLAN_SUSPEND: Suspend state. + * @HDD_WLAN_EARLY_RESUME: Early resume state. + * @HDD_WLAN_RESUME: Resume state. + * + * Suspend state to indicate in diag event of suspend resume. + */ +enum suspend_resume_state { + HDD_WLAN_EARLY_SUSPEND, + HDD_WLAN_SUSPEND, + HDD_WLAN_EARLY_RESUME, + HDD_WLAN_RESUME +}; + /* SSR shutdown & re-init functions */ QDF_STATUS hdd_wlan_shutdown(void); @@ -171,4 +187,12 @@ int wlan_hdd_ipv4_changed(struct notifier_block *nb, int wlan_hdd_ipv6_changed(struct notifier_block *nb, unsigned long data, void *arg); +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void hdd_wlan_suspend_resume_event(uint8_t state); +#else +static inline +void hdd_wlan_suspend_resume_event(uint8_t state) {} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + + #endif /* __WLAN_HDD_POWER_H */ diff --git a/core/hdd/inc/wlan_hdd_tdls.h b/core/hdd/inc/wlan_hdd_tdls.h index 8a4cd45e7f89..2d446b4fe504 100644 --- a/core/hdd/inc/wlan_hdd_tdls.h +++ b/core/hdd/inc/wlan_hdd_tdls.h @@ -161,6 +161,30 @@ typedef enum eTDLSLinkStatus { } tTDLSLinkStatus; /** + * enum tdls_teardown_reason - Reason for TDLS teardown + * @eTDLS_TEARDOWN_EXT_CTRL: Reason ext ctrl. + * @eTDLS_TEARDOWN_CONCURRENCY: Reason concurrency. + * @eTDLS_TEARDOWN_RSSI_THRESHOLD: Reason rssi threshold. + * @eTDLS_TEARDOWN_TXRX_THRESHOLD: Reason txrx threshold. + * @eTDLS_TEARDOWN_BTCOEX: Reason BTCOEX. + * @eTDLS_TEARDOWN_SCAN: Reason scan. + * @eTDLS_TEARDOWN_BSS_DISCONNECT: Reason bss disconnected. + * @eTDLS_TEARDOWN_ANTENNA_SWITCH: Disconnected due to antenna switch + * + * Reason to indicate in diag event of tdls teardown. + */ +enum tdls_teardown_reason { + eTDLS_TEARDOWN_EXT_CTRL, + eTDLS_TEARDOWN_CONCURRENCY, + eTDLS_TEARDOWN_RSSI_THRESHOLD, + eTDLS_TEARDOWN_TXRX_THRESHOLD, + eTDLS_TEARDOWN_BTCOEX, + eTDLS_TEARDOWN_SCAN, + eTDLS_TEARDOWN_BSS_DISCONNECT, + eTDLS_TEARDOWN_ANTENNA_SWITCH, +}; + +/** * enum tTDLSLinkReason - tdls link reason * * @eTDLS_LINK_SUCCESS: Success @@ -607,7 +631,8 @@ int hdd_set_tdls_offchannel(hdd_context_t *hdd_ctx, int offchannel); int hdd_set_tdls_secoffchanneloffset(hdd_context_t *hdd_ctx, int offchanoffset); int hdd_set_tdls_offchannelmode(hdd_adapter_t *adapter, int offchanmode); int hdd_set_tdls_scan_type(hdd_context_t *hdd_ctx, int val); -void hdd_tdls_pre_init(hdd_context_t *hdd_ctx); +void hdd_tdls_context_init(hdd_context_t *hdd_ctx); +void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx); #else static inline void hdd_tdls_notify_mode_change(hdd_adapter_t *adapter, @@ -622,7 +647,28 @@ static inline void wlan_hdd_tdls_exit(hdd_adapter_t *adapter) { } -static inline void hdd_tdls_pre_init(hdd_context_t *hdd_ctx) { } +static inline void hdd_tdls_context_init(hdd_context_t *hdd_ctx) { } +static inline void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx) { } #endif /* End of FEATURE_WLAN_TDLS */ +#ifdef FEATURE_WLAN_DIAG_SUPPORT +void hdd_send_wlan_tdls_teardown_event(uint32_t reason, + uint8_t *peer_mac); +void hdd_wlan_tdls_enable_link_event(const uint8_t *peer_mac, + uint8_t is_off_chan_supported, + uint8_t is_off_chan_configured, + uint8_t is_off_chan_established); +void hdd_wlan_block_scan_by_tdls_event(void); +#else +static inline +void hdd_send_wlan_tdls_teardown_event(uint32_t reason, + uint8_t *peer_mac) {} +static inline +void hdd_wlan_tdls_enable_link_event(const uint8_t *peer_mac, + uint8_t is_off_chan_supported, + uint8_t is_off_chan_configured, + uint8_t is_off_chan_established) {} +static inline void hdd_wlan_block_scan_by_tdls_event(void) {} +#endif /* FEATURE_WLAN_DIAG_SUPPORT */ + #endif /* __HDD_TDLS_H */ diff --git a/core/hdd/inc/wlan_hdd_tsf.h b/core/hdd/inc/wlan_hdd_tsf.h new file mode 100644 index 000000000000..f251327d7f06 --- /dev/null +++ b/core/hdd/inc/wlan_hdd_tsf.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#if !defined WLAN_HDD_TSF_H +#define WLAN_HDD_TSF_H + +/** + * enum hdd_tsf_get_state - status of get tsf action + * @TSF_RETURN: get tsf + * @TSF_STA_NOT_CONNECTED_NO_TSF: sta not connected to ap + * @TSF_NOT_RETURNED_BY_FW: fw not returned tsf + * @TSF_CURRENT_IN_CAP_STATE: driver in capture state + * @TSF_CAPTURE_FAIL: capture fail + * @TSF_GET_FAIL: get fail + * @TSF_RESET_GPIO_FAIL: GPIO reset fail + * @TSF_SAP_NOT_STARTED_NO_TSF SAP not started + */ +enum hdd_tsf_get_state { + TSF_RETURN = 0, + TSF_STA_NOT_CONNECTED_NO_TSF, + TSF_NOT_RETURNED_BY_FW, + TSF_CURRENT_IN_CAP_STATE, + TSF_CAPTURE_FAIL, + TSF_GET_FAIL, + TSF_RESET_GPIO_FAIL, + TSF_SAP_NOT_STARTED_NO_TSF +}; + +/** + * enum hdd_tsf_capture_state - status of capture + * @TSF_IDLE: idle + * @TSF_CAP_STATE: current is in capture state + */ +enum hdd_tsf_capture_state { + TSF_IDLE = 0, + TSF_CAP_STATE +}; + +#ifdef WLAN_FEATURE_TSF +void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx); +int hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len); +int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len); +#else +static inline void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx) +{ + return; +} + +static inline int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, + int len) +{ + return -ENOTSUPP; +} + +static inline int +hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len) +{ + return -ENOTSUPP; +} +#endif + +#endif diff --git a/core/hdd/inc/wlan_hdd_tx_rx.h b/core/hdd/inc/wlan_hdd_tx_rx.h index df570cd83e48..526d8d098536 100644 --- a/core/hdd/inc/wlan_hdd_tx_rx.h +++ b/core/hdd/inc/wlan_hdd_tx_rx.h @@ -128,11 +128,9 @@ static inline void wlan_hdd_log_eapol(struct sk_buff *skb, } #endif /* FEATURE_WLAN_DIAG_SUPPORT */ - const char *hdd_reason_type_to_string(enum netif_reason_type reason); const char *hdd_action_type_to_string(enum netif_action_type action); void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter, enum netif_action_type action, enum netif_reason_type reason); - - +int hdd_set_mon_rx_cb(struct net_device *dev); #endif /* end #if !defined(WLAN_HDD_TX_RX_H) */ diff --git a/core/hdd/src/wlan_hdd_assoc.c b/core/hdd/src/wlan_hdd_assoc.c index 67066ebc1733..d1464e4d5eb6 100644 --- a/core/hdd/src/wlan_hdd_assoc.c +++ b/core/hdd/src/wlan_hdd_assoc.c @@ -3172,13 +3172,22 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, pRoamInfo-> peerMac.bytes, true); - if (NULL != curr_peer - && TDLS_IS_CONNECTED(curr_peer)) { + if (NULL != curr_peer) { + hdd_info("Current status for peer " MAC_ADDRESS_STR " is %d", + MAC_ADDR_ARRAY(pRoamInfo->peerMac.bytes), + curr_peer->link_status); + if (TDLS_IS_CONNECTED(curr_peer)) { hdd_roam_deregister_tdlssta (pAdapter, pRoamInfo->staId); wlan_hdd_tdls_decrement_peer_count (pAdapter); + } else if (eTDLS_LINK_CONNECTING == + curr_peer->link_status) { + hdd_roam_deregister_tdlssta + (pAdapter, + pRoamInfo->staId); + } } wlan_hdd_tdls_reset_peer(pAdapter, pRoamInfo-> @@ -3209,6 +3218,8 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, pRoamInfo->peerMac.bytes, true); wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, pRoamInfo->reasonCode); + hdd_send_wlan_tdls_teardown_event(eTDLS_TEARDOWN_BSS_DISCONNECT, + curr_peer->peerMac); status = QDF_STATUS_SUCCESS; break; } @@ -3388,6 +3399,9 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, wlan_hdd_tdls_indicate_teardown (pHddTdlsCtx->pAdapter, curr_peer, reason); + hdd_send_wlan_tdls_teardown_event( + eTDLS_TEARDOWN_BSS_DISCONNECT, + curr_peer->peerMac); } else { hddLog(LOGE, FL @@ -3436,6 +3450,9 @@ hdd_roam_tdls_status_update_handler(hdd_adapter_t *pAdapter, wlan_hdd_tdls_indicate_teardown (pHddTdlsCtx->pAdapter, curr_peer, reason); + hdd_send_wlan_tdls_teardown_event( + eTDLS_TEARDOWN_BSS_DISCONNECT, + curr_peer->peerMac); } else { hddLog(LOGE, FL @@ -4296,6 +4313,19 @@ hdd_sme_roam_callback(void *pContext, tCsrRoamInfo *pRoamInfo, uint32_t roamId, break; } #endif /* FEATURE_WLAN_ESE */ + case eCSR_ROAM_STA_CHANNEL_SWITCH: + hdd_info("channel switch for session:%d to channel:%d", + pAdapter->sessionId, pRoamInfo->chan_info.chan_id); + + status = hdd_chan_change_notify(pAdapter, pAdapter->dev, + pRoamInfo->chan_info.chan_id); + if (QDF_IS_STATUS_ERROR(status)) + hdd_err("channel change notification failed"); + + status = cds_set_hw_mode_on_channel_switch(pAdapter->sessionId); + if (QDF_IS_STATUS_ERROR(status)) + hdd_info("set hw mode change not done"); + break; default: break; } @@ -4971,8 +5001,41 @@ static int __iw_set_essid(struct net_device *dev, (WLAN_HDD_GET_CTX(pAdapter))->config-> AdHocChannel5G); } + /* + * Change conn_state to connecting before sme_roam_connect(), + * because sme_roam_connect() has a direct path to call + * hdd_sme_roam_callback(), which will change the conn_state + * If direct path, conn_state will be accordingly changed to + * NotConnected or Associated by either + * hdd_association_completion_handler() or hdd_dis_connect_handler() + * in sme_RoamCallback()if sme_RomConnect is to be queued, + * Connecting state will remain until it is completed. + * + * If connection state is not changed, + * connection state will remain in eConnectionState_NotConnected state. + * In hdd_association_completion_handler, "hddDisconInProgress" is + * set to true if conn state is eConnectionState_NotConnected. + * If "hddDisconInProgress" is set to true then cfg80211 layer is not + * informed of connect result indication which is an issue. + */ + if (QDF_STA_MODE == pAdapter->device_mode || + QDF_P2P_CLIENT_MODE == pAdapter->device_mode) { + hdd_info("Set HDD connState to eConnectionState_Connecting"); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Connecting); + } + status = sme_roam_connect(hHal, pAdapter->sessionId, &(pWextState->roamProfile), &roamId); + if ((QDF_STATUS_SUCCESS != status) && + (QDF_STA_MODE == pAdapter->device_mode || + QDF_P2P_CLIENT_MODE == pAdapter->device_mode)) { + hdd_err("sme_roam_connect (session %d) failed with status %d. -> NotConnected", + pAdapter->sessionId, status); + /* change back to NotAssociated */ + hdd_conn_set_connection_state(pAdapter, + eConnectionState_NotConnected); + } pRoamProfile->ChannelInfo.ChannelList = NULL; pRoamProfile->ChannelInfo.numOfChannels = 0; diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index eba3d85c8a67..e5a3164a9443 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -44,6 +44,7 @@ #include <csr_api.h> #include <wlan_hdd_misc.h> #include <wlan_hdd_napi.h> +#include <cds_concurrency.h> static void cb_notify_set_roam_prefer5_g_hz(hdd_context_t *pHddCtx, unsigned long notifyId) @@ -802,6 +803,20 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_REST_TIME_CONC_MIN, CFG_REST_TIME_CONC_MAX), + REG_VARIABLE(CFG_MIN_REST_TIME_NAME, WLAN_PARAM_Integer, + struct hdd_config, min_rest_time_conc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MIN_REST_TIME_DEFAULT, + CFG_MIN_REST_TIME_MIN, + CFG_MIN_REST_TIME_MAX), + + REG_VARIABLE(CFG_IDLE_TIME_NAME , WLAN_PARAM_Integer, + struct hdd_config, idle_time_conc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_IDLE_TIME_DEFAULT, + CFG_IDLE_TIME_MIN, + CFG_IDLE_TIME_MAX) , + REG_VARIABLE(CFG_NUM_STA_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, struct hdd_config, nNumStaChanCombinedConc, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -3725,6 +3740,15 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_INFORM_BSS_RSSI_RAW_MIN, CFG_INFORM_BSS_RSSI_RAW_MAX), +#ifdef WLAN_FEATURE_TSF + REG_VARIABLE(CFG_SET_TSF_GPIO_PIN_NAME, WLAN_PARAM_Integer, + struct hdd_config, tsf_gpio_pin, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SET_TSF_GPIO_PIN_DEFAULT, + CFG_SET_TSF_GPIO_PIN_MIN, + CFG_SET_TSF_GPIO_PIN_MAX), +#endif + #ifdef QCA_WIFI_3_0_EMU REG_VARIABLE(CFG_ENABLE_M2M_LIMITATION, WLAN_PARAM_Integer, struct hdd_config, enable_m2m_limitation, @@ -3763,6 +3787,15 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ROAM_DENSE_MIN_APS_MIN, CFG_ROAM_DENSE_MIN_APS_MAX), + REG_VARIABLE(CFG_ENABLE_FATAL_EVENT_TRIGGER, WLAN_PARAM_Integer, + struct hdd_config, enable_fatal_event, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_FATAL_EVENT_TRIGGER_DEFAULT, + CFG_ENABLE_FATAL_EVENT_TRIGGER_MIN, + CFG_ENABLE_FATAL_EVENT_TRIGGER_MAX), + + }; @@ -5354,8 +5387,18 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CFG_IGNORE_PEER_HT_MODE_NAME, pHddCtx->config->ignore_peer_ht_opmode); hdd_info("Name = [%s] Value = [%u]", + CFG_ENABLE_FATAL_EVENT_TRIGGER, + pHddCtx->config->enable_fatal_event); + hdd_info("Name = [%s] Value = [%u]", CFG_ROAM_DENSE_MIN_APS, pHddCtx->config->roam_dense_min_aps); + hdd_info("Name = [%s] Value = [%u]", + CFG_MIN_REST_TIME_NAME, + pHddCtx->config->min_rest_time_conc); + hdd_info("Name = [%s] Value = [%u]", + CFG_IDLE_TIME_NAME, + pHddCtx->config->idle_time_conc); + } @@ -5454,6 +5497,66 @@ config_exit: } /** + * hdd_disable_runtime_pm() - Override to disable runtime_pm. + * @cfg_ini: Handle to struct hdd_config + * + * Return: None + */ +#ifdef FEATURE_RUNTIME_PM +static void hdd_disable_runtime_pm(struct hdd_config *cfg_ini) +{ + cfg_ini->runtime_pm = 0; +} +#else +static void hdd_disable_runtime_pm(struct hdd_config *cfg_ini) +{ +} +#endif + +/** + * hdd_disable_auto_shutdown() - Override to disable auto_shutdown. + * @cfg_ini: Handle to struct hdd_config + * + * Return: None + */ +#ifdef FEATURE_WLAN_AUTO_SHUTDOWN +static void hdd_disable_auto_shutdown(struct hdd_config *cfg_ini) +{ + cfg_ini->WlanAutoShutdown = 0; +} +#else +static void hdd_disable_auto_shutdown(struct hdd_config *cfg_ini) +{ +} +#endif + +/** + * hdd_override_all_ps() - overrides to disables all the powersave features. + * @hdd_ctx: Pointer to HDD context. + * Overrides below powersave ini configurations. + * gEnableImps=0 + * gEnableBmps=0 + * gRuntimePM=0 + * gWlanAutoShutdown = 0 + * gEnableSuspend=0 + * gEnablePowerSaveOffload=0 + * gEnableWoW=0 + * + * Return: None + */ +static void hdd_override_all_ps(hdd_context_t *hdd_ctx) +{ + struct hdd_config *cfg_ini = hdd_ctx->config; + + cfg_ini->fIsImpsEnabled = 0; + cfg_ini->is_ps_enabled = 0; + hdd_disable_runtime_pm(cfg_ini); + hdd_disable_auto_shutdown(cfg_ini); + cfg_ini->enablePowersaveOffload = 0; + cfg_ini->wowEnable = 0; +} + +/** * hdd_parse_config_ini() - parse the ini configuration file * @pHddCtx: the pointer to hdd context * @@ -5556,6 +5659,8 @@ QDF_STATUS hdd_parse_config_ini(hdd_context_t *pHddCtx) hdd_napi_event(NAPI_EVT_INI_FILE, (void *)pHddCtx->config->napi_enable); #endif /* FEATURE_NAPI */ + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) + hdd_override_all_ps(pHddCtx); config_exit: release_firmware(fw); @@ -6565,6 +6670,8 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) smeConfig->csrConfig.nPassiveMinChnTimeConc = pConfig->nPassiveMinChnTimeConc; smeConfig->csrConfig.nRestTimeConc = pConfig->nRestTimeConc; + smeConfig->csrConfig.min_rest_time_conc = pConfig->min_rest_time_conc; + smeConfig->csrConfig.idle_time_conc = pConfig->idle_time_conc; smeConfig->csrConfig.nNumStaChanCombinedConc = pConfig->nNumStaChanCombinedConc; smeConfig->csrConfig.nNumP2PChanCombinedConc = @@ -6799,6 +6906,8 @@ QDF_STATUS hdd_set_sme_config(hdd_context_t *pHddCtx) pHddCtx->config->obss_passive_dwelltime; smeConfig->csrConfig.ignore_peer_ht_opmode = pConfig->ignore_peer_ht_opmode; + smeConfig->csrConfig.enable_fatal_event = + pConfig->enable_fatal_event; status = sme_update_config(pHddCtx->hHal, smeConfig); if (!QDF_IS_STATUS_SUCCESS(status)) { diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index c8af93844f02..79cc8b41943a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -42,9 +42,6 @@ #include <net/arp.h> #include <net/cfg80211.h> #include <qdf_trace.h> -#ifdef CONFIG_CNSS -#include <net/cnss.h> -#endif #include <wlan_hdd_wowl.h> #include <ani_global.h> #include "sir_params.h" @@ -177,12 +174,6 @@ static struct ieee80211_channel hdd_channels_2_4_ghz[] = { HDD2GHZCHAN(2484, 14, 0), }; -static struct ieee80211_channel hdd_social_channels_2_4_ghz[] = { - HDD2GHZCHAN(2412, 1, 0), - HDD2GHZCHAN(2437, 6, 0), - HDD2GHZCHAN(2462, 11, 0), -}; - static struct ieee80211_channel hdd_channels_5_ghz[] = { HDD5GHZCHAN(5180, 36, 0), HDD5GHZCHAN(5200, 40, 0), @@ -271,23 +262,6 @@ static struct ieee80211_supported_band wlan_hdd_band_2_4_ghz = { .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, }; -static struct ieee80211_supported_band wlan_hdd_band_p2p_2_4_ghz = { - .channels = hdd_social_channels_2_4_ghz, - .n_channels = ARRAY_SIZE(hdd_social_channels_2_4_ghz), - .band = IEEE80211_BAND_2GHZ, - .bitrates = g_mode_rates, - .n_bitrates = g_mode_rates_size, - .ht_cap.ht_supported = 1, - .ht_cap.cap = IEEE80211_HT_CAP_SGI_20 - | IEEE80211_HT_CAP_GRN_FLD - | IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_LSIG_TXOP_PROT, - .ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, - .ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, - .ht_cap.mcs.rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0,}, - .ht_cap.mcs.rx_highest = cpu_to_le16(72), - .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, -}; - static struct ieee80211_supported_band wlan_hdd_band_5_ghz = { .channels = hdd_channels_5_ghz, .n_channels = ARRAY_SIZE(hdd_channels_5_ghz), @@ -505,6 +479,24 @@ wlan_hdd_p2p_p2p_iface_limit[] = { }, }; +static const struct ieee80211_iface_limit + wlan_hdd_mon_iface_limit[] = { + { + .max = 3, /* Monitor interface */ + .types = BIT(NL80211_IFTYPE_MONITOR), + }, +}; + +static struct ieee80211_iface_combination + wlan_hdd_mon_iface[] = { + { + .limits = wlan_hdd_mon_iface_limit, + .max_interfaces = 3, + .num_different_channels = 2, + .n_limits = ARRAY_SIZE(wlan_hdd_mon_iface_limit), + }, +}; + static struct ieee80211_iface_combination wlan_hdd_iface_combination[] = { /* STA */ @@ -585,7 +577,7 @@ static struct ieee80211_iface_combination }; static struct cfg80211_ops wlan_hdd_cfg80211_ops; - +struct hdd_bpf_context bpf_context; #ifdef WLAN_NL80211_TESTMODE enum wlan_hdd_tm_attr { @@ -1773,13 +1765,8 @@ void wlan_hdd_cfg80211_acs_ch_select_evt(hdd_adapter_t *adapter) con_sap_adapter = hdd_get_con_sap_adapter(adapter, false); if (con_sap_adapter && test_bit(ACS_PENDING, &con_sap_adapter->event_flags)) { -#ifdef CONFIG_CNSS - cnss_init_delayed_work(&con_sap_adapter->acs_pending_work, - wlan_hdd_cfg80211_start_pending_acs); -#else INIT_DELAYED_WORK(&con_sap_adapter->acs_pending_work, wlan_hdd_cfg80211_start_pending_acs); -#endif /* Lets give 500ms for OBSS + START_BSS to complete */ schedule_delayed_work(&con_sap_adapter->acs_pending_work, msecs_to_jiffies(500)); @@ -3563,7 +3550,8 @@ static int __wlan_hdd_cfg80211_wifi_logger_get_ring_data(struct wiphy *wiphy, status = cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL, WLAN_LOG_INDICATOR_FRAMEWORK, - WLAN_LOG_REASON_CODE_UNUSED); + WLAN_LOG_REASON_CODE_UNUSED, + true, false); if (QDF_STATUS_SUCCESS != status) { hddLog(LOGE, FL("Failed to trigger bug report")); return -EINVAL; @@ -4913,7 +4901,363 @@ static int wlan_hdd_cfg80211_txpower_scale_decr_db(struct wiphy *wiphy, return ret; } +/* + * define short names for the global vendor params + * used by __wlan_hdd_cfg80211_bpf_offload() + */ +#define BPF_INVALID \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID +#define BPF_SET_RESET \ + QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER +#define BPF_VERSION \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION +#define BPF_FILTER_ID \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID +#define BPF_PACKET_SIZE \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE +#define BPF_CURRENT_OFFSET \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET +#define BPF_PROGRAM \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM +#define BPF_MAX \ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + +static const struct nla_policy +wlan_hdd_bpf_offload_policy[BPF_MAX + 1] = { + [BPF_SET_RESET] = {.type = NLA_U32}, + [BPF_VERSION] = {.type = NLA_U32}, + [BPF_FILTER_ID] = {.type = NLA_U32}, + [BPF_PACKET_SIZE] = {.type = NLA_U32}, + [BPF_CURRENT_OFFSET] = {.type = NLA_U32}, + [BPF_PROGRAM] = {.type = NLA_U8}, +}; + +/** + * hdd_get_bpf_offload_cb() - Callback function to BPF Offload + * @hdd_context: hdd_context + * @bpf_get_offload: struct for get offload + * + * This function receives the response/data from the lower layer and + * checks to see if the thread is still waiting then post the results to + * upper layer, if the request has timed out then ignore. + * + * Return: None + */ +void hdd_get_bpf_offload_cb(void *hdd_context, + struct sir_bpf_get_offload *data) +{ + hdd_context_t *hdd_ctx = hdd_context; + struct hdd_bpf_context *context; + + ENTER(); + + if (wlan_hdd_validate_context(hdd_ctx) || !data) { + hddLog(LOGE, FL("HDD context is invalid or data(%p) is null"), + data); + return; + } + + spin_lock(&hdd_context_lock); + + context = &bpf_context; + /* The caller presumably timed out so there is nothing we can do */ + if (context->magic != BPF_CONTEXT_MAGIC) { + spin_unlock(&hdd_context_lock); + return; + } + + /* context is valid so caller is still waiting */ + /* paranoia: invalidate the magic */ + context->magic = 0; + + context->capability_response = *data; + complete(&context->completion); + + spin_unlock(&hdd_context_lock); + + return; +} + +/** + * hdd_post_get_bpf_capabilities_rsp() - Callback function to BPF Offload + * @hdd_context: hdd_context + * @bpf_get_offload: struct for get offload + * + * Return: 0 on success, error number otherwise. + */ +static int hdd_post_get_bpf_capabilities_rsp(hdd_context_t *hdd_ctx, + struct sir_bpf_get_offload *bpf_get_offload) +{ + struct sk_buff *skb; + uint32_t nl_buf_len; + + ENTER(); + + nl_buf_len = NLMSG_HDRLEN; + nl_buf_len += + (sizeof(bpf_get_offload->max_bytes_for_bpf_inst) + NLA_HDRLEN) + + (sizeof(bpf_get_offload->bpf_version) + NLA_HDRLEN); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(hdd_ctx->wiphy, nl_buf_len); + if (!skb) { + hddLog(LOGE, FL("cfg80211_vendor_cmd_alloc_reply_skb failed")); + return -ENOMEM; + } + + hddLog(LOG1, "BPF Version: %u BPF max bytes: %u", + bpf_get_offload->bpf_version, + bpf_get_offload->max_bytes_for_bpf_inst); + + if (nla_put_u32(skb, BPF_PACKET_SIZE, + bpf_get_offload->max_bytes_for_bpf_inst) || + nla_put_u32(skb, BPF_VERSION, bpf_get_offload->bpf_version)) { + hddLog(LOGE, FL("nla put failure")); + goto nla_put_failure; + } + + cfg80211_vendor_cmd_reply(skb); + EXIT(); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -EINVAL; +} + +/** + * hdd_get_bpf_offload - Get BPF offload Capabilities + * @hdd_ctx: Hdd context + * + * Return: 0 on success, errno on failure + */ +static int hdd_get_bpf_offload(hdd_context_t *hdd_ctx) +{ + unsigned long rc; + struct hdd_bpf_context *context; + QDF_STATUS status; + int ret; + + ENTER(); + + spin_lock(&hdd_context_lock); + context = &bpf_context; + context->magic = BPF_CONTEXT_MAGIC; + INIT_COMPLETION(context->completion); + spin_unlock(&hdd_context_lock); + + status = sme_get_bpf_offload_capabilities(hdd_ctx->hHal); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, FL("Unable to retrieve BPF caps")); + return -EINVAL; + } + /* request was sent -- wait for the response */ + rc = wait_for_completion_timeout(&context->completion, + msecs_to_jiffies(WLAN_WAIT_TIME_BPF)); + if (!rc) { + hddLog(LOGE, FL("Target response timed out")); + spin_lock(&hdd_context_lock); + context->magic = 0; + spin_unlock(&hdd_context_lock); + + return -ETIMEDOUT; + } + ret = hdd_post_get_bpf_capabilities_rsp(hdd_ctx, + &bpf_context.capability_response); + if (ret) + hddLog(LOGE, FL("Failed to post get bpf capabilities")); + + EXIT(); + return ret; +} + +/** + * hdd_set_reset_bpf_offload - Post set/reset bpf to SME + * @hdd_ctx: Hdd context + * @tb: Length of @data + * @session_id: Session identifier + * + * Return: 0 on success; errno on failure + */ +static int hdd_set_reset_bpf_offload(hdd_context_t *hdd_ctx, + struct nlattr **tb, + uint8_t session_id) +{ + struct sir_bpf_set_offload *bpf_set_offload; + QDF_STATUS status; + int prog_len; + + ENTER(); + + bpf_set_offload = qdf_mem_malloc(sizeof(*bpf_set_offload)); + if (bpf_set_offload == NULL) { + hddLog(LOGE, FL("qdf_mem_malloc failed for bpf_set_offload")); + return -ENOMEM; + } + qdf_mem_zero(bpf_set_offload, sizeof(*bpf_set_offload)); + + /* Parse and fetch bpf packet size */ + if (!tb[BPF_PACKET_SIZE]) { + hddLog(LOGE, FL("attr bpf packet size failed")); + goto fail; + } + bpf_set_offload->total_length = nla_get_u32(tb[BPF_PACKET_SIZE]); + + if (!bpf_set_offload->total_length) { + hddLog(LOG1, FL("BPF reset packet filter received")); + goto post_sme; + } + + /* Parse and fetch bpf program */ + if (!tb[BPF_PROGRAM]) { + hddLog(LOGE, FL("attr bpf program failed")); + goto fail; + } + + prog_len = nla_len(tb[BPF_PROGRAM]); + bpf_set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * prog_len); + bpf_set_offload->current_length = prog_len; + nla_memcpy(bpf_set_offload->program, tb[BPF_PROGRAM], prog_len); + bpf_set_offload->session_id = session_id; + + /* Parse and fetch filter Id */ + if (!tb[BPF_FILTER_ID]) { + hddLog(LOGE, FL("attr filter id failed")); + goto fail; + } + bpf_set_offload->filter_id = nla_get_u32(tb[BPF_FILTER_ID]); + + /* Parse and fetch current offset */ + if (!tb[BPF_CURRENT_OFFSET]) { + hddLog(LOGE, FL("attr current offset failed")); + goto fail; + } + bpf_set_offload->current_offset = nla_get_u32(tb[BPF_CURRENT_OFFSET]); + +post_sme: + hddLog(LOG1, FL("Posting BPF SET/RESET to SME, session_id: %d Bpf Version: %d filter ID: %d total_length: %d current_length: %d current offset: %d"), + bpf_set_offload->session_id, + bpf_set_offload->version, + bpf_set_offload->filter_id, + bpf_set_offload->total_length, + bpf_set_offload->current_length, + bpf_set_offload->current_offset); + + status = sme_set_bpf_instructions(hdd_ctx->hHal, bpf_set_offload); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hddLog(LOGE, + FL("sme_set_bpf_instructions failed(err=%d)"), status); + goto fail; + } + EXIT(); + if (bpf_set_offload->current_length) + qdf_mem_free(bpf_set_offload->program); + qdf_mem_free(bpf_set_offload); + return 0; + +fail: + if (bpf_set_offload->current_length) + qdf_mem_free(bpf_set_offload->program); + qdf_mem_free(bpf_set_offload); + return -EINVAL; +} + +/** + * wlan_hdd_cfg80211_bpf_offload() - Set/Reset to BPF Offload + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Return: 0 on success; errno on failure + */ +static int +__wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + struct net_device *dev = wdev->netdev; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + struct nlattr *tb[BPF_MAX + 1]; + int ret_val, packet_filter_subcmd; + + ENTER(); + + ret_val = wlan_hdd_validate_context(hdd_ctx); + if (ret_val) + return ret_val; + + if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { + hddLog(LOGE, FL("Command not allowed in FTM mode")); + return -EINVAL; + } + + if (!hdd_ctx->bpf_enabled) { + hddLog(LOGE, FL("BPF offload is not supported by firmware")); + return -ENOTSUPP; + } + + if (nla_parse(tb, BPF_MAX, data, data_len, + wlan_hdd_bpf_offload_policy)) { + hddLog(LOGE, FL("Invalid ATTR")); + return -EINVAL; + } + + if (!tb[BPF_SET_RESET]) { + hddLog(LOGE, FL("attr bpf set reset failed")); + return -EINVAL; + } + + packet_filter_subcmd = nla_get_u32(tb[BPF_SET_RESET]); + + if (packet_filter_subcmd == QCA_WLAN_GET_PACKET_FILTER) + return hdd_get_bpf_offload(hdd_ctx); + else + return hdd_set_reset_bpf_offload(hdd_ctx, tb, + pAdapter->sessionId); +} + +/** + * wlan_hdd_cfg80211_bpf_offload() - SSR Wrapper to BPF Offload + * @wiphy: wiphy structure pointer + * @wdev: Wireless device structure pointer + * @data: Pointer to the data received + * @data_len: Length of @data + * + * Return: 0 on success; errno on failure + */ + +static int wlan_hdd_cfg80211_bpf_offload(struct wiphy *wiphy, + struct wireless_dev *wdev, + const void *data, int data_len) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_bpf_offload(wiphy, wdev, data, data_len); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** + * hdd_init_bpf_completion() - Initialize the completion event for bpf + * + * Return: None + */ +void hdd_init_bpf_completion(void) +{ + init_completion(&bpf_context.completion); +} +#undef BPF_INVALID +#undef BPF_SET_RESET +#undef BPF_VERSION +#undef BPF_ID +#undef BPF_PACKET_SIZE +#undef BPF_CURRENT_OFFSET +#undef BPF_PROGRAM +#undef BPF_MAX const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { { .info.vendor_id = QCA_NL80211_VENDOR_ID, @@ -5368,6 +5712,14 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = { WIPHY_VENDOR_CMD_NEED_RUNNING, .doit = wlan_hdd_cfg80211_txpower_scale_decr_db }, + { + .info.vendor_id = QCA_NL80211_VENDOR_ID, + .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | + WIPHY_VENDOR_CMD_NEED_NETDEV | + WIPHY_VENDOR_CMD_NEED_RUNNING, + .doit = wlan_hdd_cfg80211_bpf_offload + }, }; /** @@ -5543,26 +5895,35 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS; - /* Supports STATION & AD-HOC modes right now */ - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) - | BIT(NL80211_IFTYPE_ADHOC) - | BIT(NL80211_IFTYPE_P2P_CLIENT) - | BIT(NL80211_IFTYPE_P2P_GO) - | BIT(NL80211_IFTYPE_AP); - - if (pCfg->advertiseConcurrentOperation) { - if (pCfg->enableMCC) { - int i; - for (i = 0; i < ARRAY_SIZE(wlan_hdd_iface_combination); - i++) { - if (!pCfg->allowMCCGODiffBI) - wlan_hdd_iface_combination[i]. - beacon_int_infra_match = true; + if (cds_get_conparam() != QDF_GLOBAL_MONITOR_MODE) { + /* Supports STATION & AD-HOC modes right now */ + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + | BIT(NL80211_IFTYPE_ADHOC) + | BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO) + | BIT(NL80211_IFTYPE_AP); + + if (pCfg->advertiseConcurrentOperation) { + if (pCfg->enableMCC) { + int i; + + for (i = 0; + i < ARRAY_SIZE(wlan_hdd_iface_combination); + i++) { + if (!pCfg->allowMCCGODiffBI) + wlan_hdd_iface_combination[i]. + beacon_int_infra_match = true; + } } + wiphy->n_iface_combinations = + ARRAY_SIZE(wlan_hdd_iface_combination); + wiphy->iface_combinations = wlan_hdd_iface_combination; } + } else { + wiphy->interface_modes = BIT(NL80211_IFTYPE_MONITOR); wiphy->n_iface_combinations = - ARRAY_SIZE(wlan_hdd_iface_combination); - wiphy->iface_combinations = wlan_hdd_iface_combination; + ARRAY_SIZE(wlan_hdd_mon_iface); + wiphy->iface_combinations = wlan_hdd_mon_iface; } /* Before registering we need to update the ht capabilitied based @@ -5570,8 +5931,6 @@ int wlan_hdd_cfg80211_init(struct device *dev, if (!pCfg->ShortGI20MhzEnable) { wlan_hdd_band_2_4_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; wlan_hdd_band_5_ghz.ht_cap.cap &= ~IEEE80211_HT_CAP_SGI_20; - wlan_hdd_band_p2p_2_4_ghz.ht_cap.cap &= - ~IEEE80211_HT_CAP_SGI_20; } if (!pCfg->ShortGI40MhzEnable) { @@ -7434,9 +7793,7 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, int rssi = 0; hdd_context_t *pHddCtx; int status; -#ifdef CONFIG_CNSS struct timespec ts; -#endif struct hdd_config *cfg_param; ENTER(); @@ -7455,18 +7812,11 @@ wlan_hdd_cfg80211_inform_bss_frame(hdd_adapter_t *pAdapter, memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN); -#ifdef CONFIG_CNSS /* Android does not want the timestamp from the frame. Instead it wants a monotonic increasing value */ - cnss_get_monotonic_boottime(&ts); + get_monotonic_boottime(&ts); mgmt->u.probe_resp.timestamp = ((u64) ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); -#else - /* keep old behavior for non-open source (for now) */ - memcpy(&mgmt->u.probe_resp.timestamp, bss_desc->timeStamp, - sizeof(bss_desc->timeStamp)); - -#endif mgmt->u.probe_resp.beacon_int = bss_desc->beaconInterval; mgmt->u.probe_resp.capab_info = bss_desc->capabilityInfo; @@ -7877,6 +8227,10 @@ void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel) uint8_t iniDot11Mode = (WLAN_HDD_GET_CTX(pAdapter))->config->dot11Mode; eHddDot11Mode hddDot11Mode = iniDot11Mode; struct ch_params_s ch_params; + hdd_station_ctx_t *station_ctx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + uint32_t cb_mode; + struct hdd_mon_set_ch_info *ch_info = &station_ctx->ch_info; + ch_params.ch_width = (WLAN_HDD_GET_CTX(pAdapter))->config->vhtChannelWidth; @@ -7899,10 +8253,20 @@ void hdd_select_cbmode(hdd_adapter_t *pAdapter, uint8_t operationChannel) break; } /* This call decides required channel bonding mode */ - sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal), + cb_mode = sme_set_ch_params((WLAN_HDD_GET_CTX(pAdapter)->hHal), hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode), operationChannel, 0, &ch_params); + + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) { + ch_info->channel_width = ch_params.ch_width; + ch_info->phy_mode = hdd_cfg_xlate_to_csr_phy_mode(hddDot11Mode); + ch_info->channel = operationChannel; + ch_info->cb_mode = cb_mode; + hdd_info("ch_info width %d, phymode %d channel %d", + ch_info->channel_width, ch_info->phy_mode, + ch_info->channel); + } } /** @@ -8194,20 +8558,6 @@ int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, return -EINVAL; } - /* change conn_state to connecting before sme_roam_connect(), because sme_roam_connect() - * has a direct path to call hdd_sme_roam_callback(), which will change the conn_state - * If direct path, conn_state will be accordingly changed to NotConnected or Associated - * by either hdd_association_completion_handler() or hdd_dis_connect_handler() in sme_RoamCallback() - * if sme_RomConnect is to be queued, Connecting state will remain until it is completed. - */ - if (QDF_STA_MODE == pAdapter->device_mode || - QDF_P2P_CLIENT_MODE == pAdapter->device_mode) { - hddLog(LOG1, - FL("Set HDD connState to eConnectionState_Connecting")); - hdd_conn_set_connection_state(pAdapter, - eConnectionState_Connecting); - } - /* After 8-way handshake supplicant should give the scan command * in that it update the additional IEs, But because of scan * enhancements, the supplicant is not issuing the scan command now. @@ -8263,6 +8613,32 @@ int wlan_hdd_cfg80211_connect_start(hdd_adapter_t *pAdapter, pHddCtx->config->nChannelBondingMode24GHz; sme_update_config(pHddCtx->hHal, sme_config); qdf_mem_free(sme_config); + /* + * Change conn_state to connecting before sme_roam_connect(), + * because sme_roam_connect() has a direct path to call + * hdd_sme_roam_callback(), which will change the conn_state + * If direct path, conn_state will be accordingly changed to + * NotConnected or Associated by either + * hdd_association_completion_handler() or + * hdd_dis_connect_handler() in sme_RoamCallback()if + * sme_RomConnect is to be queued, + * Connecting state will remain until it is completed. + * + * If connection state is not changed, connection state will + * remain in eConnectionState_NotConnected state. + * In hdd_association_completion_handler, "hddDisconInProgress" + * is set to true if conn state is + * eConnectionState_NotConnected. + * If "hddDisconInProgress" is set to true then cfg80211 layer + * is not informed of connect result indication which + * is an issue. + */ + if (QDF_STA_MODE == pAdapter->device_mode || + QDF_P2P_CLIENT_MODE == pAdapter->device_mode) { + hdd_info("Set HDD connState to eConnectionState_Connecting"); + hdd_conn_set_connection_state(pAdapter, + eConnectionState_Connecting); + } status = sme_roam_connect(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, pRoamProfile, @@ -11477,6 +11853,93 @@ enum cds_con_mode wlan_hdd_convert_nl_iftype_to_hdd_type( } /** + * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel + * @wiphy: Handle to struct wiphy to get handle to module context. + * @chandef: Contains information about the capture channel to be set. + * + * This interface is called if and only if monitor mode interface alone is + * active. + * + * Return: 0 success or error code on failure. + */ +static int __wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + hdd_context_t *hdd_ctx = wiphy_priv(wiphy); + hdd_adapter_t *adapter; + hdd_station_ctx_t *sta_ctx; + struct hdd_mon_set_ch_info *ch_info; + QDF_STATUS status; + tHalHandle hal_hdl; + struct qdf_mac_addr bssid; + tCsrRoamProfile roam_profile; + struct ch_params_s ch_params; + int ret; + uint16_t chan_num = cds_freq_to_chan(chandef->chan->center_freq); + + ENTER(); + + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret) + return ret; + + hal_hdl = hdd_ctx->hHal; + + adapter = hdd_get_adapter(hdd_ctx, QDF_MONITOR_MODE); + if (!adapter) + return -EIO; + + hdd_info("%s: set monitor mode Channel %d and freq %d", + adapter->dev->name, chan_num, chandef->chan->center_freq); + + sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + ch_info = &sta_ctx->ch_info; + hdd_select_cbmode(adapter, chan_num); + roam_profile.ChannelInfo.ChannelList = &ch_info->channel; + roam_profile.ChannelInfo.numOfChannels = 1; + roam_profile.phyMode = ch_info->phy_mode; + roam_profile.ch_params.ch_width = chandef->width; + + qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes, + QDF_MAC_ADDR_SIZE); + + ch_params.ch_width = chandef->width; + sme_set_ch_params(hal_hdl, ch_info->phy_mode, chan_num, 0, + &ch_params); + status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params, + &roam_profile); + if (status) { + hdd_err("Status: %d Failed to set sme_RoamChannel for monitor mode", + status); + ret = qdf_status_to_os_return(status); + return ret; + } + EXIT(); + return 0; +} + +/** + * wlan_hdd_cfg80211_set_mon_ch() - Set monitor mode capture channel + * @wiphy: Handle to struct wiphy to get handle to module context. + * @chandef: Contains information about the capture channel to be set. + * + * This interface is called if and only if monitor mode interface alone is + * active. + * + * Return: 0 success or error code on failure. + */ +static int wlan_hdd_cfg80211_set_mon_ch(struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __wlan_hdd_cfg80211_set_mon_ch(wiphy, chandef); + cds_ssr_unprotect(__func__); + return ret; +} + +/** * struct cfg80211_ops - cfg80211_ops * * @add_virtual_intf: Add virtual interface @@ -11591,4 +12054,5 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = { #ifdef CHANNEL_SWITCH_SUPPORTED .channel_switch = wlan_hdd_cfg80211_channel_switch, #endif + .set_monitor_channel = wlan_hdd_cfg80211_set_mon_ch, }; diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 9ba52bb31790..1a185b0e30fd 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -344,6 +344,7 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS = 79, QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI = 80, + QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER = 83, /* OCB commands */ QCA_NL80211_VENDOR_SUBCMD_OCB_SET_CONFIG = 92, QCA_NL80211_VENDOR_SUBCMD_OCB_SET_UTC_TIME = 93, @@ -2139,6 +2140,40 @@ enum qca_wlan_vendor_attr_rssi_monitoring { }; /** + * enum set_reset_packet_filter - set packet filter control commands + * @QCA_WLAN_SET_PACKET_FILTER: Set Packet Filter + * @QCA_WLAN_GET_PACKET_FILTER: Get Packet filter + */ +enum set_reset_packet_filter { + QCA_WLAN_SET_PACKET_FILTER = 1, + QCA_WLAN_GET_PACKET_FILTER = 2, +}; + +/** + * enum qca_wlan_vendor_attr_packet_filter - BPF control commands + * @QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID: Invalid + * @QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER: Filter ID + * @QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION: Filter Version + * @QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE: Total Length + * @QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET: Current offset + * @QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM: length of BPF instructions + */ +enum qca_wlan_vendor_attr_packet_filter { + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_SET_RESET_PACKET_FILTER, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX = + QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_AFTER_LAST - 1, +}; + +/** * enum qca_vendor_attr_get_preferred_freq_list - get preferred channel list * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_INVALID: invalid value * @QCA_WLAN_VENDOR_ATTR_GET_PREFERRED_FREQ_LIST_IFACE_TYPE: interface type @@ -2435,4 +2470,7 @@ int wlan_hdd_disable_dfs_chan_scan(hdd_context_t *hdd_ctx, int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand); + +void hdd_get_bpf_offload_cb(void *hdd_context, struct sir_bpf_get_offload *); +void hdd_init_bpf_completion(void); #endif diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index 1649840e98ae..c5fc181def9b 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -54,6 +54,7 @@ #include "qwlan_version.h" #include "bmi.h" #include "cdp_txrx_bus.h" +#include "pld_common.h" #ifdef MODULE #define WLAN_MODULE_NAME module_name(THIS_MODULE) @@ -61,25 +62,7 @@ #define WLAN_MODULE_NAME "wlan" #endif -#ifdef HIF_PCI -#ifdef CONFIG_CNSS -#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \ - cnss_wlan_register_driver(wlan_drv_ops) -#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ - cnss_wlan_unregister_driver(wlan_drv_ops) -#else -#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \ - pci_register_driver(wlan_drv_ops) -#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ - pci_unregister_driver(wlan_drv_ops) -#endif /* CONFIG_CNSS */ -#else -#define WLAN_HDD_REGISTER_DRIVER(wlan_drv_ops) \ - icnss_register_driver(wlan_drv_ops) -#define WLAN_HDD_UNREGISTER_DRIVER(wlan_drv_ops) \ - icnss_unregister_driver(wlan_drv_ops) -#endif /* HIF_PCI */ -#define DISABLE_KRAIT_IDLE_PS_VAL 1 +#define DISABLE_KRAIT_IDLE_PS_VAL 1 /* * In BMI Phase we are only sending small chunk (256 bytes) of the FW image at @@ -210,6 +193,26 @@ static void hdd_deinit_cds_hif_context(void) } /** + * to_bus_type() - Map PLD bus type to low level bus type + * @bus_type: PLD bus type + * + * Map PLD bus type to low level bus type. + * + * Return: low level bus type. + */ +static enum qdf_bus_type to_bus_type(enum pld_bus_type bus_type) +{ + switch (bus_type) { + case PLD_BUS_TYPE_PCIE: + return QDF_BUS_TYPE_PCI; + case PLD_BUS_TYPE_SNOC: + return QDF_BUS_TYPE_SNOC; + default: + return QDF_BUS_TYPE_NONE; + } +} + +/** * hdd_hif_open() - HIF open helper * @dev: wlan device structure * @bdev: bus device structure @@ -353,7 +356,7 @@ static int wlan_hdd_probe(struct device *dev, void *bdev, const hif_bus_id *bid, cds_set_load_in_progress(true); } - if (WLAN_IS_EPPING_ENABLED(mode)) { + if (QDF_IS_EPPING_ENABLED(mode)) { status = epping_open(); if (status != QDF_STATUS_SUCCESS) goto err_hdd_deinit; @@ -403,7 +406,7 @@ err_bmi_close: err_hif_close: hdd_hif_close(hif_ctx); err_epping_close: - if (WLAN_IS_EPPING_ENABLED(mode)) + if (QDF_IS_EPPING_ENABLED(mode)) epping_close(); err_hdd_deinit: cds_set_load_in_progress(false); @@ -457,7 +460,7 @@ static void wlan_hdd_remove(void) hif_disable_power_management(hif_ctx); - if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + if (QDF_IS_EPPING_ENABLED(cds_get_conparam())) { epping_disable(); epping_close(); } else { @@ -493,7 +496,7 @@ static void wlan_hdd_shutdown(void) if (!cds_wait_for_external_threads_completion(__func__)) hdd_err("Host is not ready for SSR, attempting anyway"); - if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) { hif_disable_isr(hif_ctx); hdd_wlan_shutdown(); } @@ -527,7 +530,7 @@ void wlan_hdd_crash_shutdown(void) */ void wlan_hdd_notify_handler(int state) { - if (!WLAN_IS_EPPING_ENABLED(cds_get_conparam())) { + if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) { int ret = 0; ret = hdd_wlan_notify_modem_power_state(state); if (ret < 0) @@ -790,268 +793,181 @@ static int wlan_hdd_runtime_resume(void) } #endif -#ifdef HIF_PCI /** - * wlan_hdd_pci_probe() - probe callback for pci platform driver - * @pdev: bus dev + * wlan_hdd_pld_probe() - probe function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type + * @bdev: bus device structure + * @id: bus identifier for shared busses * - * Return: void + * Return: 0 on success */ -static int wlan_hdd_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) +static int wlan_hdd_pld_probe(struct device *dev, + enum pld_bus_type pld_bus_type, + void *bdev, void *id) { - return wlan_hdd_probe(&pdev->dev, pdev, (void *)id, - QDF_BUS_TYPE_PCI, false); + enum qdf_bus_type bus_type; + + bus_type = to_bus_type(pld_bus_type); + if (bus_type == QDF_BUS_TYPE_NONE) { + hdd_err("Invalid bus type %d->%d", + pld_bus_type, bus_type); + return -EINVAL; + } + + return wlan_hdd_probe(dev, bdev, id, bus_type, false); } /** - * wlan_hdd_pci_remove() - wlan_hdd_pci_remove + * wlan_hdd_pld_remove() - remove function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type * * Return: void */ -void wlan_hdd_pci_remove(struct pci_dev *pdev) +static void wlan_hdd_pld_remove(struct device *dev, + enum pld_bus_type bus_type) { wlan_hdd_remove(); } /** - * wlan_hdd_pci_reinit() - wlan_hdd_pci_reinit - * @pdev: bus dev - * @id: bus id - * - * Return: int - */ -int wlan_hdd_pci_reinit(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - return wlan_hdd_probe(&pdev->dev, pdev, (void *)id, - QDF_BUS_TYPE_PCI, true); -} - -/** - * wlan_hdd_pci_shutdown() - wlan_hdd_pci_shutdown - * @pdev: pdev + * wlan_hdd_pld_shutdown() - shutdown function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type * * Return: void */ -void wlan_hdd_pci_shutdown(struct pci_dev *pdev) +static void wlan_hdd_pld_shutdown(struct device *dev, + enum pld_bus_type bus_type) { wlan_hdd_shutdown(); } /** - * wlan_hdd_pci_crash_shutdown() - wlan_hdd_pci_crash_shutdown - * @pdev: pdev + * wlan_hdd_pld_reinit() - reinit function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type + * @bdev: bus device structure + * @id: bus identifier for shared busses * - * Return: void + * Return: 0 on success */ -void wlan_hdd_pci_crash_shutdown(struct pci_dev *pdev) +static int wlan_hdd_pld_reinit(struct device *dev, + enum pld_bus_type pld_bus_type, + void *bdev, void *id) { - wlan_hdd_crash_shutdown(); -} + enum qdf_bus_type bus_type; -/** - * wlan_hdd_pci_notify_handler() - wlan_hdd_pci_notify_handler - * @pdev: pdev - * @state: state - * - * Return: void - */ -void wlan_hdd_pci_notify_handler(struct pci_dev *pdev, int state) -{ - wlan_hdd_notify_handler(state); -} + bus_type = to_bus_type(pld_bus_type); + if (bus_type == QDF_BUS_TYPE_NONE) { + hdd_err("Invalid bus type %d->%d", + pld_bus_type, bus_type); + return -EINVAL; + } -/** - * wlan_hdd_pci_suspend() - wlan_hdd_pci_suspend - * @pdev: pdev - * @state: state - * - * Return: void - */ -static int wlan_hdd_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - return wlan_hdd_bus_suspend(state); + return wlan_hdd_probe(dev, bdev, id, bus_type, true); } /** - * wlan_hdd_pci_resume() - wlan_hdd_pci_resume - * @pdev: pdev + * wlan_hdd_pld_crash_shutdown() - crash_shutdown function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type * * Return: void */ -static int wlan_hdd_pci_resume(struct pci_dev *pdev) -{ - return wlan_hdd_bus_resume(); -} - -#ifdef FEATURE_RUNTIME_PM -/** - * wlan_hdd_pci_runtime_suspend() - wlan_hdd_pci_suspend - * @pdev: pdev - * @state: state - * - * Return: success or errno - */ -static int wlan_hdd_pci_runtime_suspend(struct pci_dev *pdev) +static void wlan_hdd_pld_crash_shutdown(struct device *dev, + enum pld_bus_type bus_type) { - return wlan_hdd_runtime_suspend(); -} - -/** - * wlan_hdd_pci_runtime_resume() - runtime resume callback to register with pci - * @pdev: pci device id - * - * Return: success or errno - */ -static int wlan_hdd_pci_runtime_resume(struct pci_dev *pdev) -{ - return wlan_hdd_runtime_resume(); -} -#endif - -#else -/** - * wlan_hdd_snoc_probe() - wlan_hdd_snoc_probe - * @dev: dev - * - * Return: int - */ -static int wlan_hdd_snoc_probe(struct device *dev) -{ - return wlan_hdd_probe(dev, NULL, NULL, QDF_BUS_TYPE_SNOC, false); + wlan_hdd_crash_shutdown(); } /** - * wlan_hdd_snoc_remove() - wlan_hdd_snoc_remove - * @dev: dev + * wlan_hdd_pld_suspend() - suspend function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type + * @state: PM state * - * Return: void + * Return: 0 on success */ -void wlan_hdd_snoc_remove(struct device *dev) -{ - wlan_hdd_remove(); -} +static int wlan_hdd_pld_suspend(struct device *dev, + enum pld_bus_type bus_type, + pm_message_t state) -/** - * wlan_hdd_snoc_shutdown() - wlan_hdd_snoc_shutdown - * @dev: dev - * - * Return: void - */ -void wlan_hdd_snoc_shutdown(struct device *dev) { - wlan_hdd_shutdown(); + return wlan_hdd_bus_suspend(state); } /** - * wlan_hdd_snoc_reinit() - wlan_hdd_snoc_reinit - * @dev: dev + * wlan_hdd_pld_resume() - resume function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type * - * Return: int + * Return: 0 on success */ -int wlan_hdd_snoc_reinit(struct device *dev) +static int wlan_hdd_pld_resume(struct device *dev, + enum pld_bus_type bus_type) { - return wlan_hdd_probe(dev, NULL, NULL, QDF_BUS_TYPE_SNOC, true); + return wlan_hdd_bus_resume(); } /** - * wlan_hdd_snoc_crash_shutdown() - wlan_hdd_snoc_crash_shutdown - * @dev: dev + * wlan_hdd_pld_notify_handler() - notify_handler function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type + * @state: Modem power state * * Return: void */ -void wlan_hdd_snoc_crash_shutdown(void *pdev) +static void wlan_hdd_pld_notify_handler(struct device *dev, + enum pld_bus_type bus_type, + int state) { - wlan_hdd_crash_shutdown(); + wlan_hdd_notify_handler(state); } +#ifdef FEATURE_RUNTIME_PM /** - * wlan_hdd_snoc_suspend() - wlan_hdd_snoc_suspend - * @dev: dev - * @state: state + * wlan_hdd_pld_runtime_suspend() - runtime suspend function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type * - * Return: int + * Return: 0 on success */ -static int wlan_hdd_snoc_suspend(struct device *dev, pm_message_t state) +static int wlan_hdd_pld_runtime_suspend(struct device *dev, + enum pld_bus_type bus_type) { - return wlan_hdd_bus_suspend(state); + return wlan_hdd_runtime_suspend(); } /** - * wlan_hdd_snoc_resume() - wlan_hdd_snoc_resume - * @dev: dev + * wlan_hdd_pld_runtime_resume() - runtime resume function registered to PLD + * @dev: device + * @pld_bus_type: PLD bus type * - * Return: int + * Return: 0 on success */ -static int wlan_hdd_snoc_resume(struct device *dev) +static int wlan_hdd_pld_runtime_resume(struct device *dev, + enum pld_bus_type bus_type) { - return wlan_hdd_bus_resume(); + return wlan_hdd_runtime_resume(); } -#endif /* HIF_PCI */ - -#ifdef HIF_PCI -static struct pci_device_id wlan_hdd_pci_id_table[] = { - { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, - { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, - { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID }, - { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID }, - { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID }, - { 0 } -}; - -#ifdef CONFIG_CNSS - -#ifdef FEATURE_RUNTIME_PM -struct cnss_wlan_runtime_ops runtime_pm_ops = { - .runtime_suspend = wlan_hdd_pci_runtime_suspend, - .runtime_resume = wlan_hdd_pci_runtime_resume, -}; #endif -struct cnss_wlan_driver wlan_drv_ops = { - .name = "wlan_hdd_pci", - .id_table = wlan_hdd_pci_id_table, - .probe = wlan_hdd_pci_probe, - .remove = wlan_hdd_pci_remove, - .reinit = wlan_hdd_pci_reinit, - .shutdown = wlan_hdd_pci_shutdown, - .crash_shutdown = wlan_hdd_pci_crash_shutdown, - .modem_status = wlan_hdd_pci_notify_handler, -#ifdef ATH_BUS_PM - .suspend = wlan_hdd_pci_suspend, - .resume = wlan_hdd_pci_resume, -#endif /* ATH_BUS_PM */ +struct pld_driver_ops wlan_drv_ops = { + .probe = wlan_hdd_pld_probe, + .remove = wlan_hdd_pld_remove, + .shutdown = wlan_hdd_pld_shutdown, + .reinit = wlan_hdd_pld_reinit, + .crash_shutdown = wlan_hdd_pld_crash_shutdown, + .suspend = wlan_hdd_pld_suspend, + .resume = wlan_hdd_pld_resume, + .modem_status = wlan_hdd_pld_notify_handler, #ifdef FEATURE_RUNTIME_PM - .runtime_ops = &runtime_pm_ops, + .runtime_suspend = wlan_hdd_pld_runtime_suspend, + .runtime_resume = wlan_hdd_pld_runtime_resume, #endif }; -#else -MODULE_DEVICE_TABLE(pci, wlan_hdd_pci_id_table); -struct pci_driver wlan_drv_ops = { - .name = "wlan_hdd_pci", - .id_table = wlan_hdd_pci_id_table, - .probe = wlan_hdd_pci_probe, - .remove = wlan_hdd_pci_remove, -#ifdef ATH_BUS_PM - .suspend = wlan_hdd_pci_suspend, - .resume = wlan_hdd_pci_resume, -#endif /* ATH_BUS_PM */ - -}; -#endif /* CONFIG_CNSS */ -#else -struct icnss_driver_ops wlan_drv_ops = { - .name = "wlan_hdd_drv", - .probe = wlan_hdd_snoc_probe, - .remove = wlan_hdd_snoc_remove, - .shutdown = wlan_hdd_snoc_shutdown, - .reinit = wlan_hdd_snoc_reinit, - .crash_shutdown = wlan_hdd_snoc_crash_shutdown, - .suspend = wlan_hdd_snoc_suspend, - .resume = wlan_hdd_snoc_resume, -}; -#endif /** * wlan_hdd_register_driver() - wlan_hdd_register_driver @@ -1060,7 +976,7 @@ struct icnss_driver_ops wlan_drv_ops = { */ int wlan_hdd_register_driver(void) { - return WLAN_HDD_REGISTER_DRIVER(&wlan_drv_ops); + return pld_register_driver(&wlan_drv_ops); } /** @@ -1070,5 +986,5 @@ int wlan_hdd_register_driver(void) */ void wlan_hdd_unregister_driver(void) { - WLAN_HDD_UNREGISTER_DRIVER(&wlan_drv_ops); + pld_unregister_driver(); } diff --git a/core/hdd/src/wlan_hdd_ext_scan.c b/core/hdd/src/wlan_hdd_ext_scan.c index 06473990b67c..34a943e47df4 100644 --- a/core/hdd/src/wlan_hdd_ext_scan.c +++ b/core/hdd/src/wlan_hdd_ext_scan.c @@ -772,9 +772,8 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, { hdd_context_t *pHddCtx = (hdd_context_t *) ctx; struct sk_buff *skb = NULL; -#ifdef CONFIG_CNSS struct timespec ts; -#endif + int flags = cds_get_gfp_flags(); ENTER(); @@ -804,12 +803,12 @@ wlan_hdd_cfg80211_extscan_full_scan_result_event(void *ctx, } pData->ap.channel = cds_chan_to_freq(pData->ap.channel); -#ifdef CONFIG_CNSS + /* Android does not want the time stamp from the frame. Instead it wants a monotonic increasing value since boot */ - cnss_get_monotonic_boottime(&ts); + get_monotonic_boottime(&ts); pData->ap.ts = ((u64)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000); -#endif + hddLog(LOG1, "Req Id %u More Data %u", pData->requestId, pData->moreData); hddLog(LOG1, "AP Info: Timestamp %llu Ssid: %s " diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 3e5e6406c430..bf0cb5c310ba 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -75,6 +75,7 @@ #include "qdf_trace.h" #include "wlan_hdd_cfg.h" #include "cds_concurrency.h" +#include "wlan_hdd_tsf.h" #include "wlan_hdd_green_ap.h" #define IS_UP(_dev) \ @@ -101,16 +102,25 @@ /* Function definitions */ /** - * hdd_hostapd_channel_wakelock_init() - init the channel wakelock - * @pHddCtx: pointer to hdd context + * hdd_sap_context_init() - Initialize SAP context. + * @hdd_ctx: HDD context. * - * Return: None + * Initialize SAP context. + * + * Return: 0 on success. */ -void hdd_hostapd_channel_wakelock_init(hdd_context_t *pHddCtx) +int hdd_sap_context_init(hdd_context_t *hdd_ctx) { - /* Initialize the wakelock */ - qdf_wake_lock_create(&pHddCtx->sap_dfs_wakelock, "sap_dfs_wakelock"); - atomic_set(&pHddCtx->sap_dfs_ref_cnt, 0); + qdf_wake_lock_create(&hdd_ctx->sap_dfs_wakelock, "sap_dfs_wakelock"); + atomic_set(&hdd_ctx->sap_dfs_ref_cnt, 0); + + mutex_init(&hdd_ctx->sap_lock); + qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock"); + qdf_spinlock_create(&hdd_ctx->sap_update_info_lock); + + mutex_init(&hdd_ctx->dfs_lock); + + return 0; } /** @@ -186,25 +196,33 @@ void hdd_hostapd_channel_prevent_suspend(hdd_adapter_t *pAdapter, } /** - * hdd_hostapd_channel_wakelock_deinit() - destroy the channel wakelock + * hdd_sap_context_destroy() - Destroy SAP context * - * @pHddCtx: pointer to hdd context + * @hdd_ctx: HDD context. + * + * Destroy SAP context. * * Return: None */ -void hdd_hostapd_channel_wakelock_deinit(hdd_context_t *pHddCtx) +void hdd_sap_context_destroy(hdd_context_t *hdd_ctx) { - if (atomic_read(&pHddCtx->sap_dfs_ref_cnt)) { - /* Release wakelock */ - qdf_wake_lock_release(&pHddCtx->sap_dfs_wakelock, + if (atomic_read(&hdd_ctx->sap_dfs_ref_cnt)) { + qdf_wake_lock_release(&hdd_ctx->sap_dfs_wakelock, WIFI_POWER_EVENT_WAKELOCK_DRIVER_EXIT); - /* Reset the reference count */ - atomic_set(&pHddCtx->sap_dfs_ref_cnt, 0); - hddLog(LOGE, FL("DFS: allowing suspend")); + + atomic_set(&hdd_ctx->sap_dfs_ref_cnt, 0); + hdd_warn("DFS: Allowing suspend"); } - /* Destroy lock */ - qdf_wake_lock_destroy(&pHddCtx->sap_dfs_wakelock); + qdf_wake_lock_destroy(&hdd_ctx->sap_dfs_wakelock); + + mutex_destroy(&hdd_ctx->sap_lock); + qdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock); + + mutex_destroy(&hdd_ctx->dfs_lock); + + qdf_spinlock_destroy(&hdd_ctx->sap_update_info_lock); + } /** @@ -705,7 +723,7 @@ hdd_update_chandef(hdd_adapter_t *hostapd_adapter, * Return: Success on intimating userspace * */ -QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, +QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *adapter, struct net_device *dev, uint8_t oper_chan) { @@ -715,7 +733,7 @@ QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, eCsrPhyMode phy_mode; ePhyChanBondState cb_mode; uint32_t freq; - tHalHandle hal = WLAN_HDD_GET_HAL_CTX(hostapd_adapter); + tHalHandle hal = WLAN_HDD_GET_HAL_CTX(adapter); if (NULL == hal) { hdd_err("hal is NULL"); @@ -724,14 +742,18 @@ QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, freq = cds_chan_to_freq(oper_chan); - chan = __ieee80211_get_channel(hostapd_adapter->wdev.wiphy, freq); + chan = __ieee80211_get_channel(adapter->wdev.wiphy, freq); if (!chan) { hdd_err("Invalid input frequency for channel conversion"); return QDF_STATUS_E_FAILURE; } - phy_mode = hdd_sap_get_phymode(hostapd_adapter); + if (adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) + phy_mode = hdd_sap_get_phymode(adapter); + else + phy_mode = sme_get_phy_mode(hal); if (oper_chan <= 14) cb_mode = sme_get_cb_phy_state_from_cb_ini_value( @@ -766,7 +788,7 @@ QDF_STATUS hdd_chan_change_notify(hdd_adapter_t *hostapd_adapter, if ((phy_mode == eCSR_DOT11_MODE_11ac) || (phy_mode == eCSR_DOT11_MODE_11ac_ONLY)) - hdd_update_chandef(hostapd_adapter, &chandef, cb_mode); + hdd_update_chandef(adapter, &chandef, cb_mode); cfg80211_ch_switch_notify(dev, &chandef); @@ -1098,6 +1120,15 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, cds_dump_concurrency_info(); /* Send SCC/MCC Switching event to IPA */ hdd_ipa_send_mcc_scc_msg(pHddCtx, pHddCtx->mcc_mode); + + if (cds_is_hw_mode_change_after_vdev_up()) { + hdd_info("check for possible hw mode change"); + status = cds_set_hw_mode_on_channel_switch( + pHostapdAdapter->sessionId); + if (QDF_IS_STATUS_ERROR(status)) + hdd_info("set hw mode change not done"); + cds_set_do_hw_mode_change_flag(false); + } break; /* Event will be sent after Switch-Case stmt */ case eSAP_STOP_BSS_EVENT: @@ -2453,7 +2484,16 @@ static __iw_softap_setparam(struct net_device *dev, else ret = -EINVAL; break; - + case QCSAP_PARAM_CONC_SYSTEM_PREF: + hdd_info("New preference: %d", set_value); + if (!((set_value >= CFG_CONC_SYSTEM_PREF_MIN) && + (set_value <= CFG_CONC_SYSTEM_PREF_MAX))) { + hdd_err("Invalid system preference %d", set_value); + return -EINVAL; + } + /* hdd_ctx, hdd_ctx->config are already checked for null */ + hdd_ctx->config->conc_system_pref = set_value; + break; case QCSAP_PARAM_MAX_ASSOC: if (WNI_CFG_ASSOC_STA_LIMIT_STAMIN > set_value) { hddLog(LOGE, FL("Invalid setMaxAssoc value %d"), @@ -3011,6 +3051,66 @@ static __iw_softap_setparam(struct net_device *dev, return ret; } +/** + * __iw_softap_get_three() - return three value to upper layer. + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/out + * + * Return: execute result + */ +static int __iw_softap_get_three(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + uint32_t *value = (uint32_t *)extra; + uint32_t sub_cmd = value[0]; + int ret = 0; /* success */ + struct hdd_context_s *hdd_ctx; + struct hdd_adapter_s *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + ret = wlan_hdd_validate_context(hdd_ctx); + if (ret != 0) + return ret; + + switch (sub_cmd) { + case QCSAP_GET_TSF: + ret = hdd_indicate_tsf(adapter, value, 3); + break; + default: + hdd_err(FL("Invalid getparam command %d"), sub_cmd); + ret = -EINVAL; + break; + } + return ret; +} + + +/** + * iw_softap_get_three() - return three value to upper layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/Output + * + * Return: execute result + */ +static int iw_softap_get_three(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_softap_get_three(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + int static iw_softap_setparam(struct net_device *dev, struct iw_request_info *info, @@ -3211,6 +3311,9 @@ static __iw_softap_getparam(struct net_device *dev, VDEV_CMD); break; } + case QCSAP_CAP_TSF: + ret = hdd_capture_tsf(pHostapdAdapter, (uint32_t *)value, 1); + break; case QCASAP_GET_TEMP_CMD: { hddLog(LOG1, "QCASAP_GET_TEMP_CMD"); @@ -5608,6 +5711,10 @@ static const struct iw_priv_args hostapd_private_args[] = { QCSAP_PARAM_AUTO_CHANNEL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setAutoChannel" + }, { + QCSAP_PARAM_CONC_SYSTEM_PREF, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, + "setConcSysPref" }, /* Sub-cmds DBGLOG specific commands */ { @@ -5822,6 +5929,15 @@ static const struct iw_priv_args hostapd_private_args[] = { QCASAP_NSS_CMD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_nss" }, { + QCSAP_CAP_TSF, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "cap_tsf" + }, { + QCSAP_IOCTL_SET_NONE_GET_THREE, 0, IW_PRIV_TYPE_INT | + IW_PRIV_SIZE_FIXED | 3, "" + }, { + QCSAP_GET_TSF, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + "get_tsf" + }, { QCASAP_GET_TEMP_CMD, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_temp" }, { @@ -5997,6 +6113,8 @@ static const iw_handler hostapd_private[] = { [QCSAP_IOCTL_SETPARAM - SIOCIWFIRSTPRIV] = iw_softap_setparam, /* get priv ioctl */ [QCSAP_IOCTL_GETPARAM - SIOCIWFIRSTPRIV] = iw_softap_getparam, + [QCSAP_IOCTL_SET_NONE_GET_THREE - SIOCIWFIRSTPRIV] = + iw_softap_get_three, /* get station genIE */ [QCSAP_IOCTL_GET_STAWPAIE - SIOCIWFIRSTPRIV] = iw_get_genie, [QCSAP_IOCTL_SETWPAIE - SIOCIWFIRSTPRIV] = iw_softap_setwpsie, @@ -8046,9 +8164,9 @@ static int __wlan_hdd_cfg80211_stop_ap(struct wiphy *wiphy, (QDF_SAP_MODE == pAdapter->device_mode)) { cds_flush_work(&pHddCtx->sap_start_work); hddLog(LOGW, FL("Canceled the pending restart work")); - spin_lock(&pHddCtx->sap_update_info_lock); + qdf_spin_lock(&pHddCtx->sap_update_info_lock); pHddCtx->is_sap_restart_required = false; - spin_unlock(&pHddCtx->sap_update_info_lock); + qdf_spin_unlock(&pHddCtx->sap_update_info_lock); } pAdapter->sessionCtx.ap.sapConfig.acs_cfg.acs_mode = false; if (pAdapter->sessionCtx.ap.sapConfig.acs_cfg.ch_list) diff --git a/core/hdd/src/wlan_hdd_hostapd.h b/core/hdd/src/wlan_hdd_hostapd.h index 223b1c12cf0e..ed8c0ac5d3e0 100644 --- a/core/hdd/src/wlan_hdd_hostapd.h +++ b/core/hdd/src/wlan_hdd_hostapd.h @@ -98,8 +98,8 @@ QDF_STATUS hdd_hostapd_sap_event_cb(tpSap_Event pSapEvent, QDF_STATUS hdd_init_ap_mode(hdd_adapter_t *pAdapter); void hdd_set_ap_ops(struct net_device *pWlanHostapdDev); int hdd_hostapd_stop(struct net_device *dev); -void hdd_hostapd_channel_wakelock_init(hdd_context_t *pHddCtx); -void hdd_hostapd_channel_wakelock_deinit(hdd_context_t *pHddCtx); +int hdd_sap_context_init(hdd_context_t *hdd_ctx); +void hdd_sap_context_destroy(hdd_context_t *hdd_ctx); #ifdef FEATURE_WLAN_FORCE_SAP_SCC void hdd_restart_softap(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter); #endif /* FEATURE_WLAN_FORCE_SAP_SCC */ diff --git a/core/hdd/src/wlan_hdd_ipa.c b/core/hdd/src/wlan_hdd_ipa.c index 84cc0e37cb38..90e6c7228e87 100644 --- a/core/hdd/src/wlan_hdd_ipa.c +++ b/core/hdd/src/wlan_hdd_ipa.c @@ -1743,19 +1743,11 @@ end: * * Return: none */ -#ifdef CONFIG_CNSS -static void hdd_ipa_init_uc_op_work(struct work_struct *work, - work_func_t work_handler) -{ - cnss_init_work(work, work_handler); -} -#else static void hdd_ipa_init_uc_op_work(struct work_struct *work, work_func_t work_handler) { INIT_WORK(work, work_handler); } -#endif /** @@ -2353,19 +2345,11 @@ int hdd_ipa_set_perf_level(hdd_context_t *hdd_ctx, uint64_t tx_packets, * * Return: none */ -#ifdef CONFIG_CNSS -static void hdd_ipa_init_uc_rm_work(struct work_struct *work, - work_func_t work_handler) -{ - cnss_init_work(work, work_handler); -} -#else static void hdd_ipa_init_uc_rm_work(struct work_struct *work, work_func_t work_handler) { INIT_WORK(work, work_handler); } -#endif /** * hdd_ipa_setup_rm() - Setup IPA resource management @@ -2430,13 +2414,8 @@ static int hdd_ipa_setup_rm(struct hdd_ipa_priv *hdd_ipa) } qdf_wake_lock_create(&hdd_ipa->wake_lock, "wlan_ipa"); -#ifdef CONFIG_CNSS - cnss_init_delayed_work(&hdd_ipa->wake_lock_work, - hdd_ipa_wake_lock_timer_func); -#else INIT_DELAYED_WORK(&hdd_ipa->wake_lock_work, hdd_ipa_wake_lock_timer_func); -#endif qdf_spinlock_create(&hdd_ipa->rm_lock); hdd_ipa->rm_state = HDD_IPA_RM_RELEASED; hdd_ipa->wake_lock_released = true; @@ -4045,11 +4024,7 @@ QDF_STATUS hdd_ipa_init(hdd_context_t *hdd_ctx) qdf_spinlock_create(&iface_context->interface_lock); } -#ifdef CONFIG_CNSS - cnss_init_work(&hdd_ipa->pm_work, hdd_ipa_pm_send_pkt_to_tl); -#else INIT_WORK(&hdd_ipa->pm_work, hdd_ipa_pm_send_pkt_to_tl); -#endif qdf_spinlock_create(&hdd_ipa->pm_lock); qdf_nbuf_queue_init(&hdd_ipa->pm_queue_head); diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index acf6f9de0335..eb70039025e4 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -55,6 +55,7 @@ #include "wlan_hdd_ftm.h" #include "wlan_hdd_power.h" #include "wlan_hdd_stats.h" +#include "wlan_hdd_scan.h" #include "qdf_types.h" #include "qdf_trace.h" #include <cdp_txrx_peer_ops.h> @@ -90,6 +91,7 @@ #include "cds_regdomain.h" #include "cdp_txrx_flow_ctrl_v2.h" #endif /* FEATURE_WLAN_CH_AVOID */ +#include "pld_common.h" #include "wlan_hdd_ocb.h" #include "wlan_hdd_nan.h" #include "wlan_hdd_debugfs.h" @@ -101,6 +103,7 @@ #include "hif.h" #include "wma.h" #include "cds_concurrency.h" +#include "wlan_hdd_tsf.h" #include "wlan_hdd_green_ap.h" #include "platform_icnss.h" #include "bmi.h" @@ -1335,6 +1338,7 @@ void hdd_update_tgt_cfg(void *context, void *param) hdd_info("Init current antenna mode: %d", hdd_ctx->current_antenna_mode); + hdd_ctx->bpf_enabled = cfg->bpf_enabled; } /** @@ -1433,6 +1437,42 @@ bool hdd_is_valid_mac_address(const uint8_t *pMacAddr) } /** + * __hdd__mon_open() - HDD Open function + * @dev: Pointer to net_device structure + * + * This is called in response to ifconfig up + * + * Return: 0 for success; non-zero for failure + */ +static int __hdd_mon_open(struct net_device *dev) +{ + int ret; + + ENTER_DEV(dev); + ret = hdd_set_mon_rx_cb(dev); + return ret; +} + +/** + * hdd_mon_open() - Wrapper function for __hdd_mon_open to protect it from SSR + * @dev: Pointer to net_device structure + * + * This is called in response to ifconfig up + * + * Return: 0 for success; non-zero for failure + */ +int hdd_mon_open(struct net_device *dev) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __hdd_mon_open(dev); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** * __hdd_open() - HDD Open function * @dev: Pointer to net_device structure * @@ -1889,9 +1929,44 @@ static struct net_device_ops wlan_drv_ops = { #endif }; +/* Monitor mode net_device_ops, doesnot Tx and most of operations. */ +static struct net_device_ops wlan_mon_drv_ops = { + .ndo_open = hdd_mon_open, + .ndo_stop = hdd_stop, + .ndo_get_stats = hdd_get_stats, +}; + +/** + * hdd_set_station_ops() - update net_device ops for monitor mode + * @pWlanDev: Handle to struct net_device to be updated. + * Return: None + */ void hdd_set_station_ops(struct net_device *pWlanDev) { - pWlanDev->netdev_ops = &wlan_drv_ops; + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) + pWlanDev->netdev_ops = &wlan_mon_drv_ops; + else + pWlanDev->netdev_ops = &wlan_drv_ops; +} + +/** + * hdd_mon_mode_ether_setup() - Update monitor mode struct net_device. + * @dev: Handle to struct net_device to be updated. + * + * Return: None + */ +static void hdd_mon_mode_ether_setup(struct net_device *dev) +{ + dev->header_ops = NULL; + dev->type = ARPHRD_IEEE80211_RADIOTAP; + dev->hard_header_len = ETH_HLEN; + dev->mtu = ETH_DATA_LEN; + dev->addr_len = ETH_ALEN; + dev->tx_queue_len = 1000; /* Ethernet wants good queues */ + dev->flags = IFF_BROADCAST|IFF_MULTICAST; + dev->priv_flags |= IFF_TX_SKB_SHARING; + + memset(dev->broadcast, 0xFF, ETH_ALEN); } /** @@ -1919,7 +1994,9 @@ static hdd_adapter_t *hdd_alloc_station_adapter(hdd_context_t *hdd_ctx, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) || defined(WITH_BACKPORTS) name_assign_type, #endif - ether_setup, NUM_TX_QUEUES); + (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() ? + hdd_mon_mode_ether_setup : ether_setup), + NUM_TX_QUEUES); if (pWlanDev != NULL) { @@ -2431,6 +2508,7 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, case QDF_P2P_CLIENT_MODE: case QDF_P2P_DEVICE_MODE: case QDF_OCB_MODE: + case QDF_MONITOR_MODE: { adapter = hdd_alloc_station_adapter(hdd_ctx, macAddr, name_assign_type, @@ -2447,6 +2525,8 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, adapter->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; else if (QDF_P2P_DEVICE_MODE == session_type) adapter->wdev.iftype = NL80211_IFTYPE_P2P_DEVICE; + else if (QDF_MONITOR_MODE == session_type) + adapter->wdev.iftype = NL80211_IFTYPE_MONITOR; else adapter->wdev.iftype = NL80211_IFTYPE_STATION; @@ -2462,27 +2542,17 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, * Workqueue which gets scheduled in IPv4 notification * callback */ -#ifdef CONFIG_CNSS - cnss_init_work(&adapter->ipv4NotifierWorkQueue, - hdd_ipv4_notifier_work_queue); -#else INIT_WORK(&adapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue); -#endif #ifdef WLAN_NS_OFFLOAD /* * Workqueue which gets scheduled in IPv6 * notification callback. */ -#ifdef CONFIG_CNSS - cnss_init_work(&adapter->ipv6NotifierWorkQueue, - hdd_ipv6_notifier_work_queue); -#else INIT_WORK(&adapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue); #endif -#endif status = hdd_register_interface(adapter, rtnl_held); if (QDF_STATUS_SUCCESS != status) { hdd_deinit_adapter(hdd_ctx, adapter, rtnl_held); @@ -3587,9 +3657,11 @@ QDF_STATUS hdd_abort_mac_scan_all_adapters(hdd_context_t *hdd_ctx) #ifdef WLAN_NS_OFFLOAD /** - * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier + * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier * @hdd_ctx: Pointer to hdd context * + * Unregister for IPv6 address change notifications. + * * Return: None */ static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) @@ -3600,42 +3672,52 @@ static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) } /** - * hdd_wlan_register_ip6_notifier() - register IP6 change notifier + * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier * @hdd_ctx: Pointer to hdd context * - * Return: None + * Register for IPv6 address change notifications. + * + * Return: 0 on success and errno on failure. */ -static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) +static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) { int ret; hdd_ctx->ipv6_notifier.notifier_call = wlan_hdd_ipv6_changed; ret = register_inet6addr_notifier(&hdd_ctx->ipv6_notifier); - if (ret) - hddLog(LOGE, FL("Failed to register IPv6 notifier")); - else - hdd_info("Registered IPv6 notifier"); + if (ret) { + hdd_err("Failed to register IPv6 notifier: %d", ret); + goto out; + } - return; + hdd_info("Registered IPv6 notifier"); +out: + return ret; } #else /** - * hdd_wlan_unregister_ip6_notifier() - unregister IP6 change notifier + * hdd_wlan_unregister_ip6_notifier() - unregister IPv6 change notifier * @hdd_ctx: Pointer to hdd context * + * Unregister for IPv6 address change notifications. + * * Return: None */ static void hdd_wlan_unregister_ip6_notifier(hdd_context_t *hdd_ctx) { } + /** - * hdd_wlan_register_ip6_notifier() - register IP6 change notifier + * hdd_wlan_register_ip6_notifier() - register IPv6 change notifier * @hdd_ctx: Pointer to hdd context * + * Register for IPv6 address change notifications. + * * Return: None */ -static void hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) +static int hdd_wlan_register_ip6_notifier(hdd_context_t *hdd_ctx) { + return 0; } #endif @@ -3770,6 +3852,63 @@ static inline int hdd_logging_sock_deactivate_svc(hdd_context_t *hdd_ctx) #endif /** + * hdd_register_notifiers - Register netdev notifiers. + * @hdd_ctx: HDD context + * + * Register netdev notifiers like IPv4 and IPv6. + * + * Return: 0 on success and errno on failure + */ +static int hdd_register_notifiers(hdd_context_t *hdd_ctx) +{ + int ret; + + ret = register_netdevice_notifier(&hdd_netdev_notifier); + if (ret) { + hdd_err("register_netdevice_notifier failed: %d", ret); + goto out; + } + + ret = hdd_wlan_register_ip6_notifier(hdd_ctx); + if (ret) + goto unregister_notifier; + + hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed; + ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier); + if (ret) { + hdd_err("Failed to register IPv4 notifier: %d", ret); + goto unregister_ip6_notifier; + } + + return 0; + +unregister_ip6_notifier: + hdd_wlan_unregister_ip6_notifier(hdd_ctx); +unregister_notifier: + unregister_netdevice_notifier(&hdd_netdev_notifier); +out: + return ret; + +} + +/** + * hdd_unregister_notifiers - Unregister netdev notifiers. + * @hdd_ctx: HDD context + * + * Unregister netdev notifiers like IPv4 and IPv6. + * + * Return: None. + */ +static void hdd_unregister_notifiers(hdd_context_t *hdd_ctx) +{ + hdd_wlan_unregister_ip6_notifier(hdd_ctx); + + unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier); + + unregister_netdevice_notifier(&hdd_netdev_notifier); +} + +/** * hdd_exit_netlink_services - Exit netlink services * @hdd_ctx: HDD context * @@ -3844,20 +3983,94 @@ out: return ret; } +#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK +/** + * hdd_rx_wake_lock_destroy() - Destroy RX wakelock + * @hdd_ctx: HDD context. + * + * Destroy RX wakelock. + * + * Return: None. + */ +static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) +{ + qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock); +} + +/** + * hdd_rx_wake_lock_create() - Create RX wakelock + * @hdd_ctx: HDD context. + * + * Create RX wakelock. + * + * Return: None. + */ +static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) +{ + qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock"); +} +#else +static void hdd_rx_wake_lock_destroy(hdd_context_t *hdd_ctx) { } +static void hdd_rx_wake_lock_create(hdd_context_t *hdd_ctx) { } +#endif + +/** + * hdd_roc_context_init() - Init ROC context + * @hdd_ctx: HDD context. + * + * Initialize ROC context. + * + * Return: 0 on success and errno on failure. + */ +static int hdd_roc_context_init(hdd_context_t *hdd_ctx) +{ + qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock); + qdf_list_create(&hdd_ctx->hdd_roc_req_q, MAX_ROC_REQ_QUEUE_ENTRY); + + INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue); + + return 0; +} + +/** + * hdd_roc_context_destroy() - Destroy ROC context + * @hdd_ctx: HDD context. + * + * Destroy roc list and flush the pending roc work. + * + * Return: None. + */ +static void hdd_roc_context_destroy(hdd_context_t *hdd_ctx) +{ + flush_delayed_work(&hdd_ctx->roc_req_work); + qdf_list_destroy(&hdd_ctx->hdd_roc_req_q); +} /** - * hdd_free_context - Free HDD context - * @hdd_ctx: HDD context to be freed. + * hdd_context_destroy() - Destroy HDD context + * @hdd_ctx: HDD context to be destroyed. * - * Free config and HDD context. + * Free config and HDD context as well as destroy all the resources. * * Return: None */ -static void hdd_free_context(hdd_context_t *hdd_ctx) +static void hdd_context_destroy(hdd_context_t *hdd_ctx) { if (QDF_GLOBAL_FTM_MODE != hdd_get_conparam()) hdd_logging_sock_deactivate_svc(hdd_ctx); + hdd_roc_context_destroy(hdd_ctx); + + hdd_sap_context_destroy(hdd_ctx); + + hdd_rx_wake_lock_destroy(hdd_ctx); + + hdd_tdls_context_destroy(hdd_ctx); + + hdd_scan_context_destroy(hdd_ctx); + + qdf_list_destroy(&hdd_ctx->hddAdapters); + qdf_mem_free(hdd_ctx->config); hdd_ctx->config = NULL; @@ -3880,11 +4093,6 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) ENTER(); - hddLog(LOGE, FL("Unregister IPv6 notifier")); - hdd_wlan_unregister_ip6_notifier(hdd_ctx); - hddLog(LOGE, FL("Unregister IPv4 notifier")); - unregister_inetaddr_notifier(&hdd_ctx->ipv4_notifier); - hdd_unregister_wext_all_adapters(hdd_ctx); if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { @@ -3894,6 +4102,8 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) goto free_hdd_ctx; } + hdd_unregister_notifiers(hdd_ctx); + /* * Cancel any outstanding scan requests. We are about to close all * of our adapters, but an adapter structure is what SME passes back @@ -3972,14 +4182,10 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) FL("Failed to close CDS Scheduler")); QDF_ASSERT(QDF_IS_STATUS_SUCCESS(qdf_status)); } -#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - /* Destroy the wake lock */ - qdf_wake_lock_destroy(&hdd_ctx->rx_wake_lock); -#endif - /* Destroy the wake lock */ - qdf_wake_lock_destroy(&hdd_ctx->sap_wake_lock); - hdd_hostapd_channel_wakelock_deinit(hdd_ctx); + qdf_spinlock_destroy(&hdd_ctx->hdd_adapter_lock); + qdf_spinlock_destroy(&hdd_ctx->sta_update_info_lock); + qdf_spinlock_destroy(&hdd_ctx->connection_status_lock); /* * Close CDS @@ -3998,8 +4204,6 @@ void hdd_wlan_exit(hdd_context_t *hdd_ctx) /* Free up RoC request queue and flush workqueue */ cds_flush_work(&hdd_ctx->roc_req_work); - qdf_list_destroy(&hdd_ctx->hdd_roc_req_q); - qdf_list_destroy(&hdd_ctx->hdd_scan_req_q); if (!QDF_IS_STATUS_SUCCESS(cds_deinit_policy_mgr())) { hdd_err("Failed to deinit policy manager"); @@ -4010,7 +4214,7 @@ free_hdd_ctx: wiphy_unregister(wiphy); - hdd_free_context(hdd_ctx); + hdd_context_destroy(hdd_ctx); } void __hdd_wlan_exit(void) @@ -4035,11 +4239,9 @@ void __hdd_wlan_exit(void) memdump_deinit(); -#ifdef QCA_PKT_PROTO_TRACE - cds_pkt_proto_trace_close(); -#endif /* Do all the cleanup before deregistering the driver */ hdd_wlan_exit(hdd_ctx); + EXIT(); } @@ -5264,7 +5466,80 @@ static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx) } /** - * hdd_init_context - Alloc and initialize HDD context + * hdd_context_init() - Initialize HDD context + * @hdd_ctx: HDD context. + * + * Initialize HDD context along with all the feature specific contexts. + * + * return: 0 on success and errno on failure. + */ +static int hdd_context_init(hdd_context_t *hdd_ctx) +{ + int ret; + + hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; + hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX; + + hdd_init_ll_stats_ctx(); + + init_completion(&hdd_ctx->mc_sus_event_var); + init_completion(&hdd_ctx->ready_to_suspend); + + hdd_init_bpf_completion(); + + qdf_spinlock_create(&hdd_ctx->connection_status_lock); + qdf_spinlock_create(&hdd_ctx->sta_update_info_lock); + qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock); + + qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); + + init_completion(&hdd_ctx->set_antenna_mode_cmpl); + + ret = hdd_scan_context_init(hdd_ctx); + if (ret) + goto list_destroy; + + hdd_tdls_context_init(hdd_ctx); + + hdd_rx_wake_lock_create(hdd_ctx); + + ret = hdd_sap_context_init(hdd_ctx); + if (ret) + goto scan_destroy; + + ret = hdd_roc_context_init(hdd_ctx); + if (ret) + goto sap_destroy; + + wlan_hdd_cfg80211_extscan_init(hdd_ctx); + + hdd_init_offloaded_packets_ctx(hdd_ctx); + + ret = wlan_hdd_cfg80211_init(hdd_ctx->parent_dev, hdd_ctx->wiphy, + hdd_ctx->config); + if (ret) + goto roc_destroy; + + return 0; + +roc_destroy: + hdd_roc_context_destroy(hdd_ctx); + +sap_destroy: + hdd_sap_context_destroy(hdd_ctx); + +scan_destroy: + hdd_scan_context_destroy(hdd_ctx); + hdd_rx_wake_lock_destroy(hdd_ctx); + hdd_tdls_context_destroy(hdd_ctx); + +list_destroy: + qdf_list_destroy(&hdd_ctx->hddAdapters); + return ret; +} + +/** + * hdd_context_create() - Allocate and inialize HDD context. * @dev: Pointer to the underlying device * @hif_sc: HIF context * @@ -5273,7 +5548,7 @@ static void hdd_set_trace_level_for_each(hdd_context_t *hdd_ctx) * * Return: HDD context on success and ERR_PTR on failure */ -hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc) +hdd_context_t *hdd_context_create(struct device *dev, void *hif_sc) { QDF_STATUS status; int ret = 0; @@ -5298,6 +5573,7 @@ hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc) } hdd_ctx->pcds_context = p_cds_context; + hdd_ctx->parent_dev = dev; hdd_ctx->config = qdf_mem_malloc(sizeof(struct hdd_config)); if (hdd_ctx->config == NULL) { @@ -5315,53 +5591,26 @@ hdd_context_t *hdd_init_context(struct device *dev, void *hif_sc) goto err_free_config; } - ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx; - - hdd_ctx->parent_dev = dev; - - hdd_ctx->ioctl_scan_mode = eSIR_ACTIVE_SCAN; - - hdd_init_ll_stats_ctx(); - - init_completion(&hdd_ctx->mc_sus_event_var); - init_completion(&hdd_ctx->ready_to_suspend); - - qdf_spinlock_create(&hdd_ctx->connection_status_lock); - qdf_spinlock_create(&hdd_ctx->sched_scan_lock); - - qdf_spinlock_create(&hdd_ctx->hdd_adapter_lock); - qdf_list_create(&hdd_ctx->hddAdapters, MAX_NUMBER_OF_ADAPTERS); - - wlan_hdd_cfg80211_extscan_init(hdd_ctx); - - hdd_tdls_pre_init(hdd_ctx); - mutex_init(&hdd_ctx->dfs_lock); - mutex_init(&hdd_ctx->sap_lock); - - init_completion(&hdd_ctx->set_antenna_mode_cmpl); - - hdd_ctx->target_type = tgt_info->target_type; - - hdd_init_offloaded_packets_ctx(hdd_ctx); - - icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log); - - hdd_ctx->max_intf_count = CSR_ROAM_SESSION_MAX; - hdd_ctx->configuredMcastBcastFilter = hdd_ctx->config->mcastBcastFilterSetting; hdd_notice("Setting configuredMcastBcastFilter: %d", hdd_ctx->config->mcastBcastFilterSetting); + cds_set_fatal_event(hdd_ctx->config->enable_fatal_event); + hdd_override_ini_config(hdd_ctx); - ret = wlan_hdd_cfg80211_init(dev, hdd_ctx->wiphy, hdd_ctx->config); + ((cds_context_type *) (p_cds_context))->pHDDContext = (void *)hdd_ctx; - if (ret) { - hdd_err("CFG80211 wiphy init failed: %d", ret); + ret = hdd_context_init(hdd_ctx); + + if (ret) goto err_free_config; - } + + hdd_ctx->target_type = tgt_info->target_type; + + icnss_set_fw_debug_mode(hdd_ctx->config->enable_fw_log); hdd_enable_fastpath(hdd_ctx->config, hif_sc); @@ -5459,6 +5708,21 @@ static inline int hdd_open_p2p_interface(struct hdd_context_t *hdd_ctx, #endif /** + * hdd_open_monitor_interface() - Open monitor mode interface + * @hdd_ctx: HDD context + * @rtnl_held: True if RTNL lock is held + * + * Return: Primary adapter on success and PTR_ERR on failure + */ +static hdd_adapter_t *hdd_open_monitor_interface(hdd_context_t *hdd_ctx, + bool rtnl_held) +{ + return hdd_open_adapter(hdd_ctx, QDF_MONITOR_MODE, "wlan%d", + wlan_hdd_get_intf_addr(hdd_ctx), + NET_NAME_UNKNOWN, rtnl_held); +} + +/** * hdd_open_interfaces - Open all required interfaces * hdd_ctx: HDD context * rtnl_held: True if RTNL lock is held @@ -5671,6 +5935,124 @@ QDF_STATUS hdd_register_for_sap_restart_with_channel_switch(void) #endif /** + * hdd_tsf_init() - Initialize the TSF synchronization interface + * @hdd_ctx: HDD global context + * + * When TSF synchronization via GPIO is supported by the driver and + * has been enabled in the configuration file, this function plumbs + * the GPIO value down to firmware via SME. + * + * Return: None + */ +#ifdef WLAN_FEATURE_TSF +static void hdd_tsf_init(hdd_context_t *hdd_ctx) +{ + QDF_STATUS status; + + if (hdd_ctx->config->tsf_gpio_pin == TSF_GPIO_PIN_INVALID) + return; + + status = sme_set_tsf_gpio(hdd_ctx->hHal, + hdd_ctx->config->tsf_gpio_pin); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Set tsf GPIO failed, status: %d", status); +} +#else +static void hdd_tsf_init(hdd_context_t *hdd_ctx) +{ +} +#endif + +/** + * hdd_pre_enable_configure() - Configurations prior to cds_enable + * @hdd_ctx: HDD context + * + * Pre configurations to be done at lower layer before calling cds enable. + * + * Return: 0 on success and errno on failure. + */ +static int hdd_pre_enable_configure(hdd_context_t *hdd_ctx) +{ + int ret; + QDF_STATUS status; + tSirRetStatus hal_status; + + ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb); + + /* + * Set 802.11p config + * TODO-OCB: This has been temporarily added here to ensure this + * parameter is set in CSR when we init the channel list. This should + * be removed once the 5.9 GHz channels are added to the regulatory + * domain. + */ + hdd_set_dot11p_config(hdd_ctx); + + /* + * Note that the cds_pre_enable() sequence triggers the cfg download. + * The cfg download must occur before we update the SME config + * since the SME config operation must access the cfg database + */ + status = hdd_set_sme_config(hdd_ctx); + + if (QDF_STATUS_SUCCESS != status) { + hdd_alert("Failed hdd_set_sme_config: %d", status); + ret = qdf_status_to_os_return(status); + goto out; + } + + ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS, + hdd_ctx->config->tx_chain_mask_1ss, + PDEV_CMD); + if (0 != ret) { + hdd_err("WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", ret); + goto out; + } + + hdd_program_country_code(hdd_ctx); + + status = hdd_set_sme_chan_list(hdd_ctx); + if (status != QDF_STATUS_SUCCESS) { + hdd_alert("Failed to init channel list: %d", status); + ret = qdf_status_to_os_return(status); + goto out; + } + + /* Apply the cfg.ini to cfg.dat */ + if (!hdd_update_config_dat(hdd_ctx)) { + hdd_alert("config update failed"); + ret = -EINVAL; + goto out; + } + + status = hdd_update_mac_config(hdd_ctx); + if (QDF_STATUS_SUCCESS != status) { + hdd_warn("can't update mac config, using MAC from ini file: %d", + status); + } + + /* + * Set the MAC Address Currently this is used by HAL to add self sta. + * Remove this once self sta is added as part of session open. + */ + hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID, + hdd_ctx->config->intfMacAddr[0].bytes, + sizeof(hdd_ctx->config->intfMacAddr[0])); + + if (!IS_SIR_STATUS_SUCCESS(hal_status)) { + hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]", + hal_status, hal_status); + ret = -EINVAL; + goto out; + } + + hdd_init_channel_avoidance(hdd_ctx); + +out: + return ret; +} + +/** * hdd_wlan_startup() - HDD init function * @dev: Pointer to the underlying device * @@ -5686,18 +6068,16 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) int ret; tSirTxPowerLimit hddtxlimit; bool rtnl_held; - tSirRetStatus hal_status; - int ret_val; ENTER(); - if (WLAN_IS_EPPING_ENABLED(con_mode)) { + if (QDF_IS_EPPING_ENABLED(con_mode)) { ret = epping_enable(dev); EXIT(); return ret; } - hdd_ctx = hdd_init_context(dev, hif_sc); + hdd_ctx = hdd_context_create(dev, hif_sc); if (IS_ERR(hdd_ctx)) return PTR_ERR(hdd_ctx); @@ -5734,80 +6114,15 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto err_cds_close; } - ol_txrx_register_pause_cb(wlan_hdd_txrx_pause_cb); - - ret_val = hdd_wiphy_init(hdd_ctx); - - if (ret_val) { - hdd_alert("failed to initialize wiphy"); + ret = hdd_wiphy_init(hdd_ctx); + if (ret) { + hdd_alert("Failed to initialize wiphy: %d", ret); goto err_cds_close; } - /* - * Set 802.11p config - * TODO-OCB: This has been temporarily added here to ensure this - * parameter is set in CSR when we init the channel list. This should - * be removed once the 5.9 GHz channels are added to the regulatory - * domain. - */ - hdd_set_dot11p_config(hdd_ctx); - - /* - * Note that the cds_pre_enable() sequence triggers the cfg download. - * The cfg download must occur before we update the SME config - * since the SME config operation must access the cfg database - */ - status = hdd_set_sme_config(hdd_ctx); - - if (QDF_STATUS_SUCCESS != status) { - hddLog(QDF_TRACE_LEVEL_FATAL, FL("Failed hdd_set_sme_config")); - goto err_wiphy_unregister; - } - - ret = wma_cli_set_command(0, WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS, - hdd_ctx->config->tx_chain_mask_1ss, - PDEV_CMD); - if (0 != ret) { - hddLog(QDF_TRACE_LEVEL_ERROR, - "%s: WMI_PDEV_PARAM_TX_CHAIN_MASK_1SS failed %d", - __func__, ret); - } - - hdd_program_country_code(hdd_ctx); - - status = hdd_set_sme_chan_list(hdd_ctx); - if (status != QDF_STATUS_SUCCESS) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("Failed to init channel list")); - goto err_wiphy_unregister; - } - - /* Apply the cfg.ini to cfg.dat */ - if (false == hdd_update_config_dat(hdd_ctx)) { - hddLog(QDF_TRACE_LEVEL_FATAL, - FL("config update failed")); - goto err_wiphy_unregister; - } - - if (QDF_STATUS_SUCCESS != hdd_update_mac_config(hdd_ctx)) { - hddLog(QDF_TRACE_LEVEL_WARN, - FL("can't update mac config, using MAC from ini file")); - } - - /* - * Set the MAC Address Currently this is used by HAL to add self sta. - * Remove this once self sta is added as part of session open. - */ - hal_status = cfg_set_str(hdd_ctx->hHal, WNI_CFG_STA_ID, - hdd_ctx->config->intfMacAddr[0].bytes, - sizeof(hdd_ctx->config->intfMacAddr[0])); - - if (!IS_SIR_STATUS_SUCCESS(hal_status)) { - hdd_err("Failed to set MAC Address. HALStatus is %08d [x%08x]", - hal_status, hal_status); - ret = -EINVAL; + ret = hdd_pre_enable_configure(hdd_ctx); + if (ret) goto err_wiphy_unregister; - } if (hdd_ipa_init(hdd_ctx) == QDF_STATUS_E_FAILURE) goto err_wiphy_unregister; @@ -5822,8 +6137,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto err_ipa_cleanup; } - hdd_init_channel_avoidance(hdd_ctx); - status = hdd_post_cds_enable_config(hdd_ctx); if (!QDF_IS_STATUS_SUCCESS(status)) { hddLog(QDF_TRACE_LEVEL_FATAL, @@ -5831,11 +6144,12 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) goto err_cds_disable; } - cds_pkt_proto_trace_init(); - rtnl_held = hdd_hold_rtnl_lock(); - adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); + if (QDF_GLOBAL_MONITOR_MODE == hdd_get_conparam()) + adapter = hdd_open_monitor_interface(hdd_ctx, rtnl_held); + else + adapter = hdd_open_interfaces(hdd_ctx, rtnl_held); if (IS_ERR(adapter)) { ret = PTR_ERR(adapter); @@ -5869,7 +6183,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) ret = hdd_init_netlink_services(hdd_ctx); if (ret) - goto err_debugfs_exit; + goto err_close_adapter; /* * Action frame registered in one adapter which will @@ -5880,21 +6194,6 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) hdd_release_rtnl_lock(); rtnl_held = false; - ret = register_netdevice_notifier(&hdd_netdev_notifier); - if (ret < 0) { - hdd_err("register_netdevice_notifier failed: %d", ret); - goto err_exit_nl_srv; - } - -#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - /* Initialize the wake lcok */ - qdf_wake_lock_create(&hdd_ctx->rx_wake_lock, "qcom_rx_wakelock"); -#endif - /* Initialize the wake lcok */ - qdf_wake_lock_create(&hdd_ctx->sap_wake_lock, "qcom_sap_wakelock"); - - hdd_hostapd_channel_wakelock_init(hdd_ctx); - if (hdd_ctx->config->fIsImpsEnabled) hdd_set_idle_ps_config(hdd_ctx, true); else @@ -5942,6 +6241,7 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) if (QDF_IS_STATUS_SUCCESS(status)) hdd_err("Error setting txlimit in sme: %d", status); + hdd_tsf_init(hdd_ctx); #ifdef MSM_PLATFORM spin_lock_init(&hdd_ctx->bus_bw_lock); qdf_mc_timer_init(&hdd_ctx->bus_bw_timer, @@ -5956,64 +6256,41 @@ int hdd_wlan_startup(struct device *dev, void *hif_sc) status = hdd_register_for_sap_restart_with_channel_switch(); if (!QDF_IS_STATUS_SUCCESS(status)) - /* Error already logged */ - goto err_unreg_netdev_notifier; + goto err_exit_nl_srv; sme_set_rssi_threshold_breached_cb(hdd_ctx->hHal, hdd_rssi_threshold_breached); - hdd_cfg80211_link_layer_stats_init(hdd_ctx); + status = sme_bpf_offload_register_callback(hdd_ctx->hHal, + hdd_get_bpf_offload_cb); + if (QDF_IS_STATUS_SUCCESS(status)) + hdd_err("set bpf offload callback failed"); + hdd_cfg80211_link_layer_stats_init(hdd_ctx); + wlan_hdd_tsf_init(hdd_ctx); wlan_hdd_send_all_scan_intf_info(hdd_ctx); wlan_hdd_send_version_pkg(hdd_ctx->target_fw_version, hdd_ctx->target_hw_version, hdd_ctx->target_hw_name); - qdf_spinlock_create(&hdd_ctx->hdd_roc_req_q_lock); - qdf_list_create((&hdd_ctx->hdd_roc_req_q), MAX_ROC_REQ_QUEUE_ENTRY); - qdf_spinlock_create(&hdd_ctx->hdd_scan_req_q_lock); - qdf_list_create((&hdd_ctx->hdd_scan_req_q), CFG_MAX_SCAN_COUNT_MAX); -#ifdef CONFIG_CNSS - cnss_init_delayed_work(&hdd_ctx->roc_req_work, - wlan_hdd_roc_request_dequeue); -#else - INIT_DELAYED_WORK(&hdd_ctx->roc_req_work, wlan_hdd_roc_request_dequeue); -#endif - - /* - * Register IPv6 notifier to notify if any change in IP - * So that we can reconfigure the offload parameters - */ - hdd_wlan_register_ip6_notifier(hdd_ctx); - - /* - * Register IPv4 notifier to notify if any change in IP - * So that we can reconfigure the offload parameters - */ - hdd_ctx->ipv4_notifier.notifier_call = wlan_hdd_ipv4_changed; - ret = register_inetaddr_notifier(&hdd_ctx->ipv4_notifier); - if (ret) - hddLog(LOGE, FL("Failed to register IPv4 notifier")); - else - hdd_info("Registered IPv4 notifier"); - wlan_hdd_dcc_register_for_dcc_stats_event(hdd_ctx); if (hdd_ctx->config->dual_mac_feature_disable) { status = wlan_hdd_disable_all_dual_mac_features(hdd_ctx); if (status != QDF_STATUS_SUCCESS) { hdd_err("Failed to disable dual mac features"); - goto err_unreg_netdev_notifier; + goto err_exit_nl_srv; } } + ret = hdd_register_notifiers(hdd_ctx); + if (ret) + goto err_exit_nl_srv; + memdump_init(); goto success; -err_unreg_netdev_notifier: - unregister_netdevice_notifier(&hdd_netdev_notifier); - err_exit_nl_srv: hdd_exit_netlink_services(hdd_ctx); @@ -6022,9 +6299,6 @@ err_exit_nl_srv: /* Proceed and complete the clean up */ } -err_debugfs_exit: - hdd_debugfs_exit(adapter); - err_close_adapter: hdd_release_rtnl_lock(); @@ -6049,7 +6323,7 @@ err_cds_close: cds_close(hdd_ctx->pcds_context); err_hdd_free_context: - hdd_free_context(hdd_ctx); + hdd_context_destroy(hdd_ctx); QDF_BUG(1); return -EIO; @@ -7019,6 +7293,8 @@ static int __hdd_module_init(void) pr_info("%s: Loading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR); + pld_init(); + qdf_wake_lock_create(&wlan_wake_lock, "wlan"); hdd_set_conparam((uint32_t) con_mode); @@ -7034,6 +7310,7 @@ static int __hdd_module_init(void) return 0; out: qdf_wake_lock_destroy(&wlan_wake_lock); + pld_deinit(); return ret; } @@ -7051,6 +7328,8 @@ static void __hdd_module_exit(void) qdf_wake_lock_destroy(&wlan_wake_lock); + pld_deinit(); + return; } diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index b54a41baba96..89a25740cde6 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -206,9 +206,7 @@ QDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx, if (REMAIN_ON_CHANNEL_REQUEST == pRemainChanCtx->rem_on_chan_request) { if (cfgState->buf) { - hddLog(LOGP, - "%s: We need to receive yet an ack from one of tx packet", - __func__); + hdd_info("We need to receive yet an ack from one of tx packet"); } cfg80211_remain_on_channel_expired( pRemainChanCtx->dev-> @@ -319,6 +317,10 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter) hddLog(LOGE, "%s: timeout waiting for remain on channel ready indication", __func__); + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_HDD_TIME_OUT, + true, false); } INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); @@ -1171,6 +1173,10 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, cds_get_driver_state()); return -EAGAIN; } + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_HDD_TIME_OUT, + true, false); } INIT_COMPLETION(pAdapter->cancel_rem_on_chan_var); /* Issue abort remain on chan request to sme. @@ -2247,8 +2253,8 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, + 2], SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE)) { /* P2P action frames */ - u8 *macFrom = - &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET + 6]; + u8 *macFrom = &pbFrames + [WLAN_HDD_80211_PEER_ADDR_OFFSET]; actionFrmType = pbFrames [WLAN_HDD_PUBLIC_ACTION_FRAME_TYPE_OFFSET]; @@ -2409,8 +2415,8 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, else if (pbFrames [WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET + 1] == WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP) { - u8 *mac = - &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET + 6]; + u8 *mac = &pbFrames + [WLAN_HDD_80211_PEER_ADDR_OFFSET]; hddLog(LOG1, "[TDLS] TDLS Discovery Response," @@ -2420,6 +2426,10 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, wlan_hdd_tdls_set_rssi(pAdapter, mac, rxRssi); wlan_hdd_tdls_recv_discovery_resp(pAdapter, mac); + cds_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS, + SIR_MAC_ACTION_RX, SIR_MAC_MGMT_ACTION, + WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP, + &pbFrames[WLAN_HDD_80211_PEER_ADDR_OFFSET]); } #endif } @@ -2437,6 +2447,10 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, "[TDLS] %s <--- OTA", tdls_action_frame_type[actionFrmType]); } + cds_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS, + SIR_MAC_ACTION_RX, SIR_MAC_MGMT_ACTION, + actionFrmType, + &pbFrames[WLAN_HDD_80211_PEER_ADDR_OFFSET]); } if ((pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == diff --git a/core/hdd/src/wlan_hdd_power.c b/core/hdd/src/wlan_hdd_power.c index 7961eb5a626d..7346aa087605 100644 --- a/core/hdd/src/wlan_hdd_power.c +++ b/core/hdd/src/wlan_hdd_power.c @@ -87,6 +87,46 @@ enum hdd_power_mode { DRIVER_POWER_MODE_ACTIVE = 1, }; +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * hdd_wlan_suspend_resume_event()- send suspend/resume state + * @state: suspend/resume state + * + * This Function send send suspend resume state diag event + * + * Return: void. + */ +void hdd_wlan_suspend_resume_event(uint8_t state) +{ + WLAN_HOST_DIAG_EVENT_DEF(suspend_state, struct host_event_suspend); + qdf_mem_zero(&suspend_state, sizeof(suspend_state)); + + suspend_state.state = state; + WLAN_HOST_DIAG_EVENT_REPORT(&suspend_state, EVENT_WLAN_SUSPEND_RESUME); +} + +/** + * hdd_wlan_offload_event()- send offloads event + * @type: offload type + * @state: enabled or disabled + * + * This Function send offloads enable/disable diag event + * + * Return: void. + */ + +void hdd_wlan_offload_event(uint8_t type, uint8_t state) +{ + WLAN_HOST_DIAG_EVENT_DEF(host_offload, struct host_event_offload_req); + qdf_mem_zero(&host_offload, sizeof(host_offload)); + + host_offload.offload_type = type; + host_offload.state = state; + + WLAN_HOST_DIAG_EVENT_REPORT(&host_offload, EVENT_WLAN_OFFLOAD_REQ); +} +#endif + /* Function and variables declarations */ extern struct notifier_block hdd_netdev_notifier; @@ -387,6 +427,8 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable) &offLoadRequest.nsOffloadInfo.selfIPv6Addr[i], &offLoadRequest.nsOffloadInfo.targetIPv6Addr[i], i); } + hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD, + SIR_OFFLOAD_ENABLE); offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; qdf_copy_macaddr(&offLoadRequest.nsOffloadInfo.self_macaddr, @@ -405,6 +447,8 @@ static void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, bool fenable) return; } } else { + hdd_wlan_offload_event(SIR_IPV6_NS_OFFLOAD, + SIR_OFFLOAD_DISABLE); /* Disable NSOffload */ qdf_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; @@ -720,6 +764,8 @@ QDF_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, bool fenable) if (ifa && ifa->ifa_local) { offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; + hdd_wlan_offload_event(SIR_IPV4_ARP_REPLY_OFFLOAD, + SIR_OFFLOAD_ENABLE); hddLog(QDF_TRACE_LEVEL_INFO, "%s: Enabled", __func__); @@ -734,7 +780,9 @@ QDF_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, bool fenable) hddLog(QDF_TRACE_LEVEL_INFO, "offload: inside arp offload conditional check"); } - + hdd_wlan_offload_event( + SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE, + SIR_OFFLOAD_ENABLE); hddLog(QDF_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d", offLoadRequest.enableOrDisable); @@ -767,6 +815,8 @@ QDF_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, bool fenable) return QDF_STATUS_SUCCESS; } else { + hdd_wlan_offload_event(SIR_IPV4_ARP_REPLY_OFFLOAD, + SIR_OFFLOAD_DISABLE); qdf_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; @@ -810,6 +860,7 @@ static void hdd_mcbc_filter_modification(hdd_context_t *pHddCtx, * of Broadcast BIT */ *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); + hdd_info("ARP offload is enabled"); } #ifdef WLAN_NS_OFFLOAD if (pHddCtx->config->fhostNSOffload) { @@ -818,6 +869,7 @@ static void hdd_mcbc_filter_modification(hdd_context_t *pHddCtx, * disable Multicast filtering, Anding with the negation * of Multicast BIT */ + hdd_info("NS offload is enabled"); *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); } #endif @@ -1137,6 +1189,7 @@ hdd_suspend_wlan(void (*callback)(void *callbackContext, bool suspended), callbackContext); pHddCtx->hdd_wlan_suspended = true; + hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_SUSPEND); return; } @@ -1170,6 +1223,7 @@ static void hdd_resume_wlan(void) } pHddCtx->hdd_wlan_suspended = false; + hdd_wlan_suspend_resume_event(HDD_WLAN_EARLY_RESUME); /*loop through all adapters. Concurrency */ status = hdd_get_front_adapter(pHddCtx, &pAdapterNode); diff --git a/core/hdd/src/wlan_hdd_scan.c b/core/hdd/src/wlan_hdd_scan.c index d35f21bd0d0f..b2c367d03288 100644 --- a/core/hdd/src/wlan_hdd_scan.c +++ b/core/hdd/src/wlan_hdd_scan.c @@ -1331,13 +1331,8 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, */ pAdapter->request = request; -#ifdef CONFIG_CNSS - cnss_init_work(&pAdapter->scan_block_work, - wlan_hdd_cfg80211_scan_block_cb); -#else INIT_WORK(&pAdapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb); -#endif schedule_work(&pAdapter->scan_block_work); return 0; } @@ -1378,6 +1373,7 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, else hddLog(LOGE, FL("TDLS teardown is ongoing %d"), status); + hdd_wlan_block_scan_by_tdls_event(); return status; } #endif @@ -1390,7 +1386,6 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy, qdf_mem_zero(&scan_req, sizeof(scan_req)); - hddLog(LOG1, "scan request for ssid = %d", request->n_ssids); scan_req.timestamp = qdf_mc_timer_get_system_ticks(); /* Even though supplicant doesn't provide any SSIDs, n_ssids is @@ -2494,3 +2489,35 @@ void hdd_cleanup_scan_queue(hdd_context_t *hdd_ctx) return; } + +/** + * hdd_scan_context_destroy() - Destroy scan context + * @hdd_ctx: HDD context. + * + * Destroy scan context. + * + * Return: None. + */ +void hdd_scan_context_destroy(hdd_context_t *hdd_ctx) +{ + qdf_list_destroy(&hdd_ctx->hdd_scan_req_q); + qdf_spinlock_destroy(&hdd_ctx->sched_scan_lock); +} + +/** + * hdd_scan_context_init() - Initialize scan context + * @hdd_ctx: HDD context. + * + * Initialize scan related resources like spin lock and lists. + * + * Return: 0 on success and errno on failure. + */ +int hdd_scan_context_init(hdd_context_t *hdd_ctx) +{ + qdf_spinlock_create(&hdd_ctx->sched_scan_lock); + + qdf_spinlock_create(&hdd_ctx->hdd_scan_req_q_lock); + qdf_list_create(&hdd_ctx->hdd_scan_req_q, CFG_MAX_SCAN_COUNT_MAX); + + return 0; +} diff --git a/core/hdd/src/wlan_hdd_scan.h b/core/hdd/src/wlan_hdd_scan.h index 8b1d7489d80f..50a6a8ddf273 100644 --- a/core/hdd/src/wlan_hdd_scan.h +++ b/core/hdd/src/wlan_hdd_scan.h @@ -50,6 +50,9 @@ int iw_get_scan(struct net_device *dev, struct iw_request_info *info, int iw_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +int hdd_scan_context_init(hdd_context_t *hdd_ctx); +void hdd_scan_context_destroy(hdd_context_t *hdd_ctx); + int wlan_hdd_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); diff --git a/core/hdd/src/wlan_hdd_tdls.c b/core/hdd/src/wlan_hdd_tdls.c index e0978c31b2e1..a0077b4b106c 100644 --- a/core/hdd/src/wlan_hdd_tdls.c +++ b/core/hdd/src/wlan_hdd_tdls.c @@ -85,6 +85,85 @@ static void wlan_hdd_tdls_determine_channel_opclass(hdd_context_t *hddctx, } } +#ifdef FEATURE_WLAN_DIAG_SUPPORT +/** + * hdd_send_wlan_tdls_teardown_event()- send TDLS teardown event + * @reason: reason for tear down. + * @peer_mac: peer mac + * + * This Function sends TDLS teardown diag event + * + * Return: void. + */ +void hdd_send_wlan_tdls_teardown_event(uint32_t reason, + uint8_t *peer_mac) +{ + WLAN_HOST_DIAG_EVENT_DEF(tdls_tear_down, + struct host_event_tdls_teardown); + qdf_mem_zero(&tdls_tear_down, + sizeof(tdls_tear_down)); + + tdls_tear_down.reason = reason; + qdf_mem_copy(tdls_tear_down.peer_mac, peer_mac, MAC_ADDR_LEN); + WLAN_HOST_DIAG_EVENT_REPORT(&tdls_tear_down, + EVENT_WLAN_TDLS_TEARDOWN); +} + +/** + * hdd_wlan_tdls_enable_link_event()- send TDLS enable link event + * @peer_mac: peer mac + * @is_off_chan_supported: Does peer supports off chan + * @is_off_chan_configured: If off channel is configured + * @is_off_chan_established: If off chan is established + * + * This Function send TDLS enable link diag event + * + * Return: void. + */ + +void hdd_wlan_tdls_enable_link_event(const uint8_t *peer_mac, + uint8_t is_off_chan_supported, + uint8_t is_off_chan_configured, + uint8_t is_off_chan_established) +{ + WLAN_HOST_DIAG_EVENT_DEF(tdls_event, + struct host_event_tdls_enable_link); + + qdf_mem_copy(tdls_event.peer_mac, + peer_mac, MAC_ADDR_LEN); + + tdls_event.is_off_chan_supported = + is_off_chan_supported; + tdls_event.is_off_chan_configured = + is_off_chan_configured; + tdls_event.is_off_chan_established = + is_off_chan_established; + + WLAN_HOST_DIAG_EVENT_REPORT(&tdls_event, + EVENT_WLAN_TDLS_ENABLE_LINK); +} + +/** + * hdd_wlan_block_scan_by_tdls_event()- send event + * if scan is blocked by tdls + * + * This Function send send diag event if scan is + * blocked by tdls + * + * Return: void. + */ +void hdd_wlan_block_scan_by_tdls_event(void) +{ + WLAN_HOST_DIAG_EVENT_DEF(tdls_scan_block_status, + struct host_event_tdls_scan_rejected); + + tdls_scan_block_status.status = true; + WLAN_HOST_DIAG_EVENT_REPORT(&tdls_scan_block_status, + EVENT_TDLS_SCAN_BLOCK); +} + +#endif + /** * wlan_hdd_tdls_hash_key() - calculate tdls hash key given mac address * @mac: mac address @@ -168,6 +247,8 @@ void wlan_hdd_tdls_disable_offchan_and_teardown_links(hdd_context_t *hddctx) curr_peer->pHddTdlsCtx->pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + hdd_send_wlan_tdls_teardown_event(eTDLS_TEARDOWN_CONCURRENCY, + curr_peer->peerMac); } } @@ -508,21 +589,32 @@ static void wlan_hdd_tdls_del_non_forced_peers(tdlsCtx_t *hdd_tdls_ctx) } /** - * hdd_tdls_pre_init - TDLS pre init + * hdd_tdls_context_init() - Init TDLS context * @hdd_ctx: HDD context * - * tdls_lock is initialized before an hdd_open_adapter ( which is - * invoked by other instances also) to protect the concurrent - * access for the Adapters by TDLS module. + * Initialize TDLS global context. * * Return: None */ -void hdd_tdls_pre_init(hdd_context_t *hdd_ctx) +void hdd_tdls_context_init(hdd_context_t *hdd_ctx) { mutex_init(&hdd_ctx->tdls_lock); } /** + * hdd_tdls_context_destroy() - Destroy TDLS context + * @hdd_ctx: HDD context + * + * Destroy TDLS global context. + * + * Return: None + */ +void hdd_tdls_context_destroy(hdd_context_t *hdd_ctx) +{ + mutex_destroy(&hdd_ctx->tdls_lock); +} + +/** * wlan_hdd_tdls_init() - tdls initializaiton * @pAdapter: hdd adapter * @@ -658,19 +750,10 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) pHddCtx->tdls_mode = eTDLS_SUPPORT_ENABLED; } -#ifdef CONFIG_CNSS - cnss_init_work(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); -#else INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); -#endif -#ifdef CONFIG_CNSS - cnss_init_delayed_work(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, - wlan_hdd_tdls_schedule_scan); -#else INIT_DELAYED_WORK(&pHddCtx->tdls_scan_ctxt.tdls_scan_work, wlan_hdd_tdls_schedule_scan); -#endif /* * Release tdls lock before calling in SME api @@ -748,7 +831,7 @@ void wlan_hdd_tdls_exit(hdd_adapter_t *pAdapter) pHddCtx = WLAN_HDD_GET_CTX(pAdapter); if (!pHddCtx) { - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, + QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_WARN, FL("pHddCtx is NULL")); return; } @@ -2764,6 +2847,9 @@ int wlan_hdd_tdls_scan_callback(hdd_adapter_t *pAdapter, struct wiphy *wiphy, (connectedPeerList[i]->pHddTdlsCtx-> pAdapter, connectedPeerList[i], eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + hdd_send_wlan_tdls_teardown_event( + eTDLS_TEARDOWN_SCAN, + connectedPeerList[i]->peerMac); } } /* schedule scan */ @@ -2876,6 +2962,7 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, wlan_hdd_tdls_set_peer_link_status(curr_peer, eTDLS_LINK_TEARING, eTDLS_LINK_UNSPECIFIED); + hdd_info("Teardown reason %d", reason); cfg80211_tdls_oper_request(pAdapter->dev, curr_peer->peerMac, NL80211_TDLS_TEARDOWN, reason, GFP_KERNEL); @@ -3899,7 +3986,11 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, cds_get_driver_state()); return -EAGAIN; } - + if (rc <= 0) + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_HDD_TIME_OUT, + true, false); pAdapter->mgmtTxCompletionStatus = false; return -EINVAL; } @@ -4117,6 +4208,9 @@ int wlan_hdd_tdls_extctrl_deconfig_peer(hdd_adapter_t *pAdapter, } else { wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + hdd_send_wlan_tdls_teardown_event( + eTDLS_TEARDOWN_EXT_CTRL, + pTdlsPeer->peerMac); } if (0 != wlan_hdd_tdls_set_force_peer(pAdapter, peer, false)) { QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, @@ -4425,7 +4519,9 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, } } } - + hdd_wlan_tdls_enable_link_event(peer, + pTdlsPeer->isOffChannelSupported, + 0, 0); } break; case NL80211_TDLS_DISABLE_LINK: @@ -4519,7 +4615,7 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, return -ENOTSUPP; default: QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_ERROR, - "%s: unsupported event", __func__); + "%s: unsupported event %d", __func__, oper); return -ENOTSUPP; } EXIT(); diff --git a/core/hdd/src/wlan_hdd_tsf.c b/core/hdd/src/wlan_hdd_tsf.c new file mode 100644 index 000000000000..2563a94bddbd --- /dev/null +++ b/core/hdd/src/wlan_hdd_tsf.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +/** + * wlan_hdd_tsf.c - WLAN Host Device Driver tsf related implementation + */ + +#include "wlan_hdd_main.h" +#include "wma_api.h" + +/** + * hdd_capture_tsf() - capture tsf + * @adapter: pointer to adapter + * @buf: pointer to uplayer buf + * @len : the length of buf + * + * This function returns tsf value to uplayer. + * + * Return: 0 for success or non-zero negative failure code + */ +int hdd_capture_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len) +{ + int ret = 0; + hdd_station_ctx_t *hdd_sta_ctx; + + if (adapter == NULL || buf == NULL) { + hdd_err(FL("invalid pointer")); + return -EINVAL; + } + if (len != 1) + return -EINVAL; + + /* Reset TSF value for new capture */ + adapter->tsf_high = 0; + adapter->tsf_low = 0; + + if (adapter->device_mode == QDF_STA_MODE || + adapter->device_mode == QDF_P2P_CLIENT_MODE) { + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (hdd_sta_ctx->conn_info.connState != + eConnectionState_Associated) { + + hdd_err(FL("failed to cap tsf, not connect with ap")); + buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF; + return ret; + } + } + if ((adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) && + !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) { + hdd_err(FL("Soft AP / P2p GO not beaconing")); + buf[0] = TSF_SAP_NOT_STARTED_NO_TSF; + return ret; + } + if (adapter->tsf_state == TSF_CAP_STATE) { + hdd_err(FL("current in capture state, pls reset")); + buf[0] = TSF_CURRENT_IN_CAP_STATE; + } else { + hdd_info(FL("Send TSF capture to FW")); + buf[0] = TSF_RETURN; + adapter->tsf_state = TSF_CAP_STATE; + ret = wma_cli_set_command((int)adapter->sessionId, + (int)GEN_PARAM_CAPTURE_TSF, + adapter->sessionId, + GEN_CMD); + + if (ret != QDF_STATUS_SUCCESS) { + hdd_err(FL("capture fail")); + buf[0] = TSF_CAPTURE_FAIL; + adapter->tsf_state = TSF_IDLE; + } + } + return ret; +} + +/** + * hdd_indicate_tsf() - return tsf to uplayer + * @adapter: pointer to adapter + * @buf: pointer to uplayer buf + * @len : the length of buf + * + * This function returns tsf value to upper layer. + * + * Return: 0 for success or non-zero negative failure code + */ +int hdd_indicate_tsf(struct hdd_adapter_s *adapter, uint32_t *buf, int len) +{ + int ret = 0; + hdd_station_ctx_t *hdd_sta_ctx; + + if (adapter == NULL || buf == NULL) { + hdd_err(FL("invalid pointer")); + return -EINVAL; + } + + if (len != 3) + return -EINVAL; + + buf[1] = 0; + buf[2] = 0; + if (adapter->device_mode == QDF_STA_MODE || + adapter->device_mode == QDF_P2P_CLIENT_MODE) { + hdd_sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + if (hdd_sta_ctx->conn_info.connState != + eConnectionState_Associated) { + + hdd_info(FL("fail to get tsf, sta in disconnected")); + buf[0] = TSF_STA_NOT_CONNECTED_NO_TSF; + return ret; + } + } + if ((adapter->device_mode == QDF_SAP_MODE || + adapter->device_mode == QDF_P2P_GO_MODE) && + !(test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags))) { + hdd_err(FL("Soft AP / P2p GO not beaconing")); + buf[0] = TSF_SAP_NOT_STARTED_NO_TSF; + return ret; + } + if (adapter->tsf_high == 0 && adapter->tsf_low == 0) { + hdd_info(FL("TSF value not received")); + buf[0] = TSF_NOT_RETURNED_BY_FW; + } else { + buf[0] = TSF_RETURN; + buf[1] = adapter->tsf_low; + buf[2] = adapter->tsf_high; + adapter->tsf_state = TSF_IDLE; + + ret = wma_cli_set_command((int)adapter->sessionId, + (int)GEN_PARAM_RESET_TSF_GPIO, + adapter->sessionId, + GEN_CMD); + + if (0 != ret) { + hdd_err(FL("tsf get fail ")); + buf[0] = TSF_RESET_GPIO_FAIL; + } + hdd_info(FL("get tsf cmd,status=%u, tsf_low=%u, tsf_high=%u"), + buf[0], buf[1], buf[2]); + } + return ret; +} + +/** + * hdd_get_tsf_cb() - handle tsf callback + * @pcb_cxt: pointer to the hdd_contex + * @ptsf: pointer to struct stsf + * + * This function handle the event that reported by firmware at first. + * The event contains the vdev_id, current tsf value of this vdev, + * tsf value is 64bits, discripted in two varaible tsf_low and tsf_high. + * These two values each is uint32. + * + * Return: 0 for success or non-zero negative failure code + */ +static int hdd_get_tsf_cb(void *pcb_cxt, struct stsf *ptsf) +{ + struct hdd_context_s *hddctx; + struct hdd_adapter_s *adapter; + int status; + + if (pcb_cxt == NULL || ptsf == NULL) { + hdd_err(FL("HDD context is not valid")); + return -EINVAL; + } + + hddctx = (struct hdd_context_s *)pcb_cxt; + status = wlan_hdd_validate_context(hddctx); + if (0 != status) { + hdd_err(FL("hdd context is not valid")); + return -EINVAL; + } + + adapter = hdd_get_adapter_by_vdev(hddctx, ptsf->vdev_id); + + if (NULL == adapter) { + hdd_err(FL("failed to find adapter")); + return -EINVAL; + } + + hdd_info(FL("tsf cb handle event, device_mode is %d"), + adapter->device_mode); + + adapter->tsf_low = ptsf->tsf_low; + adapter->tsf_high = ptsf->tsf_high; + + hdd_info(FL("hdd_get_tsf_cb sta=%u, tsf_low=%u, tsf_high=%u"), + ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high); + return 0; +} + +/** + * wlan_hdd_tsf_init() - set callback to handle tsf value. + * @hdd_ctx: pointer to the struct hdd_context_s + * + * This function set the callback to sme module, the callback will be + * called when a tsf event is reported by firmware + * + * Return: none + */ +void wlan_hdd_tsf_init(struct hdd_context_s *hdd_ctx) +{ + sme_set_tsfcb(hdd_ctx->hHal, hdd_get_tsf_cb, hdd_ctx); +} diff --git a/core/hdd/src/wlan_hdd_tx_rx.c b/core/hdd/src/wlan_hdd_tx_rx.c index 60d3162afaed..2e390476d5ef 100644 --- a/core/hdd/src/wlan_hdd_tx_rx.c +++ b/core/hdd/src/wlan_hdd_tx_rx.c @@ -55,6 +55,7 @@ #include "wlan_hdd_lro.h" #include "cdp_txrx_peer_ops.h" +#include "ol_txrx.h" #ifdef FEATURE_WLAN_DIAG_SUPPORT #define HDD_EAPOL_ETHER_TYPE (0x888E) @@ -670,6 +671,84 @@ QDF_STATUS hdd_deinit_tx_rx(hdd_adapter_t *pAdapter) } /** + * hdd_mon_rx_packet_cbk() - Receive callback registered with OL layer. + * @context: [in] pointer to qdf context + * @rxBuf: [in] pointer to rx qdf_nbuf + * + * TL will call this to notify the HDD when one or more packets were + * received for a registered STA. + * + * Return: QDF_STATUS_E_FAILURE if any errors encountered, QDF_STATUS_SUCCESS + * otherwise + */ +static QDF_STATUS hdd_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf) +{ + hdd_adapter_t *adapter; + int rxstat; + struct sk_buff *skb; + struct sk_buff *skb_next; + unsigned int cpu_index; + + /* Sanity check on inputs */ + if ((NULL == context) || (NULL == rxbuf)) { + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR, + "%s: Null params being passed", __func__); + return QDF_STATUS_E_FAILURE; + } + + adapter = (hdd_adapter_t *)context; + if ((NULL == adapter) || (WLAN_HDD_ADAPTER_MAGIC != adapter->magic)) { + QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR, + "invalid adapter %p", adapter); + return QDF_STATUS_E_FAILURE; + } + + cpu_index = wlan_hdd_get_cpu(); + + /* walk the chain until all are processed */ + skb = (struct sk_buff *) rxbuf; + while (NULL != skb) { + skb_next = skb->next; + skb->dev = adapter->dev; + + ++adapter->hdd_stats.hddTxRxStats.rxPackets[cpu_index]; + ++adapter->stats.rx_packets; + adapter->stats.rx_bytes += skb->len; + + /* Remove SKB from internal tracking table before submitting + * it to stack + */ + qdf_net_buf_debug_release_skb(skb); + + /* + * If this is not a last packet on the chain + * Just put packet into backlog queue, not scheduling RX sirq + */ + if (skb->next) { + rxstat = netif_rx(skb); + } else { + /* + * This is the last packet on the chain + * Scheduling rx sirq + */ + rxstat = netif_rx_ni(skb); + } + + if (NET_RX_SUCCESS == rxstat) + ++adapter-> + hdd_stats.hddTxRxStats.rxDelivered[cpu_index]; + else + ++adapter->hdd_stats.hddTxRxStats.rxRefused[cpu_index]; + + skb = skb_next; + } + + adapter->dev->last_rx = jiffies; + + return QDF_STATUS_SUCCESS; +} + +/** * hdd_rx_packet_cbk() - Receive packet handler * @context: pointer to HDD context * @rxBuf: pointer to rx qdf_nbuf @@ -1108,3 +1187,45 @@ void wlan_hdd_netif_queue_control(hdd_adapter_t *adapter, return; } +/** + * hdd_set_mon_rx_cb() - Set Monitor mode Rx callback + * @dev: Pointer to net_device structure + * + * Return: 0 for success; non-zero for failure + */ +int hdd_set_mon_rx_cb(struct net_device *dev) +{ + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + int ret; + QDF_STATUS qdf_status; + struct ol_txrx_desc_type sta_desc = {0}; + struct ol_txrx_ops txrx_ops; + + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + qdf_mem_zero(&txrx_ops, sizeof(txrx_ops)); + txrx_ops.rx.rx = hdd_mon_rx_packet_cbk; + ol_txrx_vdev_register( + ol_txrx_get_vdev_from_vdev_id(adapter->sessionId), + adapter, &txrx_ops); + /* peer is created wma_vdev_attach->wma_create_peer */ + qdf_status = ol_txrx_register_peer(&sta_desc); + if (QDF_STATUS_SUCCESS != qdf_status) { + hdd_err("WLANTL_RegisterSTAClient() failed to register. Status= %d [0x%08X]", + qdf_status, qdf_status); + goto exit; + } + + qdf_status = sme_create_mon_session(hdd_ctx->hHal, + adapter->macAddressCurrent.bytes); + if (QDF_STATUS_SUCCESS != qdf_status) { + hdd_err("sme_create_mon_session() failed to register. Status= %d [0x%08X]", + qdf_status, qdf_status); + } +exit: + ret = qdf_status_to_os_return(qdf_status); + return ret; +} diff --git a/core/hdd/src/wlan_hdd_wext.c b/core/hdd/src/wlan_hdd_wext.c index f8f4137c4e6c..28a9522582cc 100644 --- a/core/hdd/src/wlan_hdd_wext.c +++ b/core/hdd/src/wlan_hdd_wext.c @@ -80,6 +80,7 @@ #include "sme_power_save_api.h" #include "cds_concurrency.h" #include "wlan_hdd_conc_ut.h" +#include "wlan_hdd_tsf.h" #include "wlan_hdd_ocb.h" #include "wlan_hdd_napi.h" #include "cdp_txrx_flow_ctrl_legacy.h" @@ -215,6 +216,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { /* Private sub ioctl for starting/stopping the profiling */ #define WE_START_FW_PROFILE 87 #define WE_SET_CHANNEL 88 +#define WE_SET_CONC_SYSTEM_PREF 89 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_INT (SIOCIWFIRSTPRIV + 1) @@ -273,6 +275,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_GET_GTX_MINTPC 53 #define WE_GET_GTX_BWMASK 54 #define WE_GET_TEMPERATURE 56 +#define WE_CAP_TSF 58 /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_INT_GET_INT (SIOCIWFIRSTPRIV + 2) @@ -364,6 +367,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { #define WE_SET_DUAL_MAC_SCAN_CONFIG 21 #define WE_SET_DUAL_MAC_FW_MODE_CONFIG 22 +#define WE_SET_MON_MODE_CHAN 23 #ifdef FEATURE_WLAN_TDLS #undef MAX_VAR_ARGS @@ -383,7 +387,8 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { /* (SIOCIWFIRSTPRIV + 10) is currently unused */ /* (SIOCIWFIRSTPRIV + 12) is currently unused */ /* (SIOCIWFIRSTPRIV + 14) is currently unused */ -/* (SIOCIWFIRSTPRIV + 15) is currently unused */ +#define WLAN_PRIV_SET_NONE_GET_THREE_INT (SIOCIWFIRSTPRIV + 15) +#define WE_GET_TSF 1 /* (SIOCIWFIRSTPRIV + 16) is currently unused */ /* (SIOCIWFIRSTPRIV + 17) is currently unused */ /* (SIOCIWFIRSTPRIV + 19) is currently unused */ @@ -6271,7 +6276,19 @@ static int __iw_setint_getnone(struct net_device *dev, } break; } + case WE_SET_CONC_SYSTEM_PREF: + { + hdd_info("New preference: %d", set_value); + if (!((set_value >= CFG_CONC_SYSTEM_PREF_MIN) && + (set_value <= CFG_CONC_SYSTEM_PREF_MAX))) { + hdd_err("Invalid system preference %d", set_value); + return -EINVAL; + } + /* hdd_ctx, hdd_ctx->config are already checked for null */ + hdd_ctx->config->conc_system_pref = set_value; + break; + } default: { hddLog(LOGE, "%s: Invalid sub command %d", __func__, @@ -6299,6 +6316,65 @@ static int iw_setint_getnone(struct net_device *dev, } /** + * __iw_setnone_get_threeint() - return three value to up layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/Output + * + * Return: execute result + */ +static int __iw_setnone_get_threeint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret = 0; /* success */ + uint32_t *value = (int *)extra; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + + ENTER_DEV(dev); + ret = wlan_hdd_validate_context(hdd_ctx); + if (0 != ret) + return ret; + + hdd_info(FL("param = %d"), value[0]); + switch (value[0]) { + case WE_GET_TSF: + ret = hdd_indicate_tsf(adapter, value, 3); + break; + default: + hdd_err("Invalid IOCTL get_value command %d", value[0]); + break; + } + return ret; +} + +/** + * iw_setnone_get_threeint() - return three value to up layer. + * + * @dev: pointer of net_device of this wireless card + * @info: meta data about Request sent + * @wrqu: include request info + * @extra: buf used for in/Output + * + * Return: execute result + */ +static int iw_setnone_get_threeint(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + int ret; + + cds_ssr_protect(__func__); + ret = __iw_setnone_get_threeint(dev, info, wrqu, extra); + cds_ssr_unprotect(__func__); + + return ret; +} + +/** * iw_setchar_getnone() - Generic "set string" private ioctl handler * @dev: device upon which the ioctl was received * @info: ioctl request information @@ -6914,7 +6990,9 @@ static int __iw_setnone_getint(struct net_device *dev, QPOWER_CMD); break; } - + case WE_CAP_TSF: + ret = hdd_capture_tsf(pAdapter, (uint32_t *)value, 1); + break; case WE_GET_TEMPERATURE: { hddLog(QDF_TRACE_LEVEL_INFO, "WE_GET_TEMPERATURE"); @@ -7977,7 +8055,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, if (apps_args[0] == 0) { hddLog(LOGE, FL("set hw mode for single mac\n")); - cds_soc_set_hw_mode( + cds_pdev_set_hw_mode( pAdapter->sessionId, HW_MODE_SS_2x2, HW_MODE_80_MHZ, @@ -7988,7 +8066,7 @@ static int __iw_set_var_ints_getnone(struct net_device *dev, } else if (apps_args[0] == 1) { hddLog(LOGE, FL("set hw mode for dual mac\n")); - cds_soc_set_hw_mode( + cds_pdev_set_hw_mode( pAdapter->sessionId, HW_MODE_SS_1x1, HW_MODE_80_MHZ, @@ -9651,6 +9729,53 @@ static int iw_set_band_config(struct net_device *dev, return ret; } +/** + * wlan_hdd_set_mon_chan() - Set capture channel on the monitor mode interface. + * @adapter: Handle to adapter + * @chan: Monitor mode channel + * @bandwidth: Capture channel bandwidth + * + * Return: 0 on success else error code. + */ +static int wlan_hdd_set_mon_chan(hdd_adapter_t *adapter, uint32_t chan, + uint32_t bandwidth) +{ + hdd_context_t *hdd_ctx = WLAN_HDD_GET_CTX(adapter); + hdd_station_ctx_t *sta_ctx = WLAN_HDD_GET_STATION_CTX_PTR(adapter); + struct hdd_mon_set_ch_info *ch_info = &sta_ctx->ch_info; + QDF_STATUS status; + tHalHandle hal_hdl = hdd_ctx->hHal; + struct qdf_mac_addr bssid; + tCsrRoamProfile roam_profile; + struct ch_params_s ch_params; + + if (QDF_GLOBAL_MONITOR_MODE != hdd_get_conparam()) { + hdd_err("Not supported, device is not in monitor mode"); + return -EINVAL; + } + + hdd_info("Set monitor mode Channel %d", chan); + hdd_select_cbmode(adapter, chan); + roam_profile.ChannelInfo.ChannelList = &ch_info->channel; + roam_profile.ChannelInfo.numOfChannels = 1; + roam_profile.phyMode = ch_info->phy_mode; + roam_profile.ch_params.ch_width = bandwidth; + + qdf_mem_copy(bssid.bytes, adapter->macAddressCurrent.bytes, + QDF_MAC_ADDR_SIZE); + + ch_params.ch_width = bandwidth; + sme_set_ch_params(hal_hdl, ch_info->phy_mode, chan, 0, &ch_params); + status = sme_roam_channel_change_req(hal_hdl, bssid, &ch_params, + &roam_profile); + if (status) { + hdd_err("Status: %d Failed to set sme_roam Channel for monitor mode", + status); + } + + return qdf_status_to_os_return(status); +} + static int __iw_set_two_ints_getnone(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) @@ -9716,6 +9841,9 @@ static int __iw_set_two_ints_getnone(struct net_device *dev, if (value[1] == DUMP_DP_TRACE) qdf_dp_trace_dump_all(value[2]); break; + case WE_SET_MON_MODE_CHAN: + ret = wlan_hdd_set_mon_chan(pAdapter, value[1], value[2]); + break; default: hddLog(LOGE, "%s: Invalid IOCTL command %d", __func__, sub_cmd); break; @@ -9809,6 +9937,8 @@ static const iw_handler we_private[] = { [WLAN_PRIV_SET_NONE_GET_NONE - SIOCIWFIRSTPRIV] = iw_setnone_getnone, /* action priv ioctl */ [WLAN_PRIV_SET_VAR_INT_GET_NONE - SIOCIWFIRSTPRIV] = iw_hdd_set_var_ints_getnone, + [WLAN_PRIV_SET_NONE_GET_THREE_INT - SIOCIWFIRSTPRIV] = + iw_setnone_get_threeint, [WLAN_PRIV_ADD_TSPEC - SIOCIWFIRSTPRIV] = iw_add_tspec, [WLAN_PRIV_DEL_TSPEC - SIOCIWFIRSTPRIV] = iw_del_tspec, [WLAN_PRIV_GET_TSPEC - SIOCIWFIRSTPRIV] = iw_get_tspec, @@ -10256,6 +10386,10 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setChanChange" }, + {WE_SET_CONC_SYSTEM_PREF, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + 0, "setConcSysPref" }, + {WLAN_PRIV_SET_NONE_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -10506,6 +10640,11 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_qnodatapoll"}, + {WE_CAP_TSF, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "cap_tsf"}, + {WE_GET_TEMPERATURE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, @@ -10565,6 +10704,15 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "setsapchannels"}, + /* handlers for main ioctl */ + {WLAN_PRIV_SET_NONE_GET_THREE_INT, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + "" }, + {WE_GET_TSF, + 0, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, + "get_tsf" }, {WE_SET_DUAL_MAC_SCAN_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, @@ -10917,6 +11065,10 @@ static const struct iw_priv_args we_private_args[] = { IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "dump_dp_trace"} , + {WE_SET_MON_MODE_CHAN, + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, + 0, "setMonChan"} + , }; const struct iw_handler_def we_handler_def = { diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index 28e96fb7b299..5fbfb179fc9d 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -1882,12 +1882,7 @@ QDF_STATUS hdd_wmm_acquire_access(hdd_adapter_t *pAdapter, pQosContext->magic = HDD_WMM_CTX_MAGIC; pQosContext->is_inactivity_timer_running = false; -#ifdef CONFIG_CNSS - cnss_init_work(&pQosContext->wmmAcSetupImplicitQos, - hdd_wmm_do_implicit_qos); -#else INIT_WORK(&pQosContext->wmmAcSetupImplicitQos, hdd_wmm_do_implicit_qos); -#endif QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_DEBUG, "%s: Scheduling work for AC %d, context %p", diff --git a/core/mac/inc/ani_global.h b/core/mac/inc/ani_global.h index 8f68465306b0..05430a9bb978 100644 --- a/core/mac/inc/ani_global.h +++ b/core/mac/inc/ani_global.h @@ -131,6 +131,7 @@ enum log_event_type { * @WLAN_LOG_INDICATOR_FRAMEWORK: Framework triggers bug report * @WLAN_LOG_INDICATOR_HOST_DRIVER: Host driver triggers bug report * @WLAN_LOG_INDICATOR_FIRMWARE: FW initiates bug report + * @WLAN_LOG_INDICATOR_HOST_ONLY: Host triggers fatal event bug report * * Enum indicating the module that triggered the bug report */ @@ -139,52 +140,39 @@ enum log_event_indicator { WLAN_LOG_INDICATOR_FRAMEWORK, WLAN_LOG_INDICATOR_HOST_DRIVER, WLAN_LOG_INDICATOR_FIRMWARE, + WLAN_LOG_INDICATOR_HOST_ONLY, }; /** * enum log_event_host_reason_code - Reason code for bug report * @WLAN_LOG_REASON_CODE_UNUSED: Unused - * @WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL: Command response status from FW - * is error * @WLAN_LOG_REASON_ROAM_FAIL: Driver initiated roam has failed - * @WLAN_LOG_REASON_THREAD_STUCK: Monitor Health of host threads and report - * fatal event if some thread is stuck * @WLAN_LOG_REASON_DATA_STALL: Unable to send/receive data due to low resource * scenario for a prolonged period * @WLAN_LOG_REASON_SME_COMMAND_STUCK: SME command is stuck in SME active queue - * @WLAN_LOG_REASON_ZERO_SCAN_RESULTS: Full scan resulted in zero scan results * @WLAN_LOG_REASON_QUEUE_FULL: Defer queue becomes full for a prolonged period * @WLAN_LOG_REASON_POWER_COLLAPSE_FAIL: Unable to allow apps power collapse * for a prolonged period - * @WLAN_LOG_REASON_SSR_FAIL: Unable to gracefully complete SSR - * @WLAN_LOG_REASON_DISCONNECT_FAIL: Disconnect from Supplicant is not - * successful - * @WLAN_LOG_REASON_CLEAN_UP_FAIL: Clean up of TDLS or Pre-Auth Sessions - * not successful * @WLAN_LOG_REASON_MALLOC_FAIL: Memory allocation Fails * @WLAN_LOG_REASON_VOS_MSG_UNDER_RUN: VOS Core runs out of message wrapper - * @WLAN_LOG_REASON_MSG_POST_FAIL: Unable to post msg - * + * @WLAN_LOG_REASON_HDD_TIME_OUT: Wait for event Timeout in HDD layer + @WLAN_LOG_REASON_SME_OUT_OF_CMD_BUFL sme out of cmd buffer * This enum contains the different reason codes for bug report */ enum log_event_host_reason_code { WLAN_LOG_REASON_CODE_UNUSED, - WLAN_LOG_REASON_COMMAND_UNSUCCESSFUL, WLAN_LOG_REASON_ROAM_FAIL, - WLAN_LOG_REASON_THREAD_STUCK, WLAN_LOG_REASON_DATA_STALL, WLAN_LOG_REASON_SME_COMMAND_STUCK, - WLAN_LOG_REASON_ZERO_SCAN_RESULTS, WLAN_LOG_REASON_QUEUE_FULL, WLAN_LOG_REASON_POWER_COLLAPSE_FAIL, - WLAN_LOG_REASON_SSR_FAIL, - WLAN_LOG_REASON_DISCONNECT_FAIL, - WLAN_LOG_REASON_CLEAN_UP_FAIL, WLAN_LOG_REASON_MALLOC_FAIL, WLAN_LOG_REASON_VOS_MSG_UNDER_RUN, - WLAN_LOG_REASON_MSG_POST_FAIL, + WLAN_LOG_REASON_HDD_TIME_OUT, + WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF, }; + /** * enum userspace_log_level - Log level at userspace * @LOG_LEVEL_NO_COLLECTION: verbose_level 0 corresponds to no collection diff --git a/core/mac/inc/qwlan_version.h b/core/mac/inc/qwlan_version.h index 738e05d5cb54..b225c7fecf54 100644 --- a/core/mac/inc/qwlan_version.h +++ b/core/mac/inc/qwlan_version.h @@ -41,9 +41,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 1 #define QWLAN_VERSION_PATCH 0 -#define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 5 +#define QWLAN_VERSION_EXTRA "A" +#define QWLAN_VERSION_BUILD 7 -#define QWLAN_VERSIONSTR "5.1.0.5" +#define QWLAN_VERSIONSTR "5.1.0.7A" #endif /* QWLAN_VERSION_H */ diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 5c5ff30e87f9..7cb2188783c3 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -494,6 +494,7 @@ typedef enum eSirBssType { eSIR_INFRA_AP_MODE, /* Added for softAP support */ eSIR_IBSS_MODE, eSIR_AUTO_MODE, + eSIR_MONITOR_MODE, eSIR_DONOT_USE_BSS_TYPE = SIR_MAX_ENUM_SIZE } tSirBssType; @@ -682,7 +683,6 @@ typedef struct sSirSmeHTProfile { uint8_t htRecommendedTxWidthSet; ePhyChanBondState htSecondaryChannelOffset; uint8_t vhtCapability; - uint8_t vhtTxChannelWidthSet; uint8_t apCenterChan; uint8_t apChanWidth; } tSirSmeHTProfile; @@ -778,6 +778,10 @@ typedef struct sSirSmeScanReq { */ /* in units of milliseconds, ignored when not connected */ uint32_t restTime; + /*in units of milliseconds, ignored when not connected*/ + uint32_t min_rest_time; + /*in units of milliseconds, ignored when not connected*/ + uint32_t idle_time; uint8_t returnAfterFirstMatch; /** @@ -2430,6 +2434,18 @@ typedef struct sSirUpdateParams { uint8_t ssidHidden; /* Hide SSID */ } tSirUpdateParams, *tpSirUpdateParams; +/** + * struct sir_create_session - Used for creating session in monitor mode + * @type: SME host message type. + * @msg_len: Length of the message. + * @bss_id: bss_id for creating the session. + */ +struct sir_create_session { + uint16_t type; + uint16_t msg_len; + struct qdf_mac_addr bss_id; +}; + /* Beacon Interval */ typedef struct sSirChangeBIParams { uint16_t messageType; @@ -3571,6 +3587,10 @@ typedef struct sSirScanOffloadReq { uint32_t scan_requestor_id; /* in units of milliseconds, ignored when not connected */ uint32_t restTime; + /*in units of milliseconds, ignored when not connected*/ + uint32_t min_rest_time; + /*in units of milliseconds, ignored when not connected*/ + uint32_t idle_time; tSirP2pScanType p2pScanType; uint16_t uIEFieldLen; uint16_t uIEFieldOffset; @@ -5564,6 +5584,21 @@ struct sir_sme_ext_cng_chan_ind { }; /** + * struct stsf - the basic stsf structure + * + * @vdev_id: vdev id + * @tsf_low: low 32bits of tsf + * @tsf_high: high 32bits of tsf + * + * driver use this struct to store the tsf info + */ +struct stsf { + uint32_t vdev_id; + uint32_t tsf_low; + uint32_t tsf_high; +}; + +/** * struct egap_params - the enhanced green ap params * @vdev_id: vdev id * @enable: enable or disable the enhance green ap in firmware @@ -5615,18 +5650,6 @@ struct csa_offload_params { }; /** - * struct sir_saved_csa_params - saved csa offload params - * @message_type: Message type - * @length: Message length - * @session_id: Session id - */ -struct sir_saved_csa_params { - uint16_t message_type; - uint16_t length; - uint32_t session_id; -}; - -/** * enum obss_ht40_scancmd_type - obss scan command type * @HT40_OBSS_SCAN_PARAM_START: OBSS scan start * @HT40_OBSS_SCAN_PARAM_UPDATE: OBSS scan param update @@ -5711,4 +5734,40 @@ struct obss_scanparam { uint16_t obss_activity_threshold; }; +/** + * struct sir_bpf_set_offload - set bpf filter instructions + * @session_id: session identifier + * @version: host bpf version + * @filter_id: Filter ID for BPF filter + * @total_length: The total length of the full instruction + * total_length equal to 0 means reset + * @current_offset: current offset, 0 means start a new setting + * @current_length: Length of current @program + * @program: BPF instructions + */ +struct sir_bpf_set_offload { + uint8_t session_id; + uint32_t version; + uint32_t filter_id; + uint32_t total_length; + uint32_t current_offset; + uint32_t current_length; + uint8_t *program; +}; + +/** + * struct sir_bpf_offload_capabilities - get bpf Capabilities + * @bpf_version: fw's implement version + * @max_bpf_filters: max filters that fw supports + * @max_bytes_for_bpf_inst: the max bytes that can be used as bpf instructions + * @remaining_bytes_for_bpf_inst: remaining bytes for bpf instructions + * + */ +struct sir_bpf_get_offload { + uint32_t bpf_version; + uint32_t max_bpf_filters; + uint32_t max_bytes_for_bpf_inst; + uint32_t remaining_bytes_for_bpf_inst; +}; + #endif /* __SIR_API_H */ diff --git a/core/mac/inc/sir_mac_prot_def.h b/core/mac/inc/sir_mac_prot_def.h index 2585a4fa3445..596f55889671 100644 --- a/core/mac/inc/sir_mac_prot_def.h +++ b/core/mac/inc/sir_mac_prot_def.h @@ -145,6 +145,9 @@ #define SIR_MAC_ACTION_FST 18 #define SIR_MAC_ACTION_VHT 21 +#define SIR_MAC_ACTION_TX 1 +#define SIR_MAC_ACTION_RX 2 + /* QoS management action codes */ #define SIR_MAC_QOS_ADD_TS_REQ 0 diff --git a/core/mac/inc/wni_api.h b/core/mac/inc/wni_api.h index 23ab4d2dffe1..e6dfb2dda66a 100644 --- a/core/mac/inc/wni_api.h +++ b/core/mac/inc/wni_api.h @@ -248,6 +248,8 @@ enum eWniMsgTypes { eWNI_SME_HT40_OBSS_SCAN_IND, /* START and UPDATE OBSS SCAN Indication*/ eWNI_SME_SET_ANTENNA_MODE_REQ, eWNI_SME_SET_ANTENNA_MODE_RESP, + eWNI_SME_TSF_EVENT, + eWNI_SME_MON_INIT_SESSION, eWNI_SME_MSG_TYPES_END }; diff --git a/core/mac/src/dph/dph_hash_table.c b/core/mac/src/dph/dph_hash_table.c index 0e592d18a774..af64bd5899a8 100644 --- a/core/mac/src/dph/dph_hash_table.c +++ b/core/mac/src/dph/dph_hash_table.c @@ -450,7 +450,8 @@ tSirRetStatus dph_delete_hash_entry(tpAniSirGlobal pMac, tSirMacAddr staAddr, void dph_print_mac_addr(tpAniSirGlobal pMac, uint8_t addr[], uint32_t level) { - lim_log(pMac, (uint16_t) level, FL("MAC ADDR = %d:%d:%d:%d:%d:%d"), + lim_log(pMac, (uint16_t) level, + FL("MAC ADDR = %02x:%02x:%02x:%02x:%02x:%02x"), addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); } diff --git a/core/mac/src/include/parser_api.h b/core/mac/src/include/parser_api.h index f48aac5c416f..4a99241f7304 100644 --- a/core/mac/src/include/parser_api.h +++ b/core/mac/src/include/parser_api.h @@ -148,6 +148,7 @@ typedef struct sSirProbeRespBeacon { tDot11fIEVHTCaps VHTCaps; tDot11fIEVHTOperation VHTOperation; tDot11fIEVHTExtBssLoad VHTExtBssLoad; + tDot11fIEExtCap ext_cap; tDot11fIEOperatingMode OperatingMode; uint8_t WiderBWChanSwitchAnnPresent; tDot11fIEWiderBWChanSwitchAnn WiderBWChanSwitchAnn; diff --git a/core/mac/src/include/sir_debug.h b/core/mac/src/include/sir_debug.h index 674855d0567b..c038523cf784 100644 --- a/core/mac/src/include/sir_debug.h +++ b/core/mac/src/include/sir_debug.h @@ -100,9 +100,6 @@ #endif /* WLAN_MDM_CODE_REDUCTION_OPT */ -#define FL(x) "%s: %d: " \ - x, __func__, __LINE__ - #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 6287638b2b8f..9959dda2df43 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -411,8 +411,8 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_DEL_PERIODIC_TX_PTRN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 153) /* Messages between 156 to 157 are not used */ -#define SIR_HAL_SOC_DUAL_MAC_CFG_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 154) -#define SIR_HAL_SOC_DUAL_MAC_CFG_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 155) +#define SIR_HAL_PDEV_DUAL_MAC_CFG_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 154) +#define SIR_HAL_PDEV_MAC_CFG_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 155) /* For IBSS peer info related messages */ #define SIR_HAL_IBSS_PEER_INFO_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 158) @@ -587,9 +587,9 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_FW_MEM_DUMP_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 327) #define SIR_HAL_START_STOP_LOGGING (SIR_HAL_ITC_MSG_TYPES_BEGIN + 328) -#define SIR_HAL_SOC_SET_HW_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 329) -#define SIR_HAL_SOC_SET_HW_MODE_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 330) -#define SIR_HAL_SOC_HW_MODE_TRANS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 331) +#define SIR_HAL_PDEV_SET_HW_MODE (SIR_HAL_ITC_MSG_TYPES_BEGIN + 329) +#define SIR_HAL_PDEV_SET_HW_MODE_RESP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 330) +#define SIR_HAL_PDEV_HW_MODE_TRANS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 331) #define SIR_HAL_SET_RSSI_MONITOR_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 333) #define SIR_HAL_SET_IE_INFO (SIR_HAL_ITC_MSG_TYPES_BEGIN + 334) @@ -599,9 +599,14 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_SET_EGAP_CONF_PARAMS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 336) #define SIR_HAL_HT40_OBSS_SCAN_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 337) +#define SIR_HAL_TSF_GPIO_PIN_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 338) + #define SIR_HAL_ADD_BCN_FILTER_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 339) #define SIR_HAL_REMOVE_BCN_FILTER_CMDID (SIR_HAL_ITC_MSG_TYPES_BEGIN + 340) +#define SIR_HAL_BPF_GET_CAPABILITIES_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 341) +#define SIR_HAL_BPF_SET_INSTRUCTIONS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 342) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ @@ -635,7 +640,7 @@ typedef struct sSirMbMsgP2p { #define SIR_LIM_SCH_CLEAN_MSG (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xB) /* Message from ISR upon Radar Detection */ #define SIR_LIM_RADAR_DETECT_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xC) -#define SIR_LIM_CSA_POST_HW_MODE_CHANGE (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xD) +/* Message id 0xD available */ /* Message from Hal to send out a DEL-TS indication */ #define SIR_LIM_DEL_TS_IND (SIR_LIM_ITC_MSG_TYPES_BEGIN + 0xE) diff --git a/core/mac/src/pe/include/lim_api.h b/core/mac/src/pe/include/lim_api.h index e66de6befda7..dabb6b4d76e5 100644 --- a/core/mac/src/pe/include/lim_api.h +++ b/core/mac/src/pe/include/lim_api.h @@ -172,6 +172,17 @@ static inline QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, return QDF_STATUS_E_NOSUPPORT; } #endif + +/** + * lim_mon_init_session() - create PE session for monitor mode operation + * @mac_ptr: mac pointer + * @msg: Pointer to struct sir_create_session type. + * + * Return: NONE + */ +void lim_mon_init_session(tpAniSirGlobal mac_ptr, + struct sir_create_session *msg); + #define limGetQosMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limQosEnabled) #define limGetWmeMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWmeEnabled) #define limGetWsmMode(psessionEntry, pVal) (*(pVal) = (psessionEntry)->limWsmEnabled) diff --git a/core/mac/src/pe/include/lim_session.h b/core/mac/src/pe/include/lim_session.h index 8ff3010ee5a7..779070b6ed12 100644 --- a/core/mac/src/pe/include/lim_session.h +++ b/core/mac/src/pe/include/lim_session.h @@ -309,7 +309,6 @@ typedef struct sPESession /* Added to Support BT-AMP */ tBeaconParams beaconParams; uint8_t vhtCapability; - uint8_t vhtTxChannelWidthSet; tLimOperatingModeInfo gLimOperatingMode; uint8_t vhtCapabilityPresentInBeacon; uint8_t ch_center_freq_seg0; @@ -472,11 +471,11 @@ typedef struct sPESession /* Added to Support BT-AMP */ uint8_t country_info_present; uint8_t nss; bool add_bss_failed; - struct csa_offload_params saved_csa_params; /* To hold OBSS Scan IE Parameters */ struct obss_scanparam obss_ht40_scanparam; /* Supported NSS is intersection of self and peer NSS */ bool supported_nss_1x1; + bool is_ext_caps_present; } tPESession, *tpPESession; /*------------------------------------------------------------------------- diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index 5912165c93aa..3c440df4627b 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -1699,8 +1699,6 @@ void lim_fill_join_rsp_ht_caps(tpPESession session, tpSirSmeJoinRsp join_rsp) ht_profile->dot11mode = session->dot11mode; ht_profile->htCapability = session->htCapability; ht_profile->vhtCapability = session->vhtCapability; - ht_profile->vhtTxChannelWidthSet = - session->vhtTxChannelWidthSet; ht_profile->apCenterChan = session->ch_center_freq_seg0; ht_profile->apChanWidth = session->ch_width; } @@ -1880,6 +1878,7 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, tpAddBssParams add_bss_params; uint8_t local_nss; QDF_STATUS status = QDF_STATUS_E_FAILURE; + uint16_t join_rsp_len; if (!roam_sync_ind_ptr) { lim_log(mac_ctx, LOGE, FL("LFR3:roam_sync_ind_ptr is NULL")); @@ -1989,6 +1988,31 @@ QDF_STATUS pe_roam_synch_callback(tpAniSirGlobal mac_ctx, curr_sta_ds->nss = local_nss; ft_session_ptr->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; lim_init_tdls_data(mac_ctx, ft_session_ptr); + join_rsp_len = ft_session_ptr->RICDataLen + sizeof(tSirSmeJoinRsp) - + sizeof(uint8_t); + roam_sync_ind_ptr->join_rsp = qdf_mem_malloc(join_rsp_len); + if (NULL == roam_sync_ind_ptr->join_rsp) { + lim_log(mac_ctx, LOGE, FL("LFR3:mem alloc failed")); + ft_session_ptr->bRoamSynchInProgress = false; + if (mac_ctx->roam.pReassocResp) + qdf_mem_free(mac_ctx->roam.pReassocResp); + mac_ctx->roam.pReassocResp = NULL; + return QDF_STATUS_E_NOMEM; + } + qdf_mem_zero(roam_sync_ind_ptr->join_rsp, join_rsp_len); + + lim_log(mac_ctx, LOG1, FL("Session RicLength = %d"), + ft_session_ptr->RICDataLen); + if (ft_session_ptr->ricData != NULL) { + roam_sync_ind_ptr->join_rsp->parsedRicRspLen = + ft_session_ptr->RICDataLen; + qdf_mem_copy(roam_sync_ind_ptr->join_rsp->frames, + ft_session_ptr->ricData, + roam_sync_ind_ptr->join_rsp->parsedRicRspLen); + qdf_mem_free(ft_session_ptr->ricData); + ft_session_ptr->ricData = NULL; + ft_session_ptr->RICDataLen = 0; + } roam_sync_ind_ptr->join_rsp->vht_channel_width = ft_session_ptr->ch_width; roam_sync_ind_ptr->join_rsp->staId = curr_sta_ds->staIndex; @@ -2145,3 +2169,29 @@ QDF_STATUS pe_release_global_lock(tAniSirLim *psPe) return status; } +/** + * lim_mon_init_session() - create PE session for monitor mode operation + * @mac_ptr: mac pointer + * @msg: Pointer to struct sir_create_session type. + * + * Return: NONE + */ +void lim_mon_init_session(tpAniSirGlobal mac_ptr, + struct sir_create_session *msg) +{ + tpPESession psession_entry; + uint8_t session_id; + + lim_print_mac_addr(mac_ptr, msg->bss_id.bytes, LOGE); + psession_entry = pe_create_session(mac_ptr, msg->bss_id.bytes, + &session_id, + mac_ptr->lim.maxStation, + eSIR_MONITOR_MODE); + if (psession_entry == NULL) { + QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, + ("Monitor mode: Session Can not be created")); + lim_print_mac_addr(mac_ptr, msg->bss_id.bytes, LOGE); + return; + } + psession_entry->vhtCapability = 1; +} diff --git a/core/mac/src/pe/lim/lim_process_message_queue.c b/core/mac/src/pe/lim/lim_process_message_queue.c index 27d6a4159760..bebe8120dafc 100644 --- a/core/mac/src/pe/lim/lim_process_message_queue.c +++ b/core/mac/src/pe/lim/lim_process_message_queue.c @@ -1241,160 +1241,6 @@ static void lim_process_sme_obss_scan_ind(tpAniSirGlobal mac_ctx, } /** - * lim_handle_hw_mode_change_on_csa() - Do HW mode change on CSA for STA mode - * @mac_ctx: Global MAC context - * @msg: Received message - * - * Checks if hw mode change is required for the new channel. - * If MCC upgrade is required, this function will start the opportunistic - * timer and the caller will invoke the other APIs to perform vdev restart on - * the new channel. - * - * If DBS downgrade is required, this function will initiate the hw mode - * change and vdev restart will happen on the new channel after getting hw - * mode response - * - * Return: QDF_STATUS_SUCCESS if processing of csa params (and hence vdev - * restart) needs to happen or if no hw mode change is required, - * QDF_STATUS_E_FAILURE otherwise. - */ -static QDF_STATUS lim_handle_hw_mode_change_on_csa(tpAniSirGlobal mac_ctx, - tpSirMsgQ msg) -{ - tpPESession session_entry; - struct csa_offload_params *csa_params = - (struct csa_offload_params *) (msg->bodyptr); - tpDphHashNode sta_ds = NULL; - uint8_t session_id; - uint16_t aid = 0; - QDF_STATUS status = QDF_STATUS_E_FAILURE; - - lim_log(mac_ctx, LOG1, FL("handle hw mode change for csa")); - - if (!csa_params) { - lim_log(mac_ctx, LOGE, FL("limMsgQ body ptr is NULL")); - /* qdf_mem_free() can handle NULL values */ - goto err; - } - - session_entry = pe_find_session_by_bssid(mac_ctx, - csa_params->bssId, &session_id); - if (!session_entry) { - lim_log(mac_ctx, LOGE, FL("Session does not exist")); - goto err; - } - - sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid, - &session_entry->dph.dphHashTable); - - if (!sta_ds) { - lim_log(mac_ctx, LOGE, FL("sta_ds does not exist")); - goto err; - } - - status = cds_handle_hw_mode_change_on_csa(session_entry->smeSessionId, - csa_params->channel, csa_params->bssId, - &session_entry->saved_csa_params, csa_params, - sizeof(session_entry->saved_csa_params)); - - if (QDF_IS_STATUS_SUCCESS(status)) - return status; - -err: - qdf_mem_free(csa_params); - return status; -} - -/** - * lim_handle_hw_mode_change_on_csa_event() - Handle hw mode change on csa - * @mac_ctx: Pointer to the Global Mac Context - * @msg: Received message - * - * Checks if a hw mode change is required for the received csa event. Processes - * csa params and do vdev restart immediately if the there is no need for a hw - * mode change or if MCC upgrade is required - * - * Return: None - */ -static void lim_handle_hw_mode_change_on_csa_event(tpAniSirGlobal mac_ctx, - tpSirMsgQ msg) -{ - QDF_STATUS qdf_status; - - lim_log(mac_ctx, LOG1, FL("lim received csa offload event")); - if (mac_ctx->policy_manager_enabled && - wma_is_hw_dbs_capable() == true) { - /* Check if a hw mode change is required */ - qdf_status = lim_handle_hw_mode_change_on_csa(mac_ctx, - msg); - /* Process csa params and do vdev restart immediately if - * there is no need for a hw mode change or if MCC upgrade is - * required. - */ - if (QDF_IS_STATUS_SUCCESS(qdf_status)) - lim_handle_csa_offload_msg(mac_ctx, msg); - } else { - lim_handle_csa_offload_msg(mac_ctx, msg); - } -} - -/** - * lim_handle_csa_event_post_dbs_downgrade() - Process csa event post dbs - * downgrade - * @mac_ctx: Pointer to the Global Mac Context - * @msg: Received message - * - * Process the csa event to do vdev restart on the new channel after the dbs - * downgrade. If there was a DBS downgrade as part of the event - * WMA_CSA_OFFLOAD_EVENT, SIR_LIM_CSA_POST_HW_MODE_CHANGE will be received after - * receiving the set hw mode response, where this processing will happen. - * - * Return: None - */ -static void lim_handle_csa_event_post_dbs_downgrade(tpAniSirGlobal mac_ctx, - tpSirMsgQ msg) -{ - tSirMsgQ csa_msg; - tpPESession session_entry; - - struct sir_saved_csa_params *buf = - (struct sir_saved_csa_params *)msg->bodyptr; - - /* Null check for 'msg' already done before coming here in the caller */ - - session_entry = pe_find_session_by_sme_session_id(mac_ctx, - buf->session_id); - if (!session_entry) { - lim_log(mac_ctx, LOGE, FL("Invalid session id:%d"), - buf->session_id); - return; - } - - lim_log(mac_ctx, LOG1, - FL("received csa offload event post hw change for %pM"), - session_entry->saved_csa_params.bssId); - - csa_msg.bodyptr = qdf_mem_malloc( - sizeof(struct csa_offload_params)); - if (!csa_msg.bodyptr) { - lim_log(mac_ctx, LOGE, FL("malloc failed for csa msg")); - goto clean_msg_body; - } - - qdf_mem_copy((void *)csa_msg.bodyptr, - (void *)&session_entry->saved_csa_params, - sizeof(struct csa_offload_params)); - /* If there was a DBS downgrade as part of the event - * WMA_CSA_OFFLOAD_EVENT, SIR_LIM_CSA_POST_HW_MODE_CHANGE will - * be received after receiving the set hw mode response. - */ - lim_handle_csa_offload_msg(mac_ctx, &csa_msg); -clean_msg_body: - if (msg->bodyptr) - qdf_mem_free(msg->bodyptr); -} - -/** * lim_process_messages() - Process messages from upper layers. * * @mac_ctx: Pointer to the Global Mac Context. @@ -1626,6 +1472,11 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) qdf_mem_free(msg->bodyptr); msg->bodyptr = NULL; break; + case eWNI_SME_MON_INIT_SESSION: + lim_mon_init_session(mac_ctx, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + msg->bodyptr = NULL; + break; case SIR_HAL_P2P_NOA_START_IND: session_entry = &mac_ctx->lim.gpSession[0]; lim_log(mac_ctx, LOG1, "LIM received NOA start %x", msg->type); @@ -1853,10 +1704,7 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) lim_handle_delete_bss_rsp(mac_ctx, msg); break; case WMA_CSA_OFFLOAD_EVENT: - lim_handle_hw_mode_change_on_csa_event(mac_ctx, msg); - break; - case SIR_LIM_CSA_POST_HW_MODE_CHANGE: - lim_handle_csa_event_post_dbs_downgrade(mac_ctx, msg); + lim_handle_csa_offload_msg(mac_ctx, msg); break; case WMA_SET_BSSKEY_RSP: case WMA_SET_STA_BCASTKEY_RSP: @@ -2046,17 +1894,17 @@ void lim_process_messages(tpAniSirGlobal mac_ctx, tpSirMsgQ msg) msg->bodyptr = NULL; break; #endif - case SIR_HAL_SOC_SET_HW_MODE_RESP: + case SIR_HAL_PDEV_SET_HW_MODE_RESP: lim_process_set_hw_mode_resp(mac_ctx, msg->bodyptr); qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; break; - case SIR_HAL_SOC_HW_MODE_TRANS_IND: + case SIR_HAL_PDEV_HW_MODE_TRANS_IND: lim_process_hw_mode_trans_ind(mac_ctx, msg->bodyptr); qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; break; - case SIR_HAL_SOC_DUAL_MAC_CFG_RESP: + case SIR_HAL_PDEV_MAC_CFG_RESP: lim_process_dual_mac_cfg_resp(mac_ctx, msg->bodyptr); qdf_mem_free((void *)msg->bodyptr); msg->bodyptr = NULL; diff --git a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c index d57a1ca3735e..897f3621a52e 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_req_messages.c @@ -315,7 +315,6 @@ void lim_set_dfs_channel_list(tpAniSirGlobal mac_ctx, uint8_t chan_num, dfs_ch_list->timeStamp[chan_num] = qdf_mc_timer_get_system_time(); } else { - lim_log(mac_ctx, LOG1, FL("Channel %d is Active"), chan_num); return; } @@ -2309,7 +2308,6 @@ static void lim_process_periodic_probe_req_timer(tpAniSirGlobal mac_ctx) } mlm_scan_req = mac_ctx->lim.gpLimMlmScanReq; - lim_log(mac_ctx, LOG1, FL("Scanning : Periodic scanning")); mac_ctx->lim.probeCounter++; /* Periodic channel timer timed out to send probe request. */ channel_num = lim_get_current_scan_channel(mac_ctx); diff --git a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c index 4659053ecb90..c25da0223394 100644 --- a/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_process_mlm_rsp_messages.c @@ -3207,6 +3207,7 @@ void lim_process_switch_channel_rsp(tpAniSirGlobal pMac, void *body) * the policy manager connection table needs to be updated. */ cds_update_connection_info(psessionEntry->smeSessionId); + cds_set_do_hw_mode_change_flag(true); } break; default: diff --git a/core/mac/src/pe/lim/lim_process_sme_req_messages.c b/core/mac/src/pe/lim/lim_process_sme_req_messages.c index 8de45fe8734f..7e34ab80affe 100644 --- a/core/mac/src/pe/lim/lim_process_sme_req_messages.c +++ b/core/mac/src/pe/lim/lim_process_sme_req_messages.c @@ -165,7 +165,7 @@ static QDF_STATUS lim_process_set_hw_mode(tpAniSirGlobal mac, uint32_t *msg) /* Other parameters are not needed for WMA */ cds_message.bodyptr = req_msg; - cds_message.type = SIR_HAL_SOC_SET_HW_MODE; + cds_message.type = SIR_HAL_PDEV_SET_HW_MODE; lim_log(mac, LOG1, FL("Posting SIR_HAL_SOC_SET_HW_MOD to WMA")); status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); @@ -238,10 +238,10 @@ static QDF_STATUS lim_process_set_dual_mac_cfg_req(tpAniSirGlobal mac, /* Other parameters are not needed for WMA */ cds_message.bodyptr = req_msg; - cds_message.type = SIR_HAL_SOC_DUAL_MAC_CFG_REQ; + cds_message.type = SIR_HAL_PDEV_DUAL_MAC_CFG_REQ; lim_log(mac, LOG1, - FL("Post SIR_HAL_SOC_DUAL_MAC_CFG_REQ to WMA: %x %x"), + FL("Post SIR_HAL_PDEV_DUAL_MAC_CFG_REQ to WMA: %x %x"), req_msg->scan_config, req_msg->fw_mode_config); status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { @@ -1298,6 +1298,8 @@ static QDF_STATUS lim_send_hal_start_scan_offload_req(tpAniSirGlobal pMac, pScanOffloadReq->minChannelTime = pScanReq->minChannelTime; pScanOffloadReq->maxChannelTime = pScanReq->maxChannelTime; pScanOffloadReq->restTime = pScanReq->restTime; + pScanOffloadReq->min_rest_time = pScanReq->min_rest_time; + pScanOffloadReq->idle_time = pScanReq->idle_time; /* for normal scan, the value for p2pScanType should be 0 always */ diff --git a/core/mac/src/pe/lim/lim_process_tdls.c b/core/mac/src/pe/lim/lim_process_tdls.c index 5950dd373704..9016fbf2c412 100644 --- a/core/mac/src/pe/lim/lim_process_tdls.c +++ b/core/mac/src/pe/lim/lim_process_tdls.c @@ -2757,6 +2757,10 @@ tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx, goto lim_tdls_send_mgmt_error; } + cds_tdls_tx_rx_mgmt_event(SIR_MAC_ACTION_TDLS, + SIR_MAC_ACTION_TX, SIR_MAC_MGMT_ACTION, + send_req->reqType, send_req->peer_mac.bytes); + switch (send_req->reqType) { case SIR_MAC_TDLS_DIS_REQ: lim_log(mac_ctx, LOG1, FL("Transmit Discovery Request Frame")); diff --git a/core/mac/src/pe/lim/lim_prop_exts_utils.c b/core/mac/src/pe/lim/lim_prop_exts_utils.c index 93f820141d72..869706e327f1 100644 --- a/core/mac/src/pe/lim/lim_prop_exts_utils.c +++ b/core/mac/src/pe/lim/lim_prop_exts_utils.c @@ -123,8 +123,6 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, beacon_struct->VHTOperation.present && session->vhtCapability) { session->vhtCapabilityPresentInBeacon = 1; - session->vhtTxChannelWidthSet = - beacon_struct->VHTOperation.chanWidth; if (((beacon_struct->Vendor1IEPresent && beacon_struct->vendor2_ie.present && beacon_struct->Vendor3IEPresent)) && @@ -217,6 +215,9 @@ lim_extract_ap_capability(tpAniSirGlobal mac_ctx, uint8_t *p_ie, if (beacon_struct->countryInfoPresent) session->country_info_present = true; } + /* Check if Extended caps are present in probe resp or not */ + if (beacon_struct->ext_cap.present) + session->is_ext_caps_present = true; qdf_mem_free(beacon_struct); return; } /****** end lim_extract_ap_capability() ******/ diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 757ffe9d827c..ef138b90b7d6 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -1207,6 +1207,15 @@ lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, populate_dot11f_ht_info(mac_ctx, &frm.HTInfo, pe_session); } + lim_log(mac_ctx, LOG1, + FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, short GI20:%d, shortGI40: %d, dsssCck: %d, AMPDU Param: %x"), + frm.HTCaps.supportedChannelWidthSet, + frm.HTCaps.mimoPowerSave, + frm.HTCaps.greenField, frm.HTCaps.shortGI20MHz, + frm.HTCaps.shortGI40MHz, + frm.HTCaps.dsssCckMode40MHz, + frm.HTCaps.maxRxAMPDUFactor); + if (sta->mlmStaContext.vhtCapability && pe_session->vhtCapability) { lim_log(mac_ctx, LOG1, @@ -1614,7 +1623,7 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, qdf_mem_set((uint8_t *) frm, sizeof(tDot11fAssocRequest), 0); - if (add_ie_len) { + if (add_ie_len && pe_session->is_ext_caps_present) { qdf_mem_set((uint8_t *) &extr_ext_cap, sizeof(tDot11fIEExtCap), 0); sir_status = lim_strip_extcap_update_struct(mac_ctx, @@ -1642,7 +1651,8 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, } } } else { - lim_log(mac_ctx, LOG1, FL("No additional IE for Assoc Req")); + lim_log(mac_ctx, LOG1, + FL("No addn IE or peer dosen't support addnIE for Assoc Req")); extr_ext_flag = false; } @@ -1761,6 +1771,15 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, lim_log(mac_ctx, LOG1, FL("Populate HT Caps in Assoc Request")); populate_dot11f_ht_caps(mac_ctx, pe_session, &frm->HTCaps); } + lim_log(mac_ctx, LOG1, + FL("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, short GI20:%d, shortGI40: %d, dsssCck: %d, AMPDU Param: %x"), + frm->HTCaps.supportedChannelWidthSet, + frm->HTCaps.mimoPowerSave, + frm->HTCaps.greenField, frm->HTCaps.shortGI20MHz, + frm->HTCaps.shortGI40MHz, + frm->HTCaps.dsssCckMode40MHz, + frm->HTCaps.maxRxAMPDUFactor); + if (pe_session->vhtCapability && pe_session->vhtCapabilityPresentInBeacon) { lim_log(mac_ctx, LOG1, FL("Populate VHT IEs in Assoc Request")); @@ -1782,7 +1801,9 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, &frm->vendor2_ie.VHTCaps); vht_enabled = true; } - populate_dot11f_ext_cap(mac_ctx, vht_enabled, &frm->ExtCap, pe_session); + if (pe_session->is_ext_caps_present) + populate_dot11f_ext_cap(mac_ctx, vht_enabled, + &frm->ExtCap, pe_session); if (pe_session->pLimJoinReq->is11Rconnection) { tSirBssDescription *bssdescr; diff --git a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c index 50719daca663..d61aeb308648 100644 --- a/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c +++ b/core/mac/src/pe/lim/lim_send_sme_rsp_messages.c @@ -353,8 +353,6 @@ static void lim_handle_join_rsp_status(tpAniSirGlobal mac_ctx, ht_profile->htCapability = session_entry->htCapability; ht_profile->vhtCapability = session_entry->vhtCapability; - ht_profile->vhtTxChannelWidthSet = - session_entry->vhtTxChannelWidthSet; ht_profile->apCenterChan = session_entry->ch_center_freq_seg0; ht_profile->apChanWidth = session_entry->ch_width; } @@ -648,8 +646,6 @@ lim_send_sme_start_bss_rsp(tpAniSirGlobal pMac, psessionEntry->htCapability; pSirSmeRsp->HTProfile.vhtCapability = psessionEntry->vhtCapability; - pSirSmeRsp->HTProfile.vhtTxChannelWidthSet = - psessionEntry->vhtTxChannelWidthSet; pSirSmeRsp->HTProfile.apCenterChan = psessionEntry->ch_center_freq_seg0; pSirSmeRsp->HTProfile.apChanWidth = @@ -704,9 +700,6 @@ lim_send_sme_scan_rsp(tpAniSirGlobal pMac, tSirResultCodes resultCode, uint8_t smesessionId, uint16_t smetranscationId, uint32_t scan_id) { - lim_log(pMac, LOG1, - FL("Sending message SME_SCAN_RSP reasonCode %s scanId %d"), - lim_result_code_str(resultCode), scan_id); lim_post_sme_scan_rsp_message(pMac, resultCode, smesessionId, smetranscationId, scan_id); } diff --git a/core/mac/src/pe/lim/lim_session.c b/core/mac/src/pe/lim/lim_session.c index 1aa2a6080bf3..8f1a8c139833 100644 --- a/core/mac/src/pe/lim/lim_session.c +++ b/core/mac/src/pe/lim/lim_session.c @@ -295,6 +295,8 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId, session_ptr->gLimNumOfCurrentSTAs = 0; /* Copy the BSSID to the session table */ sir_copy_mac_addr(session_ptr->bssId, bssid); + if (bssType == eSIR_MONITOR_MODE) + sir_copy_mac_addr(pMac->lim.gpSession[i].selfMacAddr, bssid); session_ptr->valid = true; /* Intialize the SME and MLM states to IDLE */ session_ptr->limMlmState = eLIM_MLM_IDLE_STATE; @@ -355,6 +357,10 @@ pe_create_session(tpAniSirGlobal pMac, uint8_t *bssid, uint8_t *sessionId, } if (eSIR_INFRASTRUCTURE_MODE == bssType) lim_ft_open(pMac, &pMac->lim.gpSession[i]); + + if (eSIR_MONITOR_MODE == bssType) + lim_ft_open(pMac, &pMac->lim.gpSession[i]); + if (eSIR_INFRA_AP_MODE == bssType) { session_ptr->old_protection_state = 0; session_ptr->mac_ctx = (void *)pMac; diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 45265686cd83..3dbf1ff563e0 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -868,6 +868,10 @@ uint8_t lim_write_deferred_msg_q(tpAniSirGlobal mac_ctx, tpSirMsgQ lim_msg) FL("queue->MsgQ full Msg:%d Msgs Failed:%d"), lim_msg->type, ++mac_ctx->lim.deferredMsgCnt); + cds_flush_logs(WLAN_LOG_TYPE_NON_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_QUEUE_FULL, + true, false); } else { mac_ctx->lim.deferredMsgCnt++; } diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index db836f05c46f..99ee02af2fd1 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -527,8 +527,8 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg) CASE_RETURN_STRING(SIR_HAL_START_STOP_LOGGING); CASE_RETURN_STRING(SIR_HAL_FLUSH_LOG_TO_FW); CASE_RETURN_STRING(SIR_HAL_PDEV_SET_PCL_TO_FW); - CASE_RETURN_STRING(SIR_HAL_SOC_SET_HW_MODE); - CASE_RETURN_STRING(SIR_HAL_SOC_DUAL_MAC_CFG_REQ); + CASE_RETURN_STRING(SIR_HAL_PDEV_SET_HW_MODE); + CASE_RETURN_STRING(SIR_HAL_PDEV_DUAL_MAC_CFG_REQ); CASE_RETURN_STRING(WMA_RADAR_DETECTED_IND); CASE_RETURN_STRING(WMA_TIMER_TRAFFIC_STATS_IND); #ifdef WLAN_FEATURE_11W diff --git a/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/core/mac/src/sys/legacy/src/utils/src/parser_api.c index db860844cef0..8063d79d0c31 100644 --- a/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -304,7 +304,7 @@ populate_dot11_supp_operating_classes(tpAniSirGlobal mac_ptr, { uint8_t ch_bandwidth; - if (session_entry->vhtTxChannelWidthSet == eHT_CHANNEL_WIDTH_80MHZ) { + if (session_entry->ch_width == CH_WIDTH_80MHZ) { ch_bandwidth = BW80; } else { switch (session_entry->htSecondaryChannelOffset) { @@ -747,13 +747,6 @@ populate_dot11f_ht_caps(tpAniSirGlobal pMac, pDot11f->shortGI40MHz = 0; } - dot11f_log(pMac, LOG2, - FL - ("SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d\n"), - pDot11f->supportedChannelWidthSet, pDot11f->mimoPowerSave, - pDot11f->greenField, pDot11f->shortGI20MHz, - pDot11f->shortGI40MHz, pDot11f->dsssCckMode40MHz); - CFG_GET_INT(nSirStatus, pMac, WNI_CFG_HT_AMPDU_PARAMS, nCfgValue); nCfgValue8 = (uint8_t) nCfgValue; @@ -763,8 +756,6 @@ populate_dot11f_ht_caps(tpAniSirGlobal pMac, pDot11f->mpduDensity = pHTParametersInfo->mpduDensity; pDot11f->reserved1 = pHTParametersInfo->reserved; - dot11f_log(pMac, LOG2, FL("AMPDU Param: %x\n"), nCfgValue); - CFG_GET_STR(nSirStatus, pMac, WNI_CFG_SUPPORTED_MCS_SET, pDot11f->supportedMCSSet, nCfgLen, SIZE_OF_SUPPORTED_MCS_SET); @@ -977,8 +968,7 @@ populate_dot11f_vht_caps(tpAniSirGlobal pMac, nCfgValue); pDot11f->ldpcCodingCap = (nCfgValue & 0x0001); - if (psessionEntry->vhtTxChannelWidthSet < - WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) { + if (psessionEntry->ch_width < CH_WIDTH_80MHZ) { pDot11f->shortGI80MHz = 0; } else { nCfgValue = 0; @@ -989,8 +979,7 @@ populate_dot11f_vht_caps(tpAniSirGlobal pMac, pDot11f->shortGI80MHz = (nCfgValue & 0x0001); } - if (psessionEntry->vhtTxChannelWidthSet < - WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) { + if (psessionEntry->ch_width < CH_WIDTH_160MHZ) { pDot11f->shortGI160and80plus80MHz = 0; } else { nCfgValue = 0; @@ -3658,6 +3647,11 @@ sir_parse_beacon_ie(tpAniSirGlobal pMac, &pBies->vendor2_ie.VHTOperation, sizeof(tDot11fIEVHTOperation)); } + if (pBies->ExtCap.present) { + pBeaconStruct->ext_cap.present = 1; + qdf_mem_copy(&pBeaconStruct->ext_cap, &pBies->ExtCap, + sizeof(tDot11fIEExtCap)); + } qdf_mem_free(pBies); return eSIR_SUCCESS; } /* End sir_parse_beacon_ie. */ diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h new file mode 100644 index 000000000000..53f25b4394a1 --- /dev/null +++ b/core/pld/inc/pld_common.h @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __PLD_COMMON_H__ +#define __PLD_COMMON_H__ + +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/pm.h> + +/** + * enum pld_bus_type - bus type + * @PLD_BUS_TYPE_NONE: invalid bus type, only return in error cases + * @PLD_BUS_TYPE_PCIE: PCIE bus + * @PLD_BUS_TYPE_SNOC: SNOC bus + */ +enum pld_bus_type { + PLD_BUS_TYPE_NONE = -1, + PLD_BUS_TYPE_PCIE = 0, + PLD_BUS_TYPE_SNOC +}; + +#define PLD_MAX_FIRMWARE_SIZE (1 * 1024 * 1024) + +/** + * enum pld_bus_width_type - bus bandwith + * @PLD_BUS_WIDTH_NONE: don't vote for bus bandwidth + * @PLD_BUS_WIDTH_LOW: vote for low bus bandwidth + * @PLD_BUS_WIDTH_MEDIUM: vote for medium bus bandwidth + * @PLD_BUS_WIDTH_HIGH: vote for high bus bandwidth + */ +enum pld_bus_width_type { + PLD_BUS_WIDTH_NONE, + PLD_BUS_WIDTH_LOW, + PLD_BUS_WIDTH_MEDIUM, + PLD_BUS_WIDTH_HIGH +}; + +#define PLD_MAX_FILE_NAME 20 + +/** + * struct pld_fw_file - WLAN FW file names + * @image_file: WLAN FW image file + * @board_data: WLAN FW board data file + * @otp_data: WLAN FW OTP file + * @utf_file: WLAN FW UTF file + * @utf_board_data: WLAN FW UTF board data file + * @epping_file: WLAN FW EPPING mode file + * @evicted_data: WLAN FW evicted file + * + * pld_fw_files is used to store WLAN FW file names + */ +struct pld_fw_files { + char image_file[PLD_MAX_FILE_NAME]; + char board_data[PLD_MAX_FILE_NAME]; + char otp_data[PLD_MAX_FILE_NAME]; + char utf_file[PLD_MAX_FILE_NAME]; + char utf_board_data[PLD_MAX_FILE_NAME]; + char epping_file[PLD_MAX_FILE_NAME]; + char evicted_data[PLD_MAX_FILE_NAME]; +}; + +/** + * struct pld_image_desc_info - FW image description + * @fw_addr: FW image address + * @fw_size: FW image size + * @bdata_addr: FW board data address + * @bdata_size: FW board data size + * + * pld_image_desc_info is used to store FW image description + * information. + */ +struct pld_image_desc_info { + dma_addr_t fw_addr; + u32 fw_size; + dma_addr_t bdata_addr; + u32 bdata_size; +}; + +#define PLD_CODESWAP_MAX_CODESEGS 16 + +/** + * struct pld_codeswap_codeseg_info - code swap segment information + * @codeseg_total_bytes: total bytes of segments + * @num_codesegs: number of code segments + * @codeseg_size: code segment size + * @codeseg_size_log2: log2 of code segment size + * @codeseg_busaddr: array of addresses of each code segment + * + * pld_codeswap_codeseg_info is used to store code swap segment + * information. + */ +struct pld_codeswap_codeseg_info { + u32 codeseg_total_bytes; + u32 num_codesegs; + u32 codeseg_size; + u32 codeseg_size_log2; + void *codeseg_busaddr[PLD_CODESWAP_MAX_CODESEGS]; +}; + +/** + * enum pld_platform_cap_flag - platform capability flag + * @PLD_HAS_EXTERNAL_SWREG: has external regulator + * @PLD_HAS_UART_ACCESS: has UART access + */ +enum pld_platform_cap_flag { + PLD_HAS_EXTERNAL_SWREG = 0x01, + PLD_HAS_UART_ACCESS = 0x02, +}; + +/** + * struct pld_platform_cap - platform capabilities + * @cap_flag: capabilities flag + * + * pld_platform_cap provides platform capabilities which are + * extracted from DTS. + */ +struct pld_platform_cap { + u32 cap_flag; +}; + +/** + * enum pld_driver_status - WLAN driver status + * @PLD_UNINITIALIZED: driver is uninitialized + * @PLD_INITIALIZED: driver is initialized + * @PLD_LOAD_UNLOADL: driver is in load-unload status + */ +enum pld_driver_status { + PLD_UNINITIALIZED, + PLD_INITIALIZED, + PLD_LOAD_UNLOAD +}; + +/** + * struct pld_ce_tgt_pipe_cfg - copy engine target pipe configuration + * @pipe_num: pipe number + * @pipe_dir: pipe direction + * @nentries: number of entries + * @nbytes_max: max number of bytes + * @flags: flags + * @reserved: reserved + * + * pld_ce_tgt_pipe_cfg is used to store copy engine target pipe + * configuration. + */ +struct pld_ce_tgt_pipe_cfg { + u32 pipe_num; + u32 pipe_dir; + u32 nentries; + u32 nbytes_max; + u32 flags; + u32 reserved; +}; + +/** + * struct pld_ce_svc_pipe_cfg - copy engine service pipe configuration + * @service_id: service ID + * @pipe_dir: pipe direction + * @pipe_num: pipe number + * + * pld_ce_svc_pipe_cfg is used to store copy engine service pipe + * configuration. + */ +struct pld_ce_svc_pipe_cfg { + u32 service_id; + u32 pipe_dir; + u32 pipe_num; +}; + +/** + * struct pld_shadow_reg_cfg - shadow register configuration + * @ce_id: copy engine ID + * @reg_offset: register offset + * + * pld_shadow_reg_cfg is used to store shadow register configuration. + */ +struct pld_shadow_reg_cfg { + u16 ce_id; + u16 reg_offset; +}; + +/** + * struct pld_wlan_enable_cfg - WLAN FW configuration + * @num_ce_tgt_cfg: number of CE target configuration + * @ce_tgt_cfg: CE target configuration + * @num_ce_svc_pipe_cfg: number of CE service configuration + * @ce_svc_cfg: CE service configuration + * @num_shadow_reg_cfg: number of shadow register configuration + * @shadow_reg_cfg: shadow register configuration + * + * pld_wlan_enable_cfg stores WLAN FW configurations. It will be + * passed to WLAN FW when WLAN host driver calls wlan_enable. + */ +struct pld_wlan_enable_cfg { + u32 num_ce_tgt_cfg; + struct pld_ce_tgt_pipe_cfg *ce_tgt_cfg; + u32 num_ce_svc_pipe_cfg; + struct pld_ce_svc_pipe_cfg *ce_svc_cfg; + u32 num_shadow_reg_cfg; + struct pld_shadow_reg_cfg *shadow_reg_cfg; +}; + +/** + * enum pld_driver_mode - WLAN host driver mode + * @PLD_MISSION: mission mode + * @PLD_FTM: FTM mode + * @PLD_EPPING: EPPING mode + * @PLD_WALTEST: WAL test mode, FW standalone test mode + * @PLD_OFF: OFF mode + */ +enum pld_driver_mode { + PLD_MISSION, + PLD_FTM, + PLD_EPPING, + PLD_WALTEST, + PLD_OFF +}; + +/** + * struct pld_soc_info - SOC information + * @v_addr: virtual address of preallocated memory + * @p_addr: physical address of preallcoated memory + * @version: version number + * + * pld_soc_info is used to store WLAN SOC information. + */ +struct pld_soc_info { + void __iomem *v_addr; + phys_addr_t p_addr; + u32 version; +}; + +/** + * struct pld_driver_ops - driver callback functions + * @probe: required operation, will be called when device is detected + * @remove: required operation, will be called when device is removed + * @shutdown: optional operation, will be called during SSR + * @reinit: optional operation, will be called during SSR + * @crash_shutdown: optional operation, will be called when a crash is + * detected + * @suspend: required operation, will be called for power management + * is enabled + * @resume: required operation, will be called for power management + * is enabled + * @modem_status: optional operation, will be called when platform driver + * sending modem power status to WLAN FW + * @runtime_suspend: optional operation, prepare the device for a condition + * in which it won't be able to communicate with the CPU(s) + * and RAM due to power management. + * @runtime_resume: optional operation, put the device into the fully + * active state in response to a wakeup event generated by + * hardware or at the request of software. + */ +struct pld_driver_ops { + int (*probe)(struct device *dev, + enum pld_bus_type bus_type, + void *bdev, void *id); + void (*remove)(struct device *dev, + enum pld_bus_type bus_type); + void (*shutdown)(struct device *dev, + enum pld_bus_type bus_type); + int (*reinit)(struct device *dev, + enum pld_bus_type bus_type, + void *bdev, void *id); + void (*crash_shutdown)(struct device *dev, + enum pld_bus_type bus_type); + int (*suspend)(struct device *dev, + enum pld_bus_type bus_type, + pm_message_t state); + int (*resume)(struct device *dev, + enum pld_bus_type bus_type); + void (*modem_status)(struct device *dev, + enum pld_bus_type bus_type, + int state); + int (*runtime_suspend)(struct device *dev, + enum pld_bus_type bus_type); + int (*runtime_resume)(struct device *dev, + enum pld_bus_type bus_type); +}; + +int pld_init(void); +void pld_deinit(void); + +int pld_register_driver(struct pld_driver_ops *ops); +void pld_unregister_driver(void); + +int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version); +int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode); +int pld_set_fw_debug_mode(struct device *dev, bool enablefwlog); +int pld_get_fw_files_for_target(struct device *dev, + struct pld_fw_files *pfw_files, + u32 target_type, u32 target_version); +int pld_get_fw_image(struct device *dev, + struct pld_image_desc_info *image_desc_info); +void pld_is_pci_link_down(struct device *dev); +int pld_pcie_shadow_control(struct device *dev, bool enable); +int pld_get_codeswap_struct(struct device *dev, + struct pld_codeswap_codeseg_info *swap_seg); +int pld_set_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list, + u16 ch_count); +int pld_get_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list, + u16 *ch_count, u16 buf_len); +int pld_wlan_set_dfs_nol(struct device *dev, void *info, u16 info_len); +int pld_wlan_get_dfs_nol(struct device *dev, void *info, u16 info_len); +int pld_wlan_pm_control(struct device *dev, bool vote); +void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size); +void pld_device_crashed(struct device *dev); +void pld_device_self_recovery(struct device *dev); +void pld_intr_notify_q6(struct device *dev); +void pld_request_pm_qos(struct device *dev, u32 qos_val); +void pld_remove_pm_qos(struct device *dev); +int pld_request_bus_bandwidth(struct device *dev, int bandwidth); +int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap); +void pld_set_driver_status(struct device *dev, enum pld_driver_status status); +int pld_get_bmi_setup(struct device *dev); +int pld_get_sha_hash(struct device *dev, const u8 *data, + u32 data_len, u8 *hash_idx, u8 *out); +void *pld_get_fw_ptr(struct device *dev); +int pld_auto_suspend(struct device *dev); +int pld_auto_resume(struct device *dev); + +int pld_ce_request_irq(struct device *dev, unsigned int ce_id, + irqreturn_t (*handler)(int, void *), + unsigned long flags, const char *name, void *ctx); +int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx); +void pld_enable_irq(struct device *dev, unsigned int ce_id); +void pld_disable_irq(struct device *dev, unsigned int ce_id); +int pld_get_soc_info(struct device *dev, struct pld_soc_info *info); +int pld_get_ce_id(struct device *dev, int irq); +void pld_lock_pm_sem(struct device *dev); +void pld_release_pm_sem(struct device *dev); + +#endif diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c new file mode 100644 index 000000000000..00d0e79368fc --- /dev/null +++ b/core/pld/src/pld_common.c @@ -0,0 +1,1157 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#define pr_fmt(fmt) "wlan_pld:%s:%d:: " fmt, __func__, __LINE__ + +#include <linux/printk.h> +#include <linux/err.h> +#include <linux/string.h> +#include <linux/list.h> +#include <linux/slab.h> +#include <linux/pm.h> + +#ifdef CONFIG_CNSS +#include <net/cnss.h> +#endif +#ifdef CONFIG_ICNSS +#include <soc/qcom/icnss.h> +#endif + +#include "pld_pcie.h" +#include "pld_snoc.h" +#include "pld_common.h" +#include "pld_internal.h" + +#define PLD_PCIE_REGISTERED BIT(0) +#define PLD_SNOC_REGISTERED BIT(1) + +static struct pld_context *pld_ctx; + +/** + * pld_init() - Initialize PLD module + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_init(void) +{ + struct pld_context *pld_context; + + pld_context = kzalloc(sizeof(*pld_context), GFP_KERNEL); + if (!pld_context) + return -ENOMEM; + + spin_lock_init(&pld_context->pld_lock); + + INIT_LIST_HEAD(&pld_context->dev_list); + + pld_ctx = pld_context; + + return 0; +} + +/** + * pld_deinit() - Uninitialize PLD module + * + * Return: void + */ +void pld_deinit(void) +{ + struct dev_node *dev_node; + struct pld_context *pld_context; + unsigned long flags; + + pld_context = pld_ctx; + if (!pld_context) { + pld_ctx = NULL; + return; + } + + spin_lock_irqsave(&pld_context->pld_lock, flags); + while (!list_empty(&pld_context->dev_list)) { + dev_node = list_first_entry(&pld_context->dev_list, + struct dev_node, list); + list_del(&dev_node->list); + kfree(dev_node); + } + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + + kfree(pld_context); + + pld_ctx = NULL; +} + +/** + * pld_get_global_context() - Get global context of PLD + * + * Return: PLD global context + */ +struct pld_context *pld_get_global_context(void) +{ + return pld_ctx; +} + +/** + * pld_get_bus_type() - Bus type of the device + * @dev: device + * + * Return: PLD bus type + */ +enum pld_bus_type pld_get_bus_type(struct device *dev) +{ + struct pld_context *pld_context; + struct dev_node *dev_node; + unsigned long flags; + + pld_context = pld_get_global_context(); + + if (dev == NULL || pld_context == NULL) { + pr_err("Invalid info: dev %p, context %p\n", + dev, pld_context); + return PLD_BUS_TYPE_NONE; + } + + spin_lock_irqsave(&pld_context->pld_lock, flags); + list_for_each_entry(dev_node, &pld_context->dev_list, list) { + if (dev_node->dev == dev) { + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + return dev_node->bus_type; + } + } + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + + return PLD_BUS_TYPE_NONE; +} + +/** + * pld_register_driver() - Register driver to kernel + * @ops: Callback functions that will be registered to kernel + * + * This function should be called when other modules want to + * register platform driver callback functions to kernel. The + * probe() is expected to be called after registration if the + * device is online. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_register_driver(struct pld_driver_ops *ops) +{ + int ret = 0; + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + + if (pld_context == NULL) { + pr_err("global context is NULL\n"); + ret = -ENODEV; + goto out; + } + + if (pld_context->ops) { + pr_err("driver already registered\n"); + ret = -EEXIST; + goto out; + } + + if (!ops || !ops->probe || !ops->remove || + !ops->suspend || !ops->resume) { + pr_err("Required callback functions are missing\n"); + ret = -EINVAL; + goto out; + } + + pld_context->ops = ops; + + if (0 == pld_pcie_register_driver()) + pld_context->pld_driver_state |= PLD_PCIE_REGISTERED; + if (0 == pld_snoc_register_driver()) + pld_context->pld_driver_state |= PLD_SNOC_REGISTERED; + + if (0 == pld_context->pld_driver_state) { + pr_err("All driver falied to register\n"); + ret = -EINVAL; + goto out; + } + +out: + return ret; +} + +/** + * pld_unregister_driver() - Unregister driver to kernel + * + * This function should be called when other modules want to + * unregister callback functions from kernel. The remove() is + * expected to be called after registration. + * + * Return: void + */ +void pld_unregister_driver(void) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + + if (pld_context == NULL) { + pr_err("global context is NULL\n"); + return; + } + + if (pld_context->ops == NULL) { + pr_err("driver not registered\n"); + return; + } + + pld_pcie_unregister_driver(); + pld_snoc_unregister_driver(); + + pld_context->pld_driver_state = 0; + + pld_context->ops = NULL; +} + +/** + * pld_wlan_enable() - Enable WLAN + * @dev: device + * @config: WLAN configuration data + * @mode: WLAN mode + * @host_version: host software version + * + * This function enables WLAN FW. It passed WLAN configuration data, + * WLAN mode and host software version to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_wlan_enable(config, mode, host_version); + break; + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_wlan_enable(config, mode, host_version); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_wlan_disable() - Disable WLAN + * @dev: device + * @mode: WLAN mode + * + * This function disables WLAN FW. It passes WLAN mode to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_wlan_disable(mode); + break; + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_wlan_disable(mode); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_set_fw_debug_mode() - Set FW debug mode + * @dev: device + * @enablefwlog: 0 for QXDM, 1 for WMI + * + * Switch Fw debug mode between DIAG logging and WMI logging. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_set_fw_debug_mode(struct device *dev, bool enablefwlog) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_set_fw_debug_mode(enablefwlog); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_fw_files_for_target() - Get FW file names + * @dev: device + * @pfw_files: buffer for FW file names + * @target_type: target type + * @target_version: target version + * + * Return target specific FW file names to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_fw_files_for_target(struct device *dev, + struct pld_fw_files *pfw_files, + u32 target_type, u32 target_version) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_get_fw_files_for_target(pfw_files, + target_type, target_version); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_fw_image() - Get FW image descriptor + * @dev: device + * @image_desc_info: buffer for image descriptor + * + * Return FW image descriptor to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_fw_image(struct device *dev, + struct pld_image_desc_info *image_desc_info) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_get_fw_image(image_desc_info); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_is_pci_link_down() - Notification for pci link down event + * @dev: device + * + * Notify platform that pci link is down. + * + * Return: void + */ +void pld_is_pci_link_down(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_wlan_pci_link_down(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_pcie_shadow_control() - Control pci shadow registers + * @dev: device + * @enable: 0 for disable, 1 for enable + * + * This function is for suspend/resume. It can control if we + * use pci shadow registers (for saving config space) or not. + * During suspend we disable it to avoid config space corruption. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_shadow_control(struct device *dev, bool enable) +{ + int ret = 0; + + /* cnss_shadow_control is not supported on BF64.0.3 kernel yet + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_shadow_control(enable); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + */ + return ret; +} + +/** + * pld_get_codeswap_struct() - Get codeswap structure + * @dev: device + * @swap_seg: buffer to codeswap information + * + * Return codeswap structure information to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_codeswap_struct(struct device *dev, + struct pld_codeswap_codeseg_info *swap_seg) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_get_codeswap_struct(swap_seg); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_set_wlan_unsafe_channel() - Set unsafe channel + * @dev: device + * @unsafe_ch_list: unsafe channel list + * @ch_count: number of channel + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_set_wlan_unsafe_channel(struct device *dev, + u16 *unsafe_ch_list, u16 ch_count) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_set_wlan_unsafe_channel(unsafe_ch_list, + ch_count); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_wlan_unsafe_channel() - Get unsafe channel + * @dev: device + * @unsafe_ch_list: buffer to unsafe channel list + * @ch_count: number of channel + * @buf_len: buffer length + * + * Return WLAN unsafe channel to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list, + u16 *ch_count, u16 buf_len) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_get_wlan_unsafe_channel(unsafe_ch_list, + ch_count, buf_len); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_wlan_set_dfs_nol() - Set DFS info + * @dev: device + * @info: DFS info + * @info_len: info length + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_wlan_set_dfs_nol(struct device *dev, void *info, u16 info_len) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_wlan_set_dfs_nol(info, info_len); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_wlan_get_dfs_nol() - Get DFS info + * @dev: device + * @info: buffer to DFS info + * @info_len: info length + * + * Return DFS info to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_wlan_get_dfs_nol(struct device *dev, void *info, u16 info_len) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_wlan_get_dfs_nol(info, info_len); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_wlan_pm_control() - WLAN PM control on PCIE + * @dev: device + * @vote: 0 for enable PCIE PC, 1 for disable PCIE PC + * + * This is for PCIE power collaps control during suspend/resume. + * When PCIE power collaps is disabled, WLAN FW can access memory + * through PCIE when system is suspended. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_wlan_pm_control(struct device *dev, bool vote) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_wlan_pm_control(vote); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_virt_ramdump_mem() - Get virtual ramdump memory + * @dev: device + * @size: buffer to virtual memory size + * + * Return: virtual ramdump memory address + */ +void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size) +{ + void *mem = NULL; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + mem = cnss_get_virt_ramdump_mem(size); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } + + return mem; +} + +/** + * pld_device_crashed() - Notification for device crash event + * @dev: device + * + * Notify subsystem a device crashed event. A subsystem restart + * is expected to happen after calling this function. + * + * Return: void + */ +void pld_device_crashed(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_device_crashed(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_device_self_recovery() - Device self recovery + * @dev: device + * + * Return: void + */ +void pld_device_self_recovery(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_device_self_recovery(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_intr_notify_q6() - Notify Q6 FW interrupts + * @dev: device + * + * Notify Q6 that a FW interrupt is triggered. + * + * Return: void + */ +void pld_intr_notify_q6(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_intr_notify_q6(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_request_pm_qos() - Request system PM + * @dev: device + * @qos_val: request value + * + * It votes for the value of aggregate QoS expectations. + * + * Return: void + */ +void pld_request_pm_qos(struct device *dev, u32 qos_val) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_request_pm_qos(qos_val); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_remove_pm_qos() - Remove system PM + * @dev: device + * + * Remove the vote request for Qos expectations. + * + * Return: void + */ +void pld_remove_pm_qos(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_remove_pm_qos(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_request_bus_bandwidth() - Request bus bandwidth + * @dev: device + * @bandwidth: bus bandwidth + * + * Votes for HIGH/MEDIUM/LOW bus bandwidth. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_request_bus_bandwidth(struct device *dev, int bandwidth) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_request_bus_bandwidth(bandwidth); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_platform_cap() - Get platform capabilities + * @dev: device + * @cap: buffer to the capabilities + * + * Return capabilities to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_get_platform_cap(cap); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_set_driver_status() - Set driver status + * @dev: device + * @status: driver status + * + * Return: void + */ +void pld_set_driver_status(struct device *dev, enum pld_driver_status status) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + pld_pcie_set_driver_status(status); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_get_bmi_setup() - Get BMI setup + * @dev: device + * + * BMI read/write test should be run if BMI test is enabled. + * + * Return: BMI test setup + */ +int pld_get_bmi_setup(struct device *dev) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_get_bmi_setup(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_sha_hash() - Get sha hash number + * @dev: device + * @data: input data + * @data_len: data length + * @hash_idx: hash index + * @out: output buffer + * + * Return computed hash to the out buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_sha_hash(struct device *dev, const u8 *data, + u32 data_len, u8 *hash_idx, u8 *out) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_get_sha_hash(data, data_len, + hash_idx, out); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_fw_ptr() - Get secure FW memory address + * @dev: device + * + * Return: secure memory address + */ +void *pld_get_fw_ptr(struct device *dev) +{ + void *ptr = NULL; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ptr = cnss_get_fw_ptr(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } + + return ptr; +} + +/** + * pld_auto_suspend() - Auto suspend + * @dev: device + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_auto_suspend(struct device *dev) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_auto_suspend(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_auto_resume() - Auto resume + * @dev: device + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_auto_resume(struct device *dev) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + ret = cnss_auto_resume(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_ce_request_irq() - Register IRQ for CE + * @dev: device + * @ce_id: CE number + * @handler: IRQ callback function + * @flags: IRQ flags + * @name: IRQ name + * @ctx: IRQ context + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_ce_request_irq(struct device *dev, unsigned int ce_id, + irqreturn_t (*handler)(int, void *), + unsigned long flags, const char *name, void *ctx) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_SNOC: + ret = icnss_ce_request_irq(ce_id, handler, flags, name, ctx); + break; + case PLD_BUS_TYPE_PCIE: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_ce_free_irq() - Free IRQ for CE + * @dev: device + * @ce_id: CE number + * @ctx: IRQ context + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_SNOC: + ret = icnss_ce_free_irq(ce_id, ctx); + break; + case PLD_BUS_TYPE_PCIE: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_enable_irq() - Enable IRQ for CE + * @dev: device + * @ce_id: CE number + * + * Return: void + */ +void pld_enable_irq(struct device *dev, unsigned int ce_id) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_SNOC: + icnss_enable_irq(ce_id); + break; + case PLD_BUS_TYPE_PCIE: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_disable_irq() - Disable IRQ for CE + * @dev: device + * @ce_id: CE number + * + * Return: void + */ +void pld_disable_irq(struct device *dev, unsigned int ce_id) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_SNOC: + icnss_disable_irq(ce_id); + break; + case PLD_BUS_TYPE_PCIE: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_get_soc_info() - Get SOC information + * @dev: device + * @info: buffer to SOC information + * + * Return SOC info to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_get_soc_info(struct device *dev, struct pld_soc_info *info) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_get_soc_info(info); + break; + case PLD_BUS_TYPE_PCIE: + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_get_ce_id() - Get CE number for the provided IRQ + * @dev: device + * @irq: IRQ number + * + * Return: CE number + */ +int pld_get_ce_id(struct device *dev, int irq) +{ + int ret = 0; + + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_SNOC: + ret = icnss_get_ce_id(irq); + break; + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_get_ce_id(irq); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_lock_pm_sem() - Lock PM semaphore + * @dev: device + * + * Return: void + */ +void pld_lock_pm_sem(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_lock_pm_sem(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} + +/** + * pld_release_pm_sem() - Release PM semaphore + * @dev: device + * + * Return: void + */ +void pld_release_pm_sem(struct device *dev) +{ + switch (pld_get_bus_type(dev)) { + case PLD_BUS_TYPE_PCIE: + cnss_release_pm_sem(); + break; + case PLD_BUS_TYPE_SNOC: + break; + default: + pr_err("Invalid device type\n"); + break; + } +} diff --git a/core/pld/src/pld_internal.h b/core/pld/src/pld_internal.h new file mode 100644 index 000000000000..3619848b6bbc --- /dev/null +++ b/core/pld/src/pld_internal.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __PLD_COMMON_I_H__ +#define __PLD_COMMON_I_H__ + +struct dev_node { + struct device *dev; + struct list_head list; + enum pld_bus_type bus_type; +}; + +struct pld_context { + struct pld_driver_ops *ops; + spinlock_t pld_lock; + struct list_head dev_list; + uint32_t pld_driver_state; +}; + +struct pld_context *pld_get_global_context(void); + +#endif diff --git a/core/pld/src/pld_pcie.c b/core/pld/src/pld_pcie.c new file mode 100644 index 000000000000..ab3cbd1e52eb --- /dev/null +++ b/core/pld/src/pld_pcie.c @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/pci.h> +#include <linux/list.h> +#include <linux/slab.h> + +#ifdef CONFIG_CNSS +#include <net/cnss.h> +#endif + +#include "pld_common.h" +#include "pld_internal.h" + +#ifdef CONFIG_PCI + +#ifdef QCA_WIFI_3_0_ADRASTEA +#define CE_COUNT_MAX 12 +#else +#define CE_COUNT_MAX 8 +#endif + +/** + * pld_pcie_probe() - Probe function for PCIE platform driver + * @pdev: PCIE device + * @id: PCIE device ID table + * + * The probe function will be called when PCIE device provided + * in the ID table is detected. + * + * Return: int + */ +static int pld_pcie_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct pld_context *pld_context; + unsigned long flags; + struct dev_node *dev_node; + int ret = 0; + + pld_context = pld_get_global_context(); + if (!pld_context) { + ret = -ENODEV; + goto out; + } + + dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL); + if (dev_node == NULL) { + ret = -ENOMEM; + goto out; + } + dev_node->dev = &pdev->dev; + dev_node->bus_type = PLD_BUS_TYPE_PCIE; + + spin_lock_irqsave(&pld_context->pld_lock, flags); + list_add_tail(&dev_node->list, &pld_context->dev_list); + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + + return pld_context->ops->probe(&pdev->dev, + PLD_BUS_TYPE_PCIE, pdev, (void *)id); + +out: + return ret; +} + + +/** + * pld_pcie_remove() - Remove function for PCIE device + * @pdev: PCIE device + * + * The remove function will be called when PCIE device is disconnected + * + * Return: void + */ +static void pld_pcie_remove(struct pci_dev *pdev) +{ + struct pld_context *pld_context; + unsigned long flags; + struct dev_node *dev_node, *tmp; + + pld_context = pld_get_global_context(); + + if (!pld_context) + return; + + spin_lock_irqsave(&pld_context->pld_lock, flags); + list_for_each_entry_safe(dev_node, tmp, &pld_context->dev_list, list) { + if (dev_node->dev == &pdev->dev) { + list_del(&dev_node->list); + kfree(dev_node); + } + } + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + + pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE); +} + +#ifdef CONFIG_CNSS +/** + * pld_pcie_reinit() - SSR re-initialize function for PCIE device + * @pdev: PCIE device + * @id: PCIE device ID + * + * During subsystem restart(SSR), this function will be called to + * re-initialize PCIE device. + * + * Return: int + */ +static int pld_pcie_reinit(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->reinit) + return pld_context->ops->reinit(&pdev->dev, + PLD_BUS_TYPE_PCIE, pdev, (void *)id); + + return -ENODEV; +} + +/** + * pld_pcie_shutdown() - SSR shutdown function for PCIE device + * @pdev: PCIE device + * + * During SSR, this function will be called to shutdown PCIE device. + * + * Return: void + */ +static void pld_pcie_shutdown(struct pci_dev *pdev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->shutdown) + pld_context->ops->shutdown(&pdev->dev, PLD_BUS_TYPE_PCIE); +} + +/** + * pld_pcie_crash_shutdown() - Crash shutdown function for PCIE device + * @pdev: PCIE device + * + * This function will be called when a crash is detected, it will shutdown + * the PCIE device. + * + * Return: void + */ +static void pld_pcie_crash_shutdown(struct pci_dev *pdev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->crash_shutdown) + pld_context->ops->crash_shutdown(&pdev->dev, PLD_BUS_TYPE_PCIE); +} + +/** + * pld_pcie_notify_handler() - Modem state notification callback function + * @pdev: PCIE device + * @state: modem power state + * + * This function will be called when there's a modem power state change. + * + * Return: void + */ +static void pld_pcie_notify_handler(struct pci_dev *pdev, int state) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->modem_status) + pld_context->ops->modem_status(&pdev->dev, + PLD_BUS_TYPE_PCIE, state); +} + +#ifdef FEATURE_RUNTIME_PM +/** + * pld_pcie_runtime_suspend() - PM runtime suspend + * @pdev: PCIE device + * + * PM runtime suspend callback function. + * + * Return: int + */ +static int pld_pcie_runtime_suspend(struct pci_dev *pdev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->runtime_suspend) + return pld_context->ops->runtime_suspend(&pdev->dev, + PLD_BUS_TYPE_PCIE); + + return -ENODEV; +} + +/** + * pld_pcie_runtime_resume() - PM runtime resume + * @pdev: PCIE device + * + * PM runtime resume callback function. + * + * Return: int + */ +static int pld_pcie_runtime_resume(struct pci_dev *pdev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->runtime_resume) + return pld_context->ops->runtime_resume(&pdev->dev, + PLD_BUS_TYPE_PCIE); + + return -ENODEV; +} +#endif +#endif + +/** + * pld_pcie_suspend() - Suspend callback function for power management + * @pdev: PCIE device + * @state: power state + * + * This function is to suspend the PCIE device when power management is + * enabled. + * + * Return: void + */ +static int pld_pcie_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + return pld_context->ops->suspend(&pdev->dev, + PLD_BUS_TYPE_PCIE, state); +} + +/** + * pld_pcie_resume() - Resume callback function for power management + * @pdev: PCIE device + * + * This function is to resume the PCIE device when power management is + * enabled. + * + * Return: void + */ +static int pld_pcie_resume(struct pci_dev *pdev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + return pld_context->ops->resume(&pdev->dev, PLD_BUS_TYPE_PCIE); +} + +static struct pci_device_id pld_pcie_id_table[] = { + { 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID }, + { 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID }, + { 0 } +}; + +#ifdef CONFIG_CNSS +#ifdef FEATURE_RUNTIME_PM +struct cnss_wlan_runtime_ops runtime_pm_ops = { + .runtime_suspend = pld_pcie_runtime_suspend, + .runtime_resume = pld_pcie_runtime_resume, +}; +#endif + +struct cnss_wlan_driver pld_pcie_ops = { + .name = "pld_pcie", + .id_table = pld_pcie_id_table, + .probe = pld_pcie_probe, + .remove = pld_pcie_remove, + .reinit = pld_pcie_reinit, + .shutdown = pld_pcie_shutdown, + .crash_shutdown = pld_pcie_crash_shutdown, + .modem_status = pld_pcie_notify_handler, +#ifdef CONFIG_PM + .suspend = pld_pcie_suspend, + .resume = pld_pcie_resume, +#endif +#ifdef FEATURE_RUNTIME_PM + .runtime_ops = &runtime_pm_ops, +#endif +}; + +/** + * pld_pcie_register_driver() - Register PCIE device callback functions + * + * Return: int + */ +int pld_pcie_register_driver(void) +{ + return cnss_wlan_register_driver(&pld_pcie_ops); +} + +/** + * pld_pcie_unregister_driver() - Unregister PCIE device callback functions + * + * Return: void + */ +void pld_pcie_unregister_driver(void) +{ + cnss_wlan_unregister_driver(&pld_pcie_ops); +} +#else +struct pci_driver pld_pcie_ops = { + .name = "pld_pcie", + .id_table = pld_pcie_id_table, + .probe = pld_pcie_probe, + .remove = pld_pcie_remove, +#ifdef CONFIG_PM + .suspend = pld_pcie_suspend, + .resume = pld_pcie_resume, +#endif +}; + +int pld_pcie_register_driver(void) +{ + return pci_register_driver(&pld_pcie_ops); +} + +void pld_pcie_unregister_driver(void) +{ + pci_unregister_driver(&pld_pcie_ops); +} +#endif + +/** + * pld_pcie_get_ce_id() - Get CE number for the provided IRQ + * @irq: IRQ number + * + * Return: CE number + */ +int pld_pcie_get_ce_id(int irq) +{ + int ce_id = irq - 100; + if (ce_id < CE_COUNT_MAX && ce_id >= 0) + return ce_id; + + return -EINVAL; +} + +#ifdef CONFIG_CNSS +#ifdef QCA_WIFI_3_0_ADRASTEA +/** + * pld_pcie_wlan_enable() - Enable WLAN + * @config: WLAN configuration data + * @mode: WLAN mode + * @host_version: host software version + * + * This function enables WLAN FW. It passed WLAN configuration data, + * WLAN mode and host software version to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_wlan_enable(struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version) +{ + struct cnss_wlan_enable_cfg cfg; + enum cnss_driver_mode cnss_mode; + + cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg; + cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *) + config->ce_tgt_cfg; + cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg; + cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *) + config->ce_svc_cfg; + cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg; + cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *) + config->shadow_reg_cfg; + + switch (mode) { + case PLD_FTM: + cnss_mode = CNSS_FTM; + break; + case PLD_EPPING: + cnss_mode = CNSS_EPPING; + break; + default: + cnss_mode = CNSS_MISSION; + break; + } + return cnss_wlan_enable(&cfg, cnss_mode, host_version); +} + +/** + * pld_pcie_wlan_disable() - Disable WLAN + * @mode: WLAN mode + * + * This function disables WLAN FW. It passes WLAN mode to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_wlan_disable(enum pld_driver_mode mode) +{ + return cnss_wlan_disable(CNSS_OFF); +} + +/** + * pld_pcie_set_fw_debug_mode() - Set FW debug mode + * @mode: 0 for QXDM, 1 for WMI + * + * Switch Fw debug mode between DIAG logging and WMI logging. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_set_fw_debug_mode(bool mode) +{ + return cnss_set_fw_debug_mode(mode); +} +#endif + +/** + * pld_pcie_get_fw_files_for_target() - Get FW file names + * @pfw_files: buffer for FW file names + * @target_type: target type + * @target_version: target version + * + * Return target specific FW file names to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_get_fw_files_for_target(struct pld_fw_files *pfw_files, + u32 target_type, u32 target_version) +{ + int ret = 0; + struct cnss_fw_files cnss_fw_files; + + if (pfw_files == NULL) + return -ENODEV; + + ret = cnss_get_fw_files_for_target(&cnss_fw_files, + target_type, target_version); + if (0 != ret) + return ret; + + memcpy(pfw_files, &cnss_fw_files, sizeof(*pfw_files)); + return 0; +} + +/** + * pld_pcie_get_fw_image() - Get FW image descriptor + * @image_desc_info: buffer for image descriptor + * + * Return FW image descriptor to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_get_fw_image(struct pld_image_desc_info *image_desc_info) +{ + int ret = 0; + struct image_desc_info cnss_image_desc_info; + + if (image_desc_info == NULL) + return -ENODEV; + + ret = cnss_get_fw_image(&cnss_image_desc_info); + if (0 != ret) + return ret; + + memcpy(image_desc_info, &cnss_image_desc_info, + sizeof(*image_desc_info)); + return 0; +} + +/** + * pld_pcie_get_codeswap_struct() - Get codeswap structure + * @swap_seg: buffer to codeswap information + * + * Return codeswap structure information to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_get_codeswap_struct(struct pld_codeswap_codeseg_info *swap_seg) +{ + int ret = 0; + struct codeswap_codeseg_info cnss_swap_seg; + + if (swap_seg == NULL) + return -ENODEV; + + ret = cnss_get_codeswap_struct(&cnss_swap_seg); + if (0 != ret) + return ret; + + memcpy(swap_seg, &cnss_swap_seg, sizeof(*swap_seg)); + return 0; +} + +/** + * pld_pcie_get_platform_cap() - Get platform capabilities + * @cap: buffer to the capabilities + * + * Return capabilities to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_pcie_get_platform_cap(struct pld_platform_cap *cap) +{ + int ret = 0; + struct cnss_platform_cap cnss_cap; + + if (cap == NULL) + return -ENODEV; + + ret = cnss_get_platform_cap(&cnss_cap); + if (0 != ret) + return ret; + + memcpy(cap, &cnss_cap, sizeof(*cap)); + return 0; +} + +/** + * pld_pcie_set_driver_status() - Set driver status + * @status: driver status + * + * Return: void + */ +void pld_pcie_set_driver_status(enum pld_driver_status status) +{ + enum cnss_driver_status cnss_status; + + switch (status) { + case PLD_UNINITIALIZED: + cnss_status = CNSS_UNINITIALIZED; + break; + case PLD_INITIALIZED: + cnss_status = CNSS_INITIALIZED; + break; + default: + cnss_status = CNSS_LOAD_UNLOAD; + break; + } + cnss_set_driver_status(cnss_status); +} +#endif + +#endif diff --git a/core/pld/src/pld_pcie.h b/core/pld/src/pld_pcie.h new file mode 100644 index 000000000000..adc830e4cda7 --- /dev/null +++ b/core/pld/src/pld_pcie.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __PLD_PCIE_H__ +#define __PLD_PCIE_H__ + +#include "pld_common.h" + +#ifndef CONFIG_PCI +static inline int pld_pcie_register_driver(void) +{ + return 0; +} + +static inline void pld_pcie_unregister_driver(void) +{ + return; +} + +static inline int pld_pcie_get_ce_id(int irq) +{ + return 0; +} +#else +int pld_pcie_register_driver(void); +void pld_pcie_unregister_driver(void); +int pld_pcie_get_ce_id(int irq); +#endif + +#if (!defined(CONFIG_CNSS)) || (!defined(QCA_WIFI_3_0_ADRASTEA)) +static inline int pld_pcie_wlan_enable(struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version) +{ + return 0; +} +static inline int pld_pcie_wlan_disable(enum pld_driver_mode mode) +{ + return 0; +} +static inline int pld_pcie_set_fw_debug_mode(bool enablefwlog) +{ + return 0; +} +static inline void cnss_intr_notify_q6(void) +{ + return; +} +#else +int pld_pcie_wlan_enable(struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version); +int pld_pcie_wlan_disable(enum pld_driver_mode mode); +int pld_pcie_set_fw_debug_mode(bool enablefwlog); +#endif + +#if (!defined(CONFIG_CNSS)) || (!defined(CONFIG_CNSS_SECURE_FW)) +static inline int cnss_get_sha_hash(const u8 *data, + u32 data_len, u8 *hash_idx, u8 *out) +{ + return 0; +} +static inline void *cnss_get_fw_ptr(void) +{ + return NULL; +} +#endif + +#if (!defined(CONFIG_CNSS)) || (!defined(CONFIG_PCI_MSM)) +static inline int cnss_wlan_pm_control(bool vote) +{ + return 0; +} +#endif + +#ifndef CONFIG_CNSS +static inline int +pld_pcie_get_fw_files_for_target(struct pld_fw_files *pfw_files, + u32 target_type, u32 target_version) +{ + return 0; +} +static inline int +pld_pcie_get_fw_image(struct pld_image_desc_info *image_desc_info) +{ + return 0; +} +static inline void cnss_wlan_pci_link_down(void) +{ + return; +} +static inline int cnss_pcie_shadow_control(bool enable) +{ + return 0; +} +static inline int +pld_pcie_get_codeswap_struct(struct pld_codeswap_codeseg_info *swap_seg) +{ + return 0; +} +static inline int +cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count) +{ + return 0; +} +static inline int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, + u16 *ch_count, u16 buf_len) +{ + return 0; +} +static inline int cnss_wlan_set_dfs_nol(void *info, u16 info_len) +{ + return 0; +} +static inline int cnss_wlan_get_dfs_nol(void *info, u16 info_len) +{ + return 0; +} +static inline void *cnss_get_virt_ramdump_mem(unsigned long *size) +{ + return NULL; +} +static inline void cnss_device_crashed(void) +{ + return; +} +static inline void cnss_device_self_recovery(void) +{ + return; +} +static inline void cnss_request_pm_qos(u32 qos_val) +{ + return; +} +static inline void cnss_remove_pm_qos(void) +{ + return; +} +static inline int cnss_request_bus_bandwidth(int bandwidth) +{ + return 0; +} +static inline int pld_pcie_get_platform_cap(struct pld_platform_cap *cap) +{ + return 0; +} +static inline void pld_pcie_set_driver_status(enum pld_driver_status status) +{ + return; +} +static inline int cnss_get_bmi_setup(void) +{ + return 0; +} +static inline int cnss_auto_suspend(void) +{ + return 0; +} +static inline int cnss_auto_resume(void) +{ + return 0; +} +static void cnss_lock_pm_sem(void) +{ + return; +} +static void cnss_release_pm_sem(void) +{ + return; +} +#else +int pld_pcie_get_fw_files_for_target(struct pld_fw_files *pfw_files, + u32 target_type, u32 target_version); +int pld_pcie_get_fw_image(struct pld_image_desc_info *image_desc_info); +int pld_pcie_get_codeswap_struct(struct pld_codeswap_codeseg_info *swap_seg); +int pld_pcie_get_platform_cap(struct pld_platform_cap *cap); +void pld_pcie_set_driver_status(enum pld_driver_status status); +#endif + +#endif diff --git a/core/pld/src/pld_snoc.c b/core/pld/src/pld_snoc.c new file mode 100644 index 000000000000..40cee705ea9d --- /dev/null +++ b/core/pld/src/pld_snoc.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#include <linux/platform_device.h> +#include <linux/err.h> +#include <linux/list.h> +#include <linux/slab.h> + +#ifdef CONFIG_ICNSS +#include <soc/qcom/icnss.h> +#endif + +#include "pld_common.h" +#include "pld_internal.h" + +#ifdef CONFIG_ICNSS +/** + * pld_snoc_probe() - Probe function for platform driver + * @dev: device + * + * The probe function will be called when platform device + * is detected. + * + * Return: int + */ +static int pld_snoc_probe(struct device *dev) +{ + struct pld_context *pld_context; + unsigned long flags; + struct dev_node *dev_node; + int ret = 0; + + pld_context = pld_get_global_context(); + if (!pld_context) { + ret = -ENODEV; + goto out; + } + + dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL); + if (dev_node == NULL) { + ret = -ENOMEM; + goto out; + } + dev_node->dev = dev; + dev_node->bus_type = PLD_BUS_TYPE_SNOC; + + spin_lock_irqsave(&pld_context->pld_lock, flags); + list_add_tail(&dev_node->list, &pld_context->dev_list); + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + + return pld_context->ops->probe(dev, PLD_BUS_TYPE_SNOC, + NULL, NULL); + +out: + return ret; +} + +/** + * pld_snoc_remove() - Remove function for platform device + * @dev: device + * + * The remove function will be called when platform device + * is disconnected + * + * Return: void + */ +static void pld_snoc_remove(struct device *dev) +{ + struct pld_context *pld_context; + unsigned long flags; + struct dev_node *dev_node, *tmp; + + pld_context = pld_get_global_context(); + + if (!pld_context) + return; + + spin_lock_irqsave(&pld_context->pld_lock, flags); + list_for_each_entry_safe(dev_node, tmp, &pld_context->dev_list, list) { + if (dev_node->dev == dev) { + list_del(&dev_node->list); + kfree(dev_node); + } + } + spin_unlock_irqrestore(&pld_context->pld_lock, flags); + + pld_context->ops->remove(dev, PLD_BUS_TYPE_SNOC); +} + +/** + * pld_snoc_reinit() - SSR re-initialize function for platform device + * @dev: device + * + * During subsystem restart(SSR), this function will be called to + * re-initialize platform device. + * + * Return: int + */ +static int pld_snoc_reinit(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->reinit) + return pld_context->ops->reinit(dev, PLD_BUS_TYPE_SNOC, + NULL, NULL); + + return -ENODEV; +} + +/** + * pld_snoc_shutdown() - SSR shutdown function for platform device + * @dev: device + * + * During SSR, this function will be called to shutdown platform device. + * + * Return: void + */ +static void pld_snoc_shutdown(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->shutdown) + pld_context->ops->shutdown(dev, PLD_BUS_TYPE_SNOC); +} + +/** + * pld_snoc_crash_shutdown() - Crash shutdown function for platform device + * @dev: device + * + * This function will be called when a crash is detected, it will shutdown + * platform device. + * + * Return: void + */ +static void pld_snoc_crash_shutdown(void *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + if (pld_context->ops->crash_shutdown) + pld_context->ops->crash_shutdown(dev, PLD_BUS_TYPE_SNOC); +} + +/** + * pld_snoc_suspend() - Suspend callback function for power management + * @dev: device + * @state: power state + * + * This function is to suspend the platform device when power management + * is enabled. + * + * Return: void + */ +static int pld_snoc_suspend(struct device *dev, pm_message_t state) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + return pld_context->ops->suspend(dev, PLD_BUS_TYPE_SNOC, state); +} + +/** + * pld_snoc_resume() - Resume callback function for power management + * @pdev: device + * + * This function is to resume the platform device when power management + * is enabled. + * + * Return: void + */ +static int pld_snoc_resume(struct device *dev) +{ + struct pld_context *pld_context; + + pld_context = pld_get_global_context(); + return pld_context->ops->resume(dev, PLD_BUS_TYPE_SNOC); +} + +struct icnss_driver_ops pld_snoc_ops = { + .name = "pld_snoc", + .probe = pld_snoc_probe, + .remove = pld_snoc_remove, + .shutdown = pld_snoc_shutdown, + .reinit = pld_snoc_reinit, + .crash_shutdown = pld_snoc_crash_shutdown, + .suspend = pld_snoc_suspend, + .resume = pld_snoc_resume, +}; + +/** + * pld_snoc_register_driver() - Register platform device callback functions + * + * Return: int + */ +int pld_snoc_register_driver(void) +{ + return icnss_register_driver(&pld_snoc_ops); +} + +/** + * pld_snoc_unregister_driver() - Unregister platform device callback functions + * + * Return: void + */ +void pld_snoc_unregister_driver(void) +{ + icnss_unregister_driver(&pld_snoc_ops); +} + +/** + * pld_snoc_wlan_enable() - Enable WLAN + * @config: WLAN configuration data + * @mode: WLAN mode + * @host_version: host software version + * + * This function enables WLAN FW. It passed WLAN configuration data, + * WLAN mode and host software version to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_snoc_wlan_enable(struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version) +{ + struct icnss_wlan_enable_cfg cfg; + enum icnss_driver_mode icnss_mode; + + cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg; + cfg.ce_tgt_cfg = (struct ce_tgt_pipe_cfg *) + config->ce_tgt_cfg; + cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg; + cfg.ce_svc_cfg = (struct ce_svc_pipe_cfg *) + config->ce_svc_cfg; + cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg; + cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *) + config->shadow_reg_cfg; + + switch (mode) { + case PLD_FTM: + icnss_mode = ICNSS_FTM; + break; + case PLD_EPPING: + icnss_mode = ICNSS_EPPING; + break; + default: + icnss_mode = ICNSS_MISSION; + break; + } + return icnss_wlan_enable(&cfg, icnss_mode, host_version); +} + +/** + * pld_snoc_wlan_disable() - Disable WLAN + * @mode: WLAN mode + * + * This function disables WLAN FW. It passes WLAN mode to FW. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_snoc_wlan_disable(enum pld_driver_mode mode) +{ + return icnss_wlan_disable(ICNSS_OFF); +} + +/** + * pld_snoc_get_soc_info() - Get SOC information + * @info: buffer to SOC information + * + * Return SOC info to the buffer. + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_snoc_get_soc_info(struct pld_soc_info *info) +{ + int ret = 0; + struct icnss_soc_info icnss_info; + + if (info == NULL) + return -ENODEV; + + ret = icnss_get_soc_info(&icnss_info); + if (0 != ret) + return ret; + + memcpy(info, &icnss_info, sizeof(*info)); + return 0; +} + +#endif diff --git a/core/pld/src/pld_snoc.h b/core/pld/src/pld_snoc.h new file mode 100644 index 000000000000..321710680cf2 --- /dev/null +++ b/core/pld/src/pld_snoc.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2016 The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * 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. + */ + +/* + * This file was originally distributed by Qualcomm Atheros, Inc. + * under proprietary terms before Copyright ownership was assigned + * to the Linux Foundation. + */ + +#ifndef __PLD_SNOC_H__ +#define __PLD_SNOC_H__ + +#include "pld_common.h" + +#ifndef CONFIG_ICNSS +static inline int pld_snoc_register_driver(void) +{ + return 0; +} + +static inline void pld_snoc_unregister_driver(void) +{ + return; +} +static inline int pld_snoc_wlan_enable(struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version) +{ + return 0; +} +static inline int pld_snoc_wlan_disable(enum pld_driver_mode mode) +{ + return 0; +} +static inline int icnss_ce_request_irq(unsigned int ce_id, + irqreturn_t (*handler)(int, void *), + unsigned long flags, const char *name, void *ctx) +{ + return 0; +} +static inline int icnss_ce_free_irq(unsigned int ce_id, void *ctx) +{ + return 0; +} +static inline void icnss_enable_irq(unsigned int ce_id) +{ + return; +} +static inline void icnss_disable_irq(unsigned int ce_id) +{ + return; +} +static inline int icnss_get_soc_info(struct pld_soc_info *info) +{ + return 0; +} +static inline int icnss_get_ce_id(int irq) +{ + return 0; +} +static inline int pld_snoc_get_soc_info(struct pld_soc_info *info) +{ + return 0; +} +#else +int pld_snoc_register_driver(void); +void pld_snoc_unregister_driver(void); +int pld_snoc_wlan_enable(struct pld_wlan_enable_cfg *config, + enum pld_driver_mode mode, const char *host_version); +int pld_snoc_wlan_disable(enum pld_driver_mode mode); +int pld_snoc_get_soc_info(struct pld_soc_info *info); +#endif + +#endif diff --git a/core/sap/dfs/inc/dfs.h b/core/sap/dfs/inc/dfs.h index 56187cbcdc8b..74c0add523a5 100644 --- a/core/sap/dfs/inc/dfs.h +++ b/core/sap/dfs/inc/dfs.h @@ -101,6 +101,16 @@ #define DFS_80P80_SEG0 0 #define DFS_80P80_SEG1 1 +/** + * @DFS_RADAR_SUMMARY_REPORT_VERSION_2: DFS-2 radar summary report + * @DFS_RADAR_SUMMARY_REPORT_VERSION_3: DFS-3 radar summary report + */ +enum { + DFS_RADAR_SUMMARY_REPORT_VERSION_2 = 1, + DFS_RADAR_SUMMARY_REPORT_VERSION_3 = 2, +}; + + /* * Constants to use for chirping detection. * @@ -286,6 +296,19 @@ struct dfs_event { uint32_t re_freq_hi; /* Upper bounds of frequency, KHz */ int sidx; /* Pulse Index as in radar summary report */ int radar_80p80_segid; /* 80p80 segment ID as in radar sum report */ + int delta_peak; /* delta peak reported in radar summary */ + int delta_diff; /* delta diff reported in radar summary */ + int agc_total_gain; /* agc total gain reported in radar summary */ + int agc_mb_gain; /* agc mb gain reported in radar summary */ + int radar_subchan_mask; /* subchan mask reported in radar summary */ + int pulse_height; /* pulse height reported in radar summary */ + int triggering_agc_event; /* triggering agc reported in radar summary */ + int pulse_rssi; /* rssi of phyerr reported in radar summary */ + int radar_fft_pri80_inband_power; /* Pri80MHz pwr reported in summary */ + int radar_fft_ext80_inband_power; /* Ext80MHz pwr reported in summary */ + int rsu_version; /* Radar summary report version */ + int phyerr_serial_num; /* phyerr seq num queued for pattern matching */ + int peak_mag; /* Peak mag reported in radar search FFT report */ STAILQ_ENTRY(dfs_event) re_list; /* List of radar events */ } qdf_packed; #ifdef WIN32 @@ -737,6 +760,30 @@ struct dfs_phy_err { * when SAP is operating in 80p80 channel width. */ int radar_80p80_segid; + /* delta peak reported in radar summary */ + int delta_peak; + /* delta diff reported in radar summary */ + int delta_diff; + /* agc total gain reported in radar summary */ + int agc_total_gain; + /* agc mb gain reported in radar summary */ + int agc_mb_gain; + /* subchan mask reported in radar summary */ + int radar_subchan_mask; + /* pulse height reported in radar summary */ + int pulse_height; + /* triggering agc reported in radar summary */ + int triggering_agc_event; + /* rssi of phyerr reported in radar summary */ + int pulse_rssi; + /* Pri80MHz pwr reported in summary */ + int radar_fft_pri80_inband_power; + /* Ext80MHz pwr reported in summary */ + int radar_fft_ext80_inband_power; + /* Peak mag reported in radar search FFT report */ + int peak_mag; + /* Radar summary report version */ + int rsu_version; }; /* Attach, detach, handle ioctl prototypes */ diff --git a/core/sap/dfs/src/dfs_phyerr_tlv.c b/core/sap/dfs/src/dfs_phyerr_tlv.c index 3ac1d08c1071..058e321d1c38 100644 --- a/core/sap/dfs/src/dfs_phyerr_tlv.c +++ b/core/sap/dfs/src/dfs_phyerr_tlv.c @@ -35,16 +35,6 @@ #include "dfs_phyerr.h" #include "dfs_phyerr_tlv.h" -/** - * enum RADAR_SUMMARY_VERSION - Radar summary report version - * @DFS_RADAR_SUMMARY_REPORT_VERSION_2: DFS-2 radar summary report - * @DFS_RADAR_SUMMARY_REPORT_VERSION_3: DFS-3 radar summary report - */ -typedef enum { -DFS_RADAR_SUMMARY_REPORT_VERSION_2 = 1, -DFS_RADAR_SUMMARY_REPORT_VERSION_3 = 2, -} RADAR_SUMMARY_VERSION; - /* * Parsed radar status */ @@ -62,7 +52,7 @@ struct rx_radar_status { int agc_mb_gain; /*Parsed only for DFS-3*/ int radar_subchan_mask; - RADAR_SUMMARY_VERSION rsu_version; + int rsu_version; /* * The parameters below are present only in * DFS-3 radar summary report and need to be @@ -882,8 +872,23 @@ dfs_process_phyerr_bb_tlv(struct ath_dfs *dfs, void *buf, uint16_t datalen, * Copy the segment ID from the radar summary report * only when radar summary report version is DFS-3. */ - if (rs.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) + if (rs.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) { e->radar_80p80_segid = rs.radar_80p80_segid; + e->delta_peak = rs.delta_peak; + e->delta_diff = rs.delta_diff; + e->agc_total_gain = rs.agc_total_gain; + e->agc_mb_gain = rs.agc_mb_gain; + e->radar_subchan_mask = rs.radar_subchan_mask; + e->pulse_height = rs.pulse_height; + e->triggering_agc_event = rs.triggering_agc_event; + e->pulse_rssi = rs.pulse_rssi; + e->radar_fft_pri80_inband_power = + rs.radar_fft_pri80_inband_power; + e->radar_fft_ext80_inband_power = + rs.radar_fft_ext80_inband_power; + e->rsu_version = rs.rsu_version; + e->peak_mag = rsfr.peak_mag; + } /* * XXX TODO: add a "chirp detection enabled" capability or config * bit somewhere, in case for some reason the hardware chirp diff --git a/core/sap/dfs/src/dfs_process_phyerr.c b/core/sap/dfs/src/dfs_process_phyerr.c index 8725236b08a8..a78b4ef4ad54 100644 --- a/core/sap/dfs/src/dfs_process_phyerr.c +++ b/core/sap/dfs/src/dfs_process_phyerr.c @@ -560,6 +560,9 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, r_fulltsf, &e, enable_log) == 0) { dfs->dfs_phyerr_reject_count++; + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + "%s:Rejected phyerr count after parsing=%d\n", + __func__, dfs->dfs_phyerr_reject_count); return; } else { if (dfs->dfs_phyerr_freq_min > e.freq) @@ -737,6 +740,22 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, event->re_chanindex = dfs->dfs_curchan_radindex; event->re_flags = 0; event->sidx = e.sidx; + if (e.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) { + event->delta_peak = e.delta_peak; + event->delta_diff = e.delta_diff; + event->agc_total_gain = e.agc_total_gain; + event->agc_mb_gain = e.agc_mb_gain; + event->radar_subchan_mask = e.radar_subchan_mask; + event->pulse_height = e.pulse_height; + event->triggering_agc_event = e.triggering_agc_event; + event->pulse_rssi = e.pulse_rssi; + event->radar_fft_pri80_inband_power = + e.radar_fft_pri80_inband_power; + event->radar_fft_ext80_inband_power = + e.radar_fft_ext80_inband_power; + event->rsu_version = e.rsu_version; + event->peak_mag = e.peak_mag; + } /* * Copy the segment ID of the phyerror * from the radar summary report only @@ -825,6 +844,35 @@ dfs_process_phyerr(struct ieee80211com *ic, void *buf, uint16_t datalen, event->re_ts = (e.rs_tstamp) & DFS_TSMASK; event->re_rssi = e.rssi; event->sidx = e.sidx; + if (e.rsu_version == + DFS_RADAR_SUMMARY_REPORT_VERSION_3) { + event->delta_peak = e.delta_peak; + event->delta_diff = e.delta_diff; + event->agc_total_gain = e.agc_total_gain; + event->agc_mb_gain = e.agc_mb_gain; + event->radar_subchan_mask = e.radar_subchan_mask; + event->pulse_height = e.pulse_height; + event->triggering_agc_event = + e.triggering_agc_event; + event->pulse_rssi = e.pulse_rssi; + event->radar_fft_pri80_inband_power = + e.radar_fft_pri80_inband_power; + event->radar_fft_ext80_inband_power = + e.radar_fft_ext80_inband_power; + event->rsu_version = e.rsu_version; + event->phyerr_serial_num = + dfs->dfs_phyerr_queued_count; + event->peak_mag = e.peak_mag; + } + /* + * Copy the segment ID of the phyerror + * from the radar summary report only + * if SAP is operating in 80p80 mode + * and both primary and extension segments + * are DFS. + */ + if (chan->ic_80p80_both_dfs) + event->radar_80p80_segid = e.radar_80p80_segid; /* * Handle chirp flags. diff --git a/core/sap/dfs/src/dfs_process_radarevent.c b/core/sap/dfs/src/dfs_process_radarevent.c index 30392b1b41cc..e77d71178642 100644 --- a/core/sap/dfs/src/dfs_process_radarevent.c +++ b/core/sap/dfs/src/dfs_process_radarevent.c @@ -115,8 +115,6 @@ static inline uint8_t dfs_process_pulse_dur(struct ath_dfs *dfs, uint8_t re_dur) int dfs_process_radarevent(struct ath_dfs *dfs, struct dfs_ieee80211_channel *chan) { -/* commenting for now to validate radar indication msg to SAP */ -/* #if 0 */ struct dfs_event re, *event; struct dfs_state *rs = NULL; struct dfs_filtertype *ft; @@ -129,9 +127,7 @@ int dfs_process_radarevent(struct ath_dfs *dfs, struct dfs_pulseline *pl; static uint32_t diff_ts; int ext_chan_event_flag = 0; -#if 0 - int pri_multiplier = 2; -#endif + int is_hw_chirp = 0; int i; int seg_id = DFS_80P80_SEG0; struct dfs_delayline *dl; @@ -404,11 +400,30 @@ int dfs_process_radarevent(struct ath_dfs *dfs, dfs->radar_log[i].dur = re.re_dur; dfs->dfs_event_log_count++; } - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, - "%s[%d]:xxxxx ts =%u re.re_dur=%u re.re_rssi =%u diff =%u pl->pl_lastelem.p_time=%llu xxxxx", - __func__, __LINE__, (uint32_t) this_ts, re.re_dur, - re.re_rssi, diff_ts, - (unsigned long long)pl->pl_elems[index].p_time); + if (re.rsu_version == DFS_RADAR_SUMMARY_REPORT_VERSION_3) { + if ((re.re_flags & DFS_EVENT_HW_CHIRP) == + DFS_EVENT_HW_CHIRP) + is_hw_chirp = 1; + + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + "\n %s[%d]:PHYERR# = %d ts = %u diff_ts = %u ppdu_rssi = %u dur = %u is_hw_chirp = %d segid = %d sidx = %d peak_mag = %d delta_peak = %d delta_diff = %d agc_total_gain = %d agc_mb_gain = %d radar_subchan_mask = 0x%x pulse_height = %d triggering_agc_event = %d rs_pulse_rssi = %d pri80_inband_power = %d ext80_inband_power = %d \n", + __func__, __LINE__, + re.phyerr_serial_num, (uint32_t) this_ts, + diff_ts, re.re_rssi, re.re_dur, is_hw_chirp, + re.radar_80p80_segid, re.sidx, re.peak_mag, + re.delta_peak, re.delta_diff, + re.agc_total_gain, re.agc_mb_gain, + re.radar_subchan_mask, re.pulse_height, + re.triggering_agc_event, re.pulse_rssi, + re.radar_fft_pri80_inband_power, + re.radar_fft_ext80_inband_power); + } else { + QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, + "%s[%d]:xxxxx ts =%u re.re_dur=%u re.re_rssi =%u diff =%u pl->pl_lastelem.p_time=%llu xxxxx", + __func__, __LINE__, (uint32_t) this_ts, re.re_dur, + re.re_rssi, diff_ts, + (unsigned long long)pl->pl_elems[index].p_time); + } /* If diff_ts is very small, we might be getting false pulse detects * due to heavy interference. We might be getting spectral splatter diff --git a/core/sap/src/sap_api_link_cntl.c b/core/sap/src/sap_api_link_cntl.c index 78b71b4b0c3e..7d76f9cd3cf1 100644 --- a/core/sap/src/sap_api_link_cntl.c +++ b/core/sap/src/sap_api_link_cntl.c @@ -507,128 +507,6 @@ wlansap_roam_process_ch_change_success(tpAniSirGlobal mac_ctx, } /** - * wlansap_set_hw_mode_on_channel_switch() - Set hw mode before channel switch - * @sap_ctx: Global SAP context - * @target_channel: Target channel - * - * Sets hw mode, if needed, before doing a channel switch - * - * Return: None - */ -static QDF_STATUS wlansap_set_hw_mode_on_channel_switch(tpAniSirGlobal mac_ctx, - ptSapContext sap_ctx, - uint32_t target_channel) -{ - QDF_STATUS status = QDF_STATUS_E_FAILURE, qdf_status; - cds_context_type *cds_ctx; - enum cds_conc_next_action action; - - cds_ctx = cds_get_context(QDF_MODULE_ID_QDF); - if (!cds_ctx) { - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, - FL("Invalid CDS Context")); - return status; - } - - qdf_mutex_acquire(&cds_ctx->qdf_conc_list_lock); - - action = cds_get_pref_hw_mode_for_chan(sap_ctx->sessionId, - target_channel); - - if ((action != CDS_DBS_DOWNGRADE) && (action != CDS_MCC_UPGRADE)) { - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, - FL("Invalid action: %d"), action); - goto done; - } - - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, - FL("action:%d session id:%d"), - action, sap_ctx->sessionId); - - /* For MCC, opportunistic timer will be trigerred. We do not - * want to do hw mode change here to avoid the ping pong effect. - * e.g., If a new connection is immediately coming up, we could be - * moving in and out of MCC. The timer after DBS_OPPORTUNISTIC_TIME - * seconds will check if the driver can move to MCC or not. - * - * 1. Start opportunistic timer - * 2. Do vdev restart on the new channel - * 3. PM will check if MCC upgrade can be done after timer expiry - */ - if (action == CDS_MCC_UPGRADE) { - qdf_mc_timer_stop(&cds_ctx->dbs_opportunistic_timer); - qdf_status = qdf_mc_timer_start( - &cds_ctx->dbs_opportunistic_timer, - DBS_OPPORTUNISTIC_TIME * - 1000); - if (!QDF_IS_STATUS_SUCCESS(qdf_status)) - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, - FL("Failed to start dbs opportunistic timer")); - else - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_DEBUG, - FL("opportunistic timer for MCC upgrade")); - goto done; - } - - /* For DBS, we want to move right away to DBS mode. Else, we could - * be doing MCC momentarily. - * - * 1. PM will initiate HW mode change to DBS rightaway - * 2. Do vdev restart on the new channel - */ - status = cds_next_actions(sap_ctx->sessionId, action, - SIR_UPDATE_REASON_CHANNEL_SWITCH); - if (!QDF_IS_STATUS_SUCCESS(status)) { - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_ERROR, - FL("no set hw mode command was issued")); - goto done; - } -done: - qdf_mutex_release(&cds_ctx->qdf_conc_list_lock); - /* success must be returned only when a set hw mode was done */ - return status; -} - -/** - * wlansap_update_hw_mode() - Set the hw mode for the new channel switch - * @hal: HAL pointer - * @sap_ctx: SAP context - * - * Sets the hw mode, if needed, for the driver based on the new channel - * to which the vdev is going to switch to - * - * Return: None - */ -void wlansap_update_hw_mode(tHalHandle hal, ptSapContext sap_ctx) -{ - QDF_STATUS status = QDF_STATUS_E_FAILURE; - tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); - tCsrRoamInfo roam_info = {0}; - - if (mac_ctx->policy_manager_enabled && - wma_is_hw_dbs_capable() == true) { - status = wlansap_set_hw_mode_on_channel_switch(mac_ctx, sap_ctx, - mac_ctx->sap.SapDfsInfo.target_channel); - } - - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO, - FL("status:%d"), status); - - /* - * If no set hw mode was done, proceed as before by doing set channel. - * If set hw mode was done, perform the following in the callback so - * that the set channel operations are done after the driver moves to - * the required hw mode. - */ - if (!QDF_IS_STATUS_SUCCESS(status)) { - csr_roam_call_callback(mac_ctx, sap_ctx->sessionId, - &roam_info, 0, - eCSR_ROAM_STATUS_UPDATE_HW_MODE, - eCSR_ROAM_RESULT_UPDATE_HW_MODE); - } -} - -/** * wlansap_roam_process_dfs_chansw_update() - handles the case for * eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS in wlansap_roam_callback() * @@ -1097,10 +975,6 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH, FL("Received Chan Sw Update Notification")); break; - case eCSR_ROAM_STATUS_UPDATE_HW_MODE: - QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH, - FL("Received HW mode update notification")); - break; case eCSR_ROAM_SET_CHANNEL_RSP: QDF_TRACE(QDF_MODULE_ID_SAP, QDF_TRACE_LEVEL_INFO_HIGH, FL("Received set channel response")); @@ -1316,26 +1190,8 @@ wlansap_roam_callback(void *ctx, tCsrRoamInfo *csr_roam_info, uint32_t roamId, &qdf_ret_status); break; case eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS: - /* eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS indicates the - * completion of sending (E)CSA IEs. After these IEs are sent, - * in eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS state, check - * for DBS downgrade/MCC upgrade is done. - * (1) From this state - * eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS, on MCC upgrade, - * transition immediately happens to the state - * eCSR_ROAM_RESULT_UPDATE_HW_MODE, where the vdev restart - * happens internally. - * (2) From this state, - * eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS, on DBS downgrade, - * transition happens to the state - * eCSR_ROAM_RESULT_UPDATE_HW_MODE to do vdev restart only after - * SME received the set HW mode response. - */ - wlansap_update_hw_mode(hal, sap_ctx); - break; - case eCSR_ROAM_RESULT_UPDATE_HW_MODE: wlansap_roam_process_dfs_chansw_update(hal, sap_ctx, - &qdf_ret_status); + &qdf_ret_status); break; case eCSR_ROAM_RESULT_CHANNEL_CHANGE_SUCCESS: wlansap_roam_process_ch_change_success(mac_ctx, sap_ctx, diff --git a/core/sme/inc/csr_api.h b/core/sme/inc/csr_api.h index ae0c98749e4f..802afc321f1d 100644 --- a/core/sme/inc/csr_api.h +++ b/core/sme/inc/csr_api.h @@ -270,7 +270,12 @@ typedef struct tagCsrScanRequest { tCsrChannelInfo ChannelInfo; uint32_t minChnTime; /* in units of milliseconds */ uint32_t maxChnTime; /* in units of milliseconds */ - uint32_t restTime; /* in units of milliseconds */ + /* In units of milliseconds, ignored when not connected */ + uint32_t restTime; + /* In units of milliseconds, ignored when not connected */ + uint32_t min_rest_time; + /* In units of milliseconds, ignored when not connected */ + uint32_t idle_time; uint32_t uIEFieldLen; uint8_t *pIEField; eCsrRequestType requestType; /* 11d scan or full scan */ @@ -492,9 +497,9 @@ typedef enum { /* Channel sw update notification */ eCSR_ROAM_DFS_CHAN_SW_NOTIFY, eCSR_ROAM_EXT_CHG_CHNL_IND, - eCSR_ROAM_STATUS_UPDATE_HW_MODE, eCSR_ROAM_DISABLE_QUEUES, eCSR_ROAM_ENABLE_QUEUES, + eCSR_ROAM_STA_CHANNEL_SWITCH, } eRoamCmdStatus; /* comment inside indicates what roaming callback gets */ @@ -591,7 +596,6 @@ typedef enum { eCSR_ROAM_RESULT_CHANNEL_CHANGE_FAILURE, eCSR_ROAM_RESULT_DFS_CHANSW_UPDATE_SUCCESS, eCSR_ROAM_EXT_CHG_CHNL_UPDATE_IND, - eCSR_ROAM_RESULT_UPDATE_HW_MODE, } eCsrRoamResult; /*---------------------------------------------------------------------------- @@ -940,7 +944,6 @@ typedef struct tagCsrRoamHTProfile { uint8_t htRecommendedTxWidthSet; ePhyChanBondState htSecondaryChannelOffset; uint8_t vhtCapability; - uint8_t vhtTxChannelWidthSet; uint8_t apCenterChan; uint8_t apChanWidth; } tCsrRoamHTProfile; @@ -1096,6 +1099,11 @@ typedef struct tagCsrConfigParam { /* number of channels combined for P2P in each split scan operation */ uint8_t nNumP2PChanCombinedConc; #endif + /*In units of milliseconds*/ + uint32_t min_rest_time_conc; + /*In units of milliseconds*/ + uint32_t idle_time_conc; + /* * in dBm, the maximum TX power The actual TX power is the lesser of * this value and 11d. If 11d is disable, the lesser of this and @@ -1222,6 +1230,7 @@ typedef struct tagCsrConfigParam { uint32_t obss_active_dwelltime; uint32_t obss_passive_dwelltime; bool ignore_peer_ht_opmode; + bool enable_fatal_event; } tCsrConfigParam; /* Tush */ diff --git a/core/sme/inc/csr_internal.h b/core/sme/inc/csr_internal.h index 15ce478fd687..17c806f2c585 100644 --- a/core/sme/inc/csr_internal.h +++ b/core/sme/inc/csr_internal.h @@ -283,7 +283,12 @@ typedef struct tagCsrChannel { typedef struct tagScanProfile { uint32_t minChnTime; uint32_t maxChnTime; - uint32_t restTime; /* This is ignored if not associated */ + /* In units of milliseconds, ignored when not connected */ + uint32_t restTime; + /* In units of milliseconds, ignored when not connected */ + uint32_t min_rest_time; + /* In units of milliseconds, ignored when not connected */ + uint32_t idle_time; uint32_t numOfChannels; uint8_t *pChannelList; tSirScanType scanType; @@ -545,6 +550,11 @@ typedef struct tagCsrConfig { uint32_t nActiveMinChnTimeConc; /* in units of milliseconds */ uint32_t nActiveMaxChnTimeConc; /* in units of milliseconds */ uint32_t nRestTimeConc; /* in units of milliseconds */ + /* In units of milliseconds */ + uint32_t min_rest_time_conc; + /* In units of milliseconds */ + uint32_t idle_time_conc; + /* number of channels combined for Sta in each split scan operation */ uint8_t nNumStaChanCombinedConc; /* number of channels combined for P2P in each split scan operation */ @@ -639,6 +649,7 @@ typedef struct tagCsrConfig { uint32_t obss_active_dwelltime; uint32_t obss_passive_dwelltime; bool ignore_peer_ht_opmode; + bool enable_fatal_event; } tCsrConfig; typedef struct tagCsrChannelPowerInfo { diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index d836a36a0389..7b74226e7fde 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -988,7 +988,7 @@ bool sme_is_any_session_in_connected_state(tHalHandle h_hal); QDF_STATUS sme_pdev_set_pcl(tHalHandle hal, struct sir_pcl_list msg); -QDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, +QDF_STATUS sme_pdev_set_hw_mode(tHalHandle hal, struct sir_hw_mode msg); void sme_register_hw_mode_trans_cb(tHalHandle hal, hw_mode_transition_cb callback); @@ -1096,6 +1096,17 @@ static inline QDF_STATUS sme_send_egap_conf_params(uint32_t enable, void sme_update_fine_time_measurement_capab(tHalHandle hal, uint32_t val); QDF_STATUS sme_ht40_stop_obss_scan(tHalHandle hHal, uint32_t vdev_id); +QDF_STATUS sme_set_tsfcb(tHalHandle hHal, + int (*cb_fn)(void *cb_ctx, struct stsf *ptsf), void *cb_ctx); + +#ifdef WLAN_FEATURE_TSF +QDF_STATUS sme_set_tsf_gpio(tHalHandle h_hal, uint32_t pinvalue); +#else +static inline QDF_STATUS sme_set_tsf_gpio(tHalHandle h_hal, uint32_t pinvalue) +{ + return QDF_STATUS_E_FAILURE; +} +#endif QDF_STATUS sme_update_mimo_power_save(tHalHandle hHal, uint8_t is_ht_smps_enabled, @@ -1106,4 +1117,13 @@ bool sme_is_sta_smps_allowed(tHalHandle hHal, uint8_t session_id); QDF_STATUS sme_add_beacon_filter(tHalHandle hal, uint32_t session_id, uint32_t *ie_map); QDF_STATUS sme_remove_beacon_filter(tHalHandle hal, uint32_t session_id); +QDF_STATUS sme_bpf_offload_register_callback(tHalHandle hal, + void (*pbpf_get_offload_cb)(void *, + struct sir_bpf_get_offload *)); + +QDF_STATUS sme_get_bpf_offload_capabilities(tHalHandle hal); +QDF_STATUS sme_set_bpf_instructions(tHalHandle hal, + struct sir_bpf_set_offload *); + +QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, uint8_t *bssid); #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/inc/sme_internal.h b/core/sme/inc/sme_internal.h index 9e27ba2d2307..6414ae8a243e 100644 --- a/core/sme/inc/sme_internal.h +++ b/core/sme/inc/sme_internal.h @@ -197,6 +197,8 @@ typedef struct tagSmeStruct { bool enableSelfRecovery; tCsrLinkStatusCallback linkStatusCallback; void *linkStatusContext; + int (*get_tsf_cb)(void *pcb_cxt, struct stsf *ptsf); + void *get_tsf_cxt; /* get temperature event context and callback */ void *pTemperatureCbContext; void (*pGetTemperatureCb)(int temperature, void *context); @@ -232,7 +234,8 @@ typedef struct tagSmeStruct { ocb_callback dcc_stats_event_callback; sme_set_thermal_level_callback set_thermal_level_cb; void *saved_scan_cmd; - struct csa_offload_params saved_csa_params; + void (*pbpf_get_offload_cb)(void *context, + struct sir_bpf_get_offload *); } tSmeStruct, *tpSmeStruct; #endif /* #if !defined( __SMEINTERNAL_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index c12aef820c50..03a9ee6bcad4 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -155,8 +155,6 @@ static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) struct sir_set_hw_mode_resp *param; enum sir_conn_update_reason reason; tSmeCmd *saved_cmd; - tCsrRoamInfo roam_info = {0}; - QDF_STATUS status; sms_log(mac, LOG1, FL("%s"), __func__); param = (struct sir_set_hw_mode_resp *)msg; @@ -251,34 +249,6 @@ static QDF_STATUS sme_process_set_hw_mode_resp(tpAniSirGlobal mac, uint8_t *msg) saved_cmd = NULL; mac->sme.saved_scan_cmd = NULL; } - } else if (reason == SIR_UPDATE_REASON_CHANNEL_SWITCH) { - csr_roam_call_callback(mac, - command->u.set_hw_mode_cmd.session_id, - &roam_info, 0, - eCSR_ROAM_STATUS_UPDATE_HW_MODE, - eCSR_ROAM_RESULT_UPDATE_HW_MODE); - } else if (reason == SIR_UPDATE_REASON_CHANNEL_SWITCH_STA) { - struct sir_saved_csa_params *msg; - - sms_log(mac, LOG1, FL("process channel switch sta")); - msg = qdf_mem_malloc(sizeof(*msg)); - if (!msg) { - sms_log(mac, LOGE, - FL("memory alloc fail for csa ")); - goto end; - } - - msg->message_type = SIR_LIM_CSA_POST_HW_MODE_CHANGE; - msg->length = sizeof(*msg); - msg->session_id = command->u.set_hw_mode_cmd.session_id; - - status = cds_send_mb_message_to_mac(msg); - if (!QDF_IS_STATUS_SUCCESS(status)) - sms_log(mac, LOGE, - FL("failed to process csa params")); - else - sms_log(mac, LOG1, - FL("csa after hw mode change")); } end: @@ -651,8 +621,16 @@ tSmeCmd *sme_get_command_buffer(tpAniSirGlobal pMac) sme_command_queue_full++; csr_ll_unlock(&pMac->roam.roamCmdPendingList); - /* panic with out-of-command */ - QDF_BUG(0); + if (pMac->roam.configParam.enable_fatal_event) + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_SME_OUT_OF_CMD_BUF, + false, + pMac->sme.enableSelfRecovery ? true : false); + else if (pMac->sme.enableSelfRecovery) + cds_trigger_recovery(); + else + QDF_BUG(0); } /* memset to zero */ @@ -2805,6 +2783,14 @@ QDF_STATUS sme_process_msg(tHalHandle hHal, cds_msg_t *pMsg) qdf_mem_free(pMsg->bodyptr); } break; + case eWNI_SME_TSF_EVENT: + if (pMac->sme.get_tsf_cb) { + pMac->sme.get_tsf_cb(pMac->sme.get_tsf_cxt, + (struct stsf *)pMsg->bodyptr); + } + if (pMsg->bodyptr) + qdf_mem_free(pMsg->bodyptr); + break; #ifdef WLAN_FEATURE_NAN case eWNI_SME_NAN_EVENT: if (pMsg->bodyptr) { @@ -7300,6 +7286,60 @@ QDF_STATUS sme_preferred_network_found_ind(tHalHandle hHal, void *pMsg) #endif /* FEATURE_WLAN_SCAN_PNO */ +/* + * sme_set_tsfcb() - Set callback for TSF capture + * @h_hal: Handler return by mac_open + * @cb_fn: Callback function pointer + * @db_ctx: Callback data + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_set_tsfcb(tHalHandle h_hal, + int (*cb_fn)(void *cb_ctx, struct stsf *ptsf), void *cb_ctx) +{ + tpAniSirGlobal mac = PMAC_STRUCT(h_hal); + QDF_STATUS status; + + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + mac->sme.get_tsf_cb = cb_fn; + mac->sme.get_tsf_cxt = cb_ctx; + sme_release_global_lock(&mac->sme); + } + return status; +} + +#ifdef WLAN_FEATURE_TSF +/* + * sme_set_tsf_gpio() - set gpio pin that be toggled when capture tef + * @h_hal: Handler return by mac_open + * @pinvalue: gpio pin id + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_set_tsf_gpio(tHalHandle h_hal, uint32_t pinvalue) +{ + QDF_STATUS status; + cds_msg_t tsf_msg = {0}; + tpAniSirGlobal mac = PMAC_STRUCT(h_hal); + + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + tsf_msg.type = WMA_TSF_GPIO_PIN; + tsf_msg.reserved = 0; + tsf_msg.bodyval = pinvalue; + + status = cds_mq_post_message(CDS_MQ_ID_WMA, &tsf_msg); + if (!QDF_IS_STATUS_SUCCESS(status)) { + sms_log(mac, LOGE, "Unable to post WMA_TSF_GPIO_PIN"); + status = QDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac->sme); + } + return status; +} +#endif + QDF_STATUS sme_get_cfg_valid_channels(tHalHandle hHal, uint8_t *aValidChannels, uint32_t *len) { @@ -11650,19 +11690,41 @@ void sme_save_active_cmd_stats(tHalHandle hHal) void active_list_cmd_timeout_handle(void *userData) { - if (NULL == userData) - return; - QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, - "%s: Active List command timeout Cmd List Count %d", __func__, - csr_ll_count(&((tpAniSirGlobal) userData)->sme. - smeCmdActiveList)); - sme_get_command_q_status((tHalHandle) userData); + tHalHandle hal = (tHalHandle)userData; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); - if (((tpAniSirGlobal) userData)->sme.enableSelfRecovery) { - sme_save_active_cmd_stats((tHalHandle) userData); + if (NULL == mac_ctx) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + "%s: mac_ctx is null", __func__); + return; + } + /* Return if no cmd pending in active list as + * in this case we should not be here. + */ + if (0 == csr_ll_count(&mac_ctx->sme.smeCmdActiveList)) + return; + sms_log(mac_ctx, LOGE, + FL("Active List command timeout Cmd List Count %d"), + csr_ll_count(&mac_ctx->sme.smeCmdActiveList)); + sme_get_command_q_status(hal); + + if (mac_ctx->roam.configParam.enable_fatal_event) + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_SME_COMMAND_STUCK, + false, + mac_ctx->sme.enableSelfRecovery ? true : false); + else + qdf_trace_dump_all(mac_ctx, 0, 0, 500, 0); + + if (mac_ctx->sme.enableSelfRecovery) { + sme_save_active_cmd_stats(hal); cds_trigger_recovery(); } else { - QDF_BUG(0); + if (!mac_ctx->roam.configParam.enable_fatal_event && + !(cds_is_load_or_unload_in_progress() || + cds_is_driver_recovering())) + QDF_BUG(0); } } @@ -14383,7 +14445,7 @@ QDF_STATUS sme_wifi_start_logger(tHalHandle hal, status = cds_mq_post_message(CDS_MQ_ID_WMA, &cds_message); if (!QDF_IS_STATUS_SUCCESS(status)) { sms_log(mac, LOGE, - FL("vos_mq_post_message failed!(err=%d)"), + FL("cds_mq_post_message failed!(err=%d)"), status); qdf_mem_free(req_msg); status = QDF_STATUS_E_FAILURE; @@ -14856,14 +14918,14 @@ QDF_STATUS sme_pdev_set_pcl(tHalHandle hal, } /* - * sme_soc_set_hw_mode() - Send WMI_SOC_SET_HW_MODE_CMDID to the WMA + * sme_pdev_set_hw_mode() - Send WMI_PDEV_SET_HW_MODE_CMDID to the WMA * @hal: Handle returned by macOpen * @msg: HW mode structure containing hw mode and callback details * - * Sends the command to CSR to send WMI_SOC_SET_HW_MODE_CMDID to FW + * Sends the command to CSR to send WMI_PDEV_SET_HW_MODE_CMDID to FW * Return: QDF_STATUS_SUCCESS on successful posting */ -QDF_STATUS sme_soc_set_hw_mode(tHalHandle hal, +QDF_STATUS sme_pdev_set_hw_mode(tHalHandle hal, struct sir_hw_mode msg) { QDF_STATUS status = QDF_STATUS_SUCCESS; @@ -15567,3 +15629,150 @@ QDF_STATUS sme_remove_beacon_filter(tHalHandle hal, uint32_t session_id) } return qdf_status; } + +/** + * sme_get_bpf_offload_capabilities() - Get length for BPF offload + * @hal: Global HAL handle + * This function constructs the cds message and fill in message type, + * post the same to WDA. + * Return: QDF_STATUS enumeration + */ +QDF_STATUS sme_get_bpf_offload_capabilities(tHalHandle hal) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + cds_msg_t cds_msg; + + sms_log(mac_ctx, LOG1, FL("enter")); + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_STATUS_SUCCESS == status) { + /* Serialize the req through MC thread */ + cds_msg.bodyptr = NULL; + cds_msg.type = WDA_BPF_GET_CAPABILITIES_REQ; + status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg); + if (!QDF_IS_STATUS_SUCCESS(status)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("Post bpf get offload msg fail")); + status = QDF_STATUS_E_FAILURE; + } + sme_release_global_lock(&mac_ctx->sme); + } else { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock error")); + } + sms_log(mac_ctx, LOG1, FL("exit")); + return status; +} + + +/** + * sme_set_bpf_instructions() - Set BPF bpf filter instructions. + * @hal: HAL handle + * @bpf_set_offload: struct to set bpf filter instructions. + * + * Return: QDF_STATUS enumeration. + */ +QDF_STATUS sme_set_bpf_instructions(tHalHandle hal, + struct sir_bpf_set_offload *req) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + cds_msg_t cds_msg; + struct sir_bpf_set_offload *set_offload; + + set_offload = qdf_mem_malloc(sizeof(*set_offload)); + + if (NULL == set_offload) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("Failed to alloc set_offload")); + return QDF_STATUS_E_NOMEM; + } + + set_offload->session_id = req->session_id; + set_offload->filter_id = req->filter_id; + set_offload->current_offset = req->current_offset; + set_offload->total_length = req->total_length; + if (set_offload->total_length) { + set_offload->current_length = req->current_length; + set_offload->program = qdf_mem_malloc(sizeof(uint8_t) * + req->current_length); + qdf_mem_copy(set_offload->program, req->program, + set_offload->current_length); + } + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_STATUS_SUCCESS == status) { + /* Serialize the req through MC thread */ + cds_msg.bodyptr = set_offload; + cds_msg.type = WDA_BPF_SET_INSTRUCTIONS_REQ; + status = cds_mq_post_message(QDF_MODULE_ID_WMA, &cds_msg); + + if (!QDF_IS_STATUS_SUCCESS(status)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("Post BPF set offload msg fail")); + status = QDF_STATUS_E_FAILURE; + if (set_offload->total_length) + qdf_mem_free(set_offload->program); + qdf_mem_free(set_offload); + } + sme_release_global_lock(&mac_ctx->sme); + } else { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock failed")); + if (set_offload->total_length) + qdf_mem_free(set_offload->program); + qdf_mem_free(set_offload); + } + return status; +} + +/** + * sme_bpf_offload_register_callback() - Register get bpf offload callbacK + * + * @hal - MAC global handle + * @callback_routine - callback routine from HDD + * + * This API is invoked by HDD to register its callback in SME + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_bpf_offload_register_callback(tHalHandle hal, + void (*pbpf_get_offload_cb)(void *context, + struct sir_bpf_get_offload *)) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac = PMAC_STRUCT(hal); + + status = sme_acquire_global_lock(&mac->sme); + if (QDF_IS_STATUS_SUCCESS(status)) { + mac->sme.pbpf_get_offload_cb = pbpf_get_offload_cb; + sme_release_global_lock(&mac->sme); + } else { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock failed")); + } + return status; +} + +/** + * sme_create_mon_session() - post message to create PE session for monitormode + * operation + * @hal_handle: Handle to the HAL + * @bssid: pointer to bssid + * + * Return: QDF_STATUS_SUCCESS on success, non-zero error code on failure. + */ +QDF_STATUS sme_create_mon_session(tHalHandle hal_handle, tSirMacAddr bss_id) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + struct sir_create_session *msg; + + msg = qdf_mem_malloc(sizeof(*msg)); + if (NULL != msg) { + msg->type = eWNI_SME_MON_INIT_SESSION; + msg->msg_len = sizeof(*msg); + qdf_mem_copy(msg->bss_id.bytes, bss_id, QDF_MAC_ADDR_SIZE); + status = cds_send_mb_message_to_mac(msg); + } + return status; +} diff --git a/core/sme/src/csr/csr_api_roam.c b/core/sme/src/csr/csr_api_roam.c index ee72ae9a44c9..0326f313a30c 100644 --- a/core/sme/src/csr/csr_api_roam.c +++ b/core/sme/src/csr/csr_api_roam.c @@ -1292,6 +1292,8 @@ static void init_config_param(tpAniSirGlobal pMac) pMac->roam.configParam.nPassiveMinChnTimeConc = CSR_PASSIVE_MIN_CHANNEL_TIME_CONC; pMac->roam.configParam.nRestTimeConc = CSR_REST_TIME_CONC; + pMac->roam.configParam.min_rest_time_conc = CSR_MIN_REST_TIME_CONC; + pMac->roam.configParam.idle_time_conc = CSR_IDLE_TIME_CONC; pMac->roam.configParam.nNumStaChanCombinedConc = CSR_NUM_STA_CHAN_COMBINED_CONC; pMac->roam.configParam.nNumP2PChanCombinedConc = @@ -2057,10 +2059,11 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pMac->roam.configParam.nPassiveMinChnTimeConc = pParam->nPassiveMinChnTimeConc; } - if (pParam->nRestTimeConc) { - pMac->roam.configParam.nRestTimeConc = - pParam->nRestTimeConc; - } + pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc; + pMac->roam.configParam.min_rest_time_conc = + pParam->min_rest_time_conc; + pMac->roam.configParam.idle_time_conc = pParam->idle_time_conc; + if (pParam->nNumStaChanCombinedConc) { pMac->roam.configParam.nNumStaChanCombinedConc = pParam->nNumStaChanCombinedConc; @@ -2353,6 +2356,8 @@ QDF_STATUS csr_change_default_config_param(tpAniSirGlobal pMac, pParam->early_stop_scan_min_threshold; pMac->roam.configParam.early_stop_scan_max_threshold = pParam->early_stop_scan_max_threshold; + pMac->roam.configParam.enable_fatal_event = + pParam->enable_fatal_event; } return status; @@ -2398,6 +2403,8 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->nPassiveMaxChnTimeConc = cfg_params->nPassiveMaxChnTimeConc; pParam->nPassiveMinChnTimeConc = cfg_params->nPassiveMinChnTimeConc; pParam->nRestTimeConc = cfg_params->nRestTimeConc; + pParam->min_rest_time_conc = cfg_params->min_rest_time_conc; + pParam->idle_time_conc = cfg_params->idle_time_conc; pParam->nNumStaChanCombinedConc = cfg_params->nNumStaChanCombinedConc; pParam->nNumP2PChanCombinedConc = cfg_params->nNumP2PChanCombinedConc; #endif @@ -2536,6 +2543,8 @@ QDF_STATUS csr_get_config_param(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->enableHtSmps = pMac->roam.configParam.enableHtSmps; pParam->htSmps = pMac->roam.configParam.htSmps; pParam->send_smps_action = pMac->roam.configParam.send_smps_action; + pParam->enable_fatal_event = + pMac->roam.configParam.enable_fatal_event; return QDF_STATUS_SUCCESS; } @@ -5942,7 +5951,6 @@ static void csr_roam_copy_ht_profile(tCsrRoamHTProfile *dst_profile, dst_profile->htSecondaryChannelOffset = src_profile->htSecondaryChannelOffset; dst_profile->vhtCapability = src_profile->vhtCapability; - dst_profile->vhtTxChannelWidthSet = src_profile->vhtTxChannelWidthSet; dst_profile->apCenterChan = src_profile->apCenterChan; dst_profile->apChanWidth = src_profile->apChanWidth; } @@ -8672,6 +8680,10 @@ static void csr_roam_roaming_state_reassoc_rsp_processor(tpAniSirGlobal pMac, "CSR SmeReassocReq failed with statusCode= 0x%08X [%d]", pSmeJoinRsp->statusCode, pSmeJoinRsp->statusCode); result = eCsrReassocFailure; + cds_flush_logs(WLAN_LOG_TYPE_FATAL, + WLAN_LOG_INDICATOR_HOST_DRIVER, + WLAN_LOG_REASON_ROAM_FAIL, + true, false); if ((eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE == pSmeJoinRsp->statusCode) || (eSIR_SME_FT_REASSOC_FAILURE == @@ -10250,6 +10262,7 @@ csr_roam_chk_lnk_swt_ch_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) uint32_t sessionId = CSR_SESSION_ID_INVALID; QDF_STATUS status; tpSirSmeSwitchChannelInd pSwitchChnInd; + tCsrRoamInfo roamInfo; /* in case of STA, the SWITCH_CHANNEL originates from its AP */ sms_log(mac_ctx, LOGW, FL("eWNI_SME_SWITCH_CHL_IND from SME")); @@ -10272,6 +10285,12 @@ csr_roam_chk_lnk_swt_ch_ind(tpAniSirGlobal mac_ctx, tSirSmeRsp *msg_ptr) session->pConnectBssDesc->channelId = (uint8_t) pSwitchChnInd->newChannelId; } + + qdf_mem_set(&roamInfo, sizeof(tCsrRoamInfo), 0); + roamInfo.chan_info.chan_id = pSwitchChnInd->newChannelId; + status = csr_roam_call_callback(mac_ctx, sessionId, + &roamInfo, 0, eCSR_ROAM_STA_CHANNEL_SWITCH, + eCSR_ROAM_RESULT_NONE); } } @@ -18709,6 +18728,7 @@ void csr_roam_synch_callback(tpAniSirGlobal mac_ctx, struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BROADCAST_INITIALIZER; tpAddBssParams add_bss_params; QDF_STATUS status = QDF_STATUS_SUCCESS; + uint16_t len; #ifdef FEATURE_WLAN_MCC_TO_SCC_SWITCH tSirSmeHTProfile *src_profile = NULL; tCsrRoamHTProfile *dst_profile = NULL; @@ -18869,6 +18889,19 @@ void csr_roam_synch_callback(tpAniSirGlobal mac_ctx, FL("LFR3:Clear Connected info")); csr_roam_free_connected_info(mac_ctx, &session->connectedInfo); + len = roam_synch_data->join_rsp->parsedRicRspLen; + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_DEBUG, + FL("LFR3: RIC length - %d"), len); + if (len) { + session->connectedInfo.pbFrames = + qdf_mem_malloc(len); + if (session->connectedInfo.pbFrames != NULL) { + qdf_mem_copy(session->connectedInfo.pbFrames, + roam_synch_data->join_rsp->frames, len); + session->connectedInfo.nRICRspLength = + roam_synch_data->join_rsp->parsedRicRspLen; + } + } conn_profile->vht_channel_width = roam_synch_data->join_rsp->vht_channel_width; add_bss_params = (tpAddBssParams)roam_synch_data->add_bss_params; diff --git a/core/sme/src/csr/csr_api_scan.c b/core/sme/src/csr/csr_api_scan.c index 87ceec5baa58..c337db354395 100644 --- a/core/sme/src/csr/csr_api_scan.c +++ b/core/sme/src/csr/csr_api_scan.c @@ -256,6 +256,11 @@ static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanTy } pScanRequest->restTime = pMac->roam.configParam.nRestTimeConc; + pScanRequest->min_rest_time = + pMac->roam.configParam.min_rest_time_conc; + pScanRequest->idle_time = + pMac->roam.configParam.idle_time_conc; + /* Return so that fields set above will not be overwritten. */ return; } @@ -278,8 +283,12 @@ static void csr_set_default_scan_timing(tpAniSirGlobal pMac, tSirScanType scanTy pMac->roam.configParam.nPassiveMinChnTime; } #ifdef WLAN_AP_STA_CONCURRENCY - /* No rest time if no sessions are connected. */ + + /* No rest time/Idle time if no sessions are connected. */ pScanRequest->restTime = 0; + pScanRequest->min_rest_time = 0; + pScanRequest->idle_time = 0; + #endif } @@ -546,9 +555,14 @@ QDF_STATUS csr_scan_request(tpAniSirGlobal pMac, uint16_t sessionId, scan_req->minChnTime, scan_req->maxChnTime); } #ifdef WLAN_AP_STA_CONCURRENCY - /* Need to set restTime only if at least one session is connected */ + /* + * Need to set restTime/min_Ret_time/idle_time + * only if at least one session is connected + */ if (scan_req->restTime == 0 && csr_is_any_session_connected(pMac)) { scan_req->restTime = cfg_prm->nRestTimeConc; + scan_req->min_rest_time = cfg_prm->min_rest_time_conc; + scan_req->idle_time = cfg_prm->idle_time_conc; if (scan_req->scanType == eSIR_ACTIVE_SCAN) { scan_req->maxChnTime = cfg_prm->nActiveMaxChnTimeConc; scan_req->minChnTime = cfg_prm->nActiveMinChnTimeConc; @@ -2916,8 +2930,8 @@ static void csr_move_temp_scan_results_to_main_list(tpAniSirGlobal pMac, return; } } - csr_elected_country_info(pMac); - csr_learn_11dcountry_information(pMac, NULL, NULL, true); + if (csr_elected_country_info(pMac)) + csr_learn_11dcountry_information(pMac, NULL, NULL, true); } static tCsrScanResult *csr_scan_save_bss_description(tpAniSirGlobal pMac, @@ -3313,6 +3327,8 @@ bool csr_elected_country_info(tpAniSirGlobal pMac) uint8_t i, j = 0; if (!pMac->scan.countryCodeCount) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_WARN, + "No AP with 11d Country code is present in scan list"); return fRet; } maxVotes = pMac->scan.votes11d[0].votes; @@ -4162,6 +4178,11 @@ bool csr_scan_complete(tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp) pCommand->u.scanCmd.abortScanDueToBandChange = false; } csr_save_scan_results(pMac, pCommand->u.scanCmd.reason, sessionId); + /* filter scan result based on valid channel list number */ + if (pMac->scan.fcc_constraint) { + sms_log(pMac, LOG1, FL("Clear BSS from invalid channels")); + csr_scan_filter_results(pMac); + } #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR csr_diag_scan_complete(pMac, pCommand, pScanRsp); #endif /* #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR */ @@ -4984,8 +5005,12 @@ QDF_STATUS csr_send_mb_scan_req(tpAniSirGlobal pMac, uint16_t sessionId, pMsg->maxChannelTime = maxChnTime; /* hidden SSID option */ pMsg->hiddenSsid = pScanReqParam->hiddenSsid; - /* rest time */ + /* maximum rest time */ pMsg->restTime = pScanReq->restTime; + /* Minimum rest time */ + pMsg->min_rest_time = pScanReq->min_rest_time; + /* Idle time */ + pMsg->idle_time = pScanReq->idle_time; pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch; /* All the scan results caching will be done by Roaming */ /* We do not want LIM to do any caching of scan results, */ @@ -7244,6 +7269,8 @@ void csr_scan_active_list_timeout_handle(void *userData) FL(" Failed to post message to LIM")); qdf_mem_free(msg); } + csr_save_scan_results(mac_ctx, scan_cmd->u.scanCmd.reason, + scan_cmd->sessionId); csr_release_scan_command(mac_ctx, scan_cmd, eCSR_SCAN_FAILURE); return; } diff --git a/core/sme/src/csr/csr_inside_api.h b/core/sme/src/csr/csr_inside_api.h index 829c4f604b64..5537bf317f39 100644 --- a/core/sme/src/csr/csr_inside_api.h +++ b/core/sme/src/csr/csr_inside_api.h @@ -53,6 +53,8 @@ #define CSR_ACTIVE_MIN_CHANNEL_TIME_CONC 20 #define CSR_REST_TIME_CONC 100 +#define CSR_MIN_REST_TIME_CONC 50 +#define CSR_IDLE_TIME_CONC 25 #define CSR_NUM_STA_CHAN_COMBINED_CONC 3 #define CSR_NUM_P2P_CHAN_COMBINED_CONC 1 diff --git a/core/sme/src/csr/csr_neighbor_roam.c b/core/sme/src/csr/csr_neighbor_roam.c index 4667d82ef3ab..e285f5394a84 100644 --- a/core/sme/src/csr/csr_neighbor_roam.c +++ b/core/sme/src/csr/csr_neighbor_roam.c @@ -1397,8 +1397,8 @@ static void csr_neighbor_roam_info_ctx_init( ngbr_roam_info->is11rAssoc = true; } else ngbr_roam_info->is11rAssoc = false; - NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("11rAssoc is = %d"), - ngbr_roam_info->is11rAssoc); + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH, + FL("11rAssoc is = %d"), ngbr_roam_info->is11rAssoc); #ifdef FEATURE_WLAN_ESE /* Based on the auth scheme tell if we are 11r */ @@ -1408,9 +1408,9 @@ static void csr_neighbor_roam_info_ctx_init( ngbr_roam_info->isESEAssoc = true; } else ngbr_roam_info->isESEAssoc = false; - NEIGHBOR_ROAM_DEBUG(pMac, LOG2, - FL("isESEAssoc is = %d ft = %d"), - ngbr_roam_info->isESEAssoc, init_ft_flag); + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_INFO_HIGH, + FL("isESEAssoc is = %d ft = %d"), + ngbr_roam_info->isESEAssoc, init_ft_flag); #endif /* If "Legacy Fast Roaming" is enabled */ if (csr_roam_is_fast_roam_enabled(pMac, session_id)) diff --git a/core/sme/src/csr/csr_tdls_process.c b/core/sme/src/csr/csr_tdls_process.c index d6baf4ea1525..bfd589fb4b6d 100644 --- a/core/sme/src/csr/csr_tdls_process.c +++ b/core/sme/src/csr/csr_tdls_process.c @@ -129,6 +129,8 @@ QDF_STATUS csr_tdls_send_mgmt_req(tHalHandle hHal, uint8_t sessionId, tdlsSendMgmtCmd->u.tdlsCmd.size = sizeof(tTdlsSendMgmtCmdInfo); sme_push_command(pMac, tdlsSendMgmtCmd, false); status = QDF_STATUS_SUCCESS; + sms_log(pMac, LOG1, + FL("Successfully posted eSmeCommandTdlsSendMgmt to SME")); return status; } @@ -201,6 +203,8 @@ QDF_STATUS csr_tdls_change_peer_sta(tHalHandle hHal, uint8_t sessionId, sizeof(tTdlsAddStaCmdInfo); sme_push_command(pMac, tdlsAddStaCmd, false); status = QDF_STATUS_SUCCESS; + sms_log(pMac, LOG1, + FL("Successfully posted eSmeCommandTdlsAddPeer to SME to modify peer ")); } } @@ -271,6 +275,8 @@ QDF_STATUS csr_tdls_send_link_establish_params(tHalHandle hHal, sizeof(tTdlsLinkEstablishCmdInfo); sme_push_command(pMac, tdlsLinkEstablishCmd, false); status = QDF_STATUS_SUCCESS; + sms_log(pMac, LOG1, + FL("Successfully posted eSmeCommandTdlsLinkEstablish to SME")); } } @@ -308,6 +314,8 @@ QDF_STATUS csr_tdls_add_peer_sta(tHalHandle hHal, uint8_t sessionId, sizeof(tTdlsAddStaCmdInfo); sme_push_command(pMac, tdlsAddStaCmd, false); status = QDF_STATUS_SUCCESS; + sms_log(pMac, LOG1, + FL("Successfully posted eSmeCommandTdlsAddPeer to SME")); } } @@ -344,6 +352,8 @@ QDF_STATUS csr_tdls_del_peer_sta(tHalHandle hHal, uint8_t sessionId, sizeof(tTdlsDelStaCmdInfo); sme_push_command(pMac, tdlsDelStaCmd, false); status = QDF_STATUS_SUCCESS; + sms_log(pMac, LOG1, + FL("Successfully posted eSmeCommandTdlsDelPeer to SME")); } } @@ -423,7 +433,7 @@ QDF_STATUS csr_tdls_process_send_mgmt(tpAniSirGlobal pMac, tSmeCmd *cmd) } /* Send the request to PE. */ - sms_log(pMac, LOG1, "sending TDLS Mgmt Frame req to PE "); + sms_log(pMac, LOG1, FL("sending TDLS Mgmt Frame req to PE ")); status = tdls_send_message(pMac, eWNI_SME_TDLS_SEND_MGMT_REQ, (void *)tdlsSendMgmtReq, sizeof(tSirTdlsSendMgmtReq) + diff --git a/core/sme/src/csr/csr_util.c b/core/sme/src/csr/csr_util.c index 1a3a2b67d7fb..7e44a7c12371 100644 --- a/core/sme/src/csr/csr_util.c +++ b/core/sme/src/csr/csr_util.c @@ -788,7 +788,9 @@ uint16_t csr_check_concurrent_channel_overlap(tpAniSirGlobal mac_ctx, (intf_hfreq > sap_lfreq && intf_hfreq < sap_hfreq)))) intf_ch = 0; } else if (intf_ch && sap_ch != intf_ch && - cc_switch_mode == QDF_MCC_TO_SCC_SWITCH_FORCE) { + ((cc_switch_mode == QDF_MCC_TO_SCC_SWITCH_FORCE) || + (cc_switch_mode == + QDF_MCC_TO_SCC_SWITCH_FORCE_WITHOUT_DISCONNECTION))) { if (!((intf_ch < 14 && sap_ch < 14) || (intf_ch > 14 && sap_ch > 14))) intf_ch = 0; diff --git a/core/sme/src/qos/sme_qos.c b/core/sme/src/qos/sme_qos.c index 1aaf22a735b5..641943e38f76 100644 --- a/core/sme/src/qos/sme_qos.c +++ b/core/sme/src/qos/sme_qos.c @@ -4632,7 +4632,12 @@ QDF_STATUS sme_qos_process_reassoc_success_ev(tpAniSirGlobal mac_ctx, if (csr_roam_session && csr_roam_session->connectedInfo.nRICRspLength) { status = sme_qos_process_ft_reassoc_rsp_ev( - mac_ctx, sessionid, event_info); + mac_ctx, sessionid, + event_info); + } else { + QDF_TRACE(QDF_MODULE_ID_SME, + QDF_TRACE_LEVEL_ERROR, FL( + "session or RIC data is not present")); } } #ifdef FEATURE_WLAN_ESE diff --git a/core/utils/epping/inc/epping_internal.h b/core/utils/epping/inc/epping_internal.h index 664076d7a523..3ae69fbfe09f 100644 --- a/core/utils/epping/inc/epping_internal.h +++ b/core/utils/epping/inc/epping_internal.h @@ -111,7 +111,7 @@ typedef struct epping_context { void *p_cds_context; /* CDS context */ struct device *parent_dev; /* Pointer to the parent device */ epping_ctx_state_t e_ctx_state; - int wow_nack; + bool wow_nack; void *epping_adapter; HTC_HANDLE HTCHandle; HTC_ENDPOINT_ID EppingEndpoint[EPPING_MAX_NUM_EPIDS]; diff --git a/core/utils/epping/inc/epping_main.h b/core/utils/epping/inc/epping_main.h index 6d29f0f175a7..813109fecade 100644 --- a/core/utils/epping/inc/epping_main.h +++ b/core/utils/epping/inc/epping_main.h @@ -41,10 +41,6 @@ #include <qdf_lock.h> #include <qdf_types.h> -#define WLAN_IS_EPPING_ENABLED(x) (x == QDF_GLOBAL_EPPING_MODE) -#define WLAN_IS_EPPING_IRQ(x) 1 -#define WLAN_IS_EPPING_FW_UART(x) 0 - /* epping_main signatures */ int epping_open(void); void epping_close(void); diff --git a/core/utils/epping/src/epping_main.c b/core/utils/epping/src/epping_main.c index a0ebc9cc9b7d..44ddc824b9ca 100644 --- a/core/utils/epping/src/epping_main.c +++ b/core/utils/epping/src/epping_main.c @@ -151,10 +151,13 @@ void epping_close(void) qdf_mem_free(to_free); } -static void epping_target_suspend_acknowledge(void *context) +/** + * epping_target_suspend_acknowledge() - process wow ack/nack from fw + * @context: HTC_INIT_INFO->context + * @wow_nack: true when wow is rejected + */ +static void epping_target_suspend_acknowledge(void *context, bool wow_nack) { - int wow_nack = *((int *)context); - if (NULL == g_epping_ctx) { EPPING_LOG(QDF_TRACE_LEVEL_FATAL, "%s: epping_ctx is NULL", __func__); @@ -165,6 +168,27 @@ static void epping_target_suspend_acknowledge(void *context) } /** + * epping_update_ol_config - API to update ol configuration parameters + * + * Return: void + */ +static void epping_update_ol_config(void) +{ + struct ol_config_info cfg; + struct ol_context *ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); + + if (!ol_ctx) + return; + + cfg.enable_self_recovery = 0; + cfg.enable_uart_print = 0; + cfg.enable_fw_log = 0; + cfg.enable_ramdump_collection = 0; + cfg.enable_lpass_support = 0; + + ol_init_ini_config(ol_ctx, &cfg); +} +/** * epping_enable(): End point ping driver enable Function * * This is the driver enable function - called by HDD to enable @@ -221,6 +245,7 @@ int epping_enable(struct device *parent_dev) pEpping_ctx->target_type = tgt_info->target_type; ol_ctx = cds_get_context(QDF_MODULE_ID_BMI); + epping_update_ol_config(); #ifndef FEATURE_BMI_2 /* Initialize BMI and Download firmware */ if (bmi_download_firmware(ol_ctx)) { diff --git a/core/utils/host_diag_log/inc/host_diag_core_event.h b/core/utils/host_diag_log/inc/host_diag_core_event.h index 0c8d963e7389..c7cce228a80a 100644 --- a/core/utils/host_diag_log/inc/host_diag_core_event.h +++ b/core/utils/host_diag_log/inc/host_diag_core_event.h @@ -299,6 +299,86 @@ struct host_event_wlan_log_complete { uint32_t reserved; }; +/** + * struct host_event_tdls_teardown - tdls teardown diag event + * @reason: reason for tear down + * @peer_mac: peer mac + * + * This structure contains tdls teardown diag event info + */ +struct host_event_tdls_teardown { + uint32_t reason; + uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; +}; + +/** + * struct host_event_tdls_enable_link - tdls enable link event + * @peer_mac: peer mac + * @is_off_chan_supported: if off channel supported + * @is_off_chan_configured: if off channel configured + * @is_off_chan_established: if off channel established + * + * This structure contain tdls enable link diag event info + */ +struct host_event_tdls_enable_link { + uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; + uint8_t is_off_chan_supported; + uint8_t is_off_chan_configured; + uint8_t is_off_chan_established; +}; + +/** + * struct host_event_suspend - suspend/resume state + * @state: suspend/resume state + * + * This structure contains suspend resume diag event info + */ +struct host_event_suspend { + uint8_t state; +}; + +/** + * struct host_event_offload_req - offload state + * @offload_type: offload type + * @state: enabled or disabled state + * + * This structure contains offload diag event info + */ +struct host_event_offload_req { + uint8_t offload_type; + uint8_t state; +}; + +/** + * struct host_event_tdls_scan_rejected - scan + * rejected due to tdls + * @status: rejected status + * + * This structure contains scan rejected due to + * tdls event info + */ +struct host_event_tdls_scan_rejected { + uint8_t status; +}; + +/** + * struct host_event_tdls_tx_rx_mgmt - for TX RX management frame + * @event_id: event ID + * @tx_rx: tx or rx + * @type: type of frame + * @action_sub_type: action frame type + * @peer_mac: peer mac + * + * This structure contains tdls TX RX management frame info + */ +struct host_event_tdls_tx_rx_mgmt { + uint8_t event_id; + uint8_t tx_rx; + uint8_t type; + uint8_t action_sub_type; + uint8_t peer_mac[QDF_MAC_ADDR_SIZE]; +}; + /*------------------------------------------------------------------------- Function declarations and documenation ------------------------------------------------------------------------*/ diff --git a/core/utils/host_diag_log/inc/host_diag_event_defs.h b/core/utils/host_diag_log/inc/host_diag_event_defs.h index ca250c592db2..6b658ba37b81 100644 --- a/core/utils/host_diag_log/inc/host_diag_event_defs.h +++ b/core/utils/host_diag_log/inc/host_diag_event_defs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -54,6 +54,12 @@ typedef enum { EVENT_WLAN_WAKE_LOCK = 0xAA2, /* 96 bytes payload */ EVENT_WLAN_BEACON_RECEIVED = 0xAA6, /* FW event: 2726 */ EVENT_WLAN_LOG_COMPLETE = 0xAA7, /* 16 bytes payload */ + EVENT_WLAN_TDLS_TEARDOWN = 0xAB5, + EVENT_WLAN_TDLS_ENABLE_LINK = 0XAB6, + EVENT_WLAN_SUSPEND_RESUME = 0xAB7, + EVENT_WLAN_OFFLOAD_REQ = 0xAB8, + EVENT_TDLS_SCAN_BLOCK = 0xAB9, + EVENT_WLAN_TDLS_TX_RX_MGMT = 0xABA, EVENT_MAX_ID = 0x0FFF } event_id_enum_type; diff --git a/core/utils/logging/inc/wlan_logging_sock_svc.h b/core/utils/logging/inc/wlan_logging_sock_svc.h index 1850a0138466..d0b76d1aed9a 100644 --- a/core/utils/logging/inc/wlan_logging_sock_svc.h +++ b/core/utils/logging/inc/wlan_logging_sock_svc.h @@ -46,6 +46,7 @@ int wlan_log_to_user(QDF_TRACE_LEVEL log_level, char *to_be_sent, int length); void wlan_logging_set_per_pkt_stats(void); void wlan_logging_set_log_level(void); void wlan_logging_set_fw_flush_complete(void); +void wlan_flush_host_logs_for_fatal(void); #ifdef FEATURE_WLAN_DIAG_SUPPORT void wlan_report_log_completion(uint32_t is_fatal, uint32_t indicator, @@ -57,5 +58,9 @@ static inline void wlan_report_log_completion(uint32_t is_fatal, { return; } +static inline void wlan_flush_host_logs_for_fatal(void) +{ +} + #endif /* FEATURE_WLAN_DIAG_SUPPORT */ #endif /* WLAN_LOGGING_SOCK_SVC_H */ diff --git a/core/utils/logging/src/wlan_logging_sock_svc.c b/core/utils/logging/src/wlan_logging_sock_svc.c index 15687a2f7e15..c0c854f05bd4 100644 --- a/core/utils/logging/src/wlan_logging_sock_svc.c +++ b/core/utils/logging/src/wlan_logging_sock_svc.c @@ -39,6 +39,7 @@ #include <wlan_ptt_sock_svc.h> #include "pktlog_ac.h" #include <host_diag_core_event.h> +#include "cds_utils.h" #define LOGGING_TRACE(level, args ...) \ QDF_TRACE(QDF_MODULE_ID_HDD, level, ## args) @@ -505,14 +506,19 @@ void wlan_report_log_completion(uint32_t is_fatal, void send_flush_completion_to_user(void) { uint32_t is_fatal, indicator, reason_code; + bool recovery_needed; - cds_get_log_completion(&is_fatal, &indicator, &reason_code); + cds_get_and_reset_log_completion(&is_fatal, + &indicator, &reason_code, &recovery_needed); /* Error on purpose, so that it will get logged in the kmsg */ LOGGING_TRACE(QDF_TRACE_LEVEL_ERROR, "%s: Sending flush done to userspace", __func__); wlan_report_log_completion(is_fatal, indicator, reason_code); + + if (recovery_needed) + cds_trigger_recovery(); } /** @@ -525,6 +531,7 @@ static int wlan_logging_thread(void *Arg) { int ret_wait_status = 0; int ret = 0; + unsigned long flags; set_user_nice(current, -2); @@ -561,6 +568,10 @@ static int wlan_logging_thread(void *Arg) ret = send_filled_buffers_to_user(); if (-ENOMEM == ret) msleep(200); + if (WLAN_LOG_INDICATOR_HOST_ONLY == + cds_get_log_indicator()) { + send_flush_completion_to_user(); + } } if (test_and_clear_bit(HOST_LOG_PER_PKT_STATS, @@ -582,6 +593,12 @@ static int wlan_logging_thread(void *Arg) send_flush_completion_to_user(); } else { gwlan_logging.is_flush_complete = true; + /* Flush all current host logs*/ + spin_lock_irqsave(&gwlan_logging.spin_lock, + flags); + wlan_queue_logmsg_for_app(); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, + flags); set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); set_bit(HOST_LOG_PER_PKT_STATS, @@ -804,10 +821,35 @@ void wlan_logging_set_log_level(void) */ void wlan_logging_set_fw_flush_complete(void) { - if (gwlan_logging.is_active == false) + if (gwlan_logging.is_active == false || + !cds_is_fatal_event_enabled()) return; set_bit(HOST_LOG_FW_FLUSH_COMPLETE, &gwlan_logging.eventFlag); wake_up_interruptible(&gwlan_logging.wait_queue); } + +/** + * wlan_flush_host_logs_for_fatal() - Flush host logs + * + * This function is used to send signal to the logger thread to + * Flush the host logs + * + * Return: None + */ +void wlan_flush_host_logs_for_fatal(void) +{ + unsigned long flags; + + if (cds_is_log_report_in_progress()) { + pr_info("%s:flush all host logs Setting HOST_LOG_POST_MASK\n", + __func__); + spin_lock_irqsave(&gwlan_logging.spin_lock, flags); + wlan_queue_logmsg_for_app(); + spin_unlock_irqrestore(&gwlan_logging.spin_lock, flags); + set_bit(HOST_LOG_DRIVER_MSG, &gwlan_logging.eventFlag); + wake_up_interruptible(&gwlan_logging.wait_queue); + } +} + #endif /* WLAN_LOGGING_SOCK_SVC_ENABLE */ diff --git a/core/utils/nlink/src/wlan_nlink_srv.c b/core/utils/nlink/src/wlan_nlink_srv.c index 80055a64f656..d3b56faef10b 100644 --- a/core/utils/nlink/src/wlan_nlink_srv.c +++ b/core/utils/nlink/src/wlan_nlink_srv.c @@ -258,9 +258,6 @@ static void nl_srv_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return; } - QDF_TRACE(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_INFO, - "NLINK: Received NL msg type [%d]", type); - /* turn type into dispatch table offset */ type -= WLAN_NL_MSG_BASE; diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index ff9dca2f5a70..3f1ac3b5fac4 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -63,6 +63,15 @@ #define WMA_CRASH_INJECT_TIMEOUT 5000 +/* MAC ID to PDEV ID mapping is as given below + * MAC_ID PDEV_ID + * 0 1 + * 1 2 + * SOC Level WMI_PDEV_ID_SOC + */ +#define WMA_MAC_TO_PDEV_MAP(x) ((x) + (1)) +#define WMA_PDEV_TO_MAC_MAP(x) ((x) - (1)) + /* In prima 12 HW stations are supported including BCAST STA(staId 0) * and SELF STA(staId 1) so total ASSOC stations which can connect to Prima * SoftAP = 12 - 1(Self STa) - 1(Bcast Sta) = 10 Stations. @@ -1972,11 +1981,11 @@ QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma, QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle, struct wmi_pcl_chan_weights *msg); -QDF_STATUS wma_send_soc_set_hw_mode_cmd(tp_wma_handle wma_handle, +QDF_STATUS wma_send_pdev_set_hw_mode_cmd(tp_wma_handle wma_handle, struct sir_hw_mode *msg); QDF_STATUS wma_get_scan_id(uint32_t *scan_id); -QDF_STATUS wma_send_soc_set_dual_mac_config(tp_wma_handle wma_handle, +QDF_STATUS wma_send_pdev_set_dual_mac_config(tp_wma_handle wma_handle, struct sir_dual_mac_config *msg); QDF_STATUS wma_send_pdev_set_antenna_mode(tp_wma_handle wma_handle, struct sir_antenna_mode_param *msg); @@ -2039,5 +2048,12 @@ QDF_STATUS wma_ht40_stop_obss_scan(tp_wma_handle wma_handle, int32_t vdev_id); QDF_STATUS wma_send_ht40_obss_scanind(tp_wma_handle wma, struct obss_ht40_scanind *req); + +int wma_get_bpf_caps_event_handler(void *handle, + u_int8_t *cmd_param_info, + u_int32_t len); +QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma); +QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma, + struct sir_bpf_set_offload *bpf_set_offload); #endif struct wma_ini_config *wma_get_ini_handle(tp_wma_handle wma_handle); diff --git a/core/wma/inc/wma_api.h b/core/wma/inc/wma_api.h index cec1e1e705ab..039202571f2a 100644 --- a/core/wma/inc/wma_api.h +++ b/core/wma/inc/wma_api.h @@ -65,6 +65,8 @@ typedef enum { GEN_PARAM_DUMP_PCIE_ACCESS_LOG, #endif GEN_PARAM_MODULATED_DTIM, + GEN_PARAM_CAPTURE_TSF, + GEN_PARAM_RESET_TSF_GPIO, } GEN_PARAM; #define VDEV_CMD 1 @@ -121,7 +123,7 @@ int wma_runtime_suspend(void); int wma_runtime_resume(void); int wma_bus_suspend(void); QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr); -void wma_target_suspend_acknowledge(void *context); +void wma_target_suspend_acknowledge(void *context, bool wow_nack); int wma_bus_resume(void); QDF_STATUS wma_resume_target(WMA_HANDLE handle); QDF_STATUS wma_disable_wow_in_fw(WMA_HANDLE handle); diff --git a/core/wma/inc/wma_internal.h b/core/wma/inc/wma_internal.h index 42c2c9d6fe3f..2f47901d9143 100644 --- a/core/wma/inc/wma_internal.h +++ b/core/wma/inc/wma_internal.h @@ -1072,6 +1072,38 @@ QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle, auto_sh_cmd); #endif +#ifdef WLAN_FEATURE_TSF +int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len); +QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id); +QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id); +QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin); +#else +static inline QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, + uint32_t vdev_id) +{ + return QDF_STATUS_SUCCESS; +} + +static inline QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, + uint32_t vdev_id) +{ + return QDF_STATUS_SUCCESS; +} + +static inline int wma_vdev_tsf_handler(void *handle, uint8_t *data, + uint32_t data_len) +{ + return 0; +} + +static inline QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin) +{ + return QDF_STATUS_E_INVAL; +} +#endif + + + #ifdef WLAN_FEATURE_NAN QDF_STATUS wma_nan_req(void *wma_ptr, tpNanRequest nan_req); diff --git a/core/wma/inc/wma_tgt_cfg.h b/core/wma/inc/wma_tgt_cfg.h index 94c5b05fca14..e6a8c86a9f80 100644 --- a/core/wma/inc/wma_tgt_cfg.h +++ b/core/wma/inc/wma_tgt_cfg.h @@ -165,5 +165,6 @@ struct wma_tgt_cfg { bool egap_support; #endif uint32_t fine_time_measurement_cap; + bool bpf_enabled; }; #endif /* WMA_TGT_CFG_H */ diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index c82cfa033a33..252d271220f0 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -432,6 +432,7 @@ #endif #define WMA_SET_SCAN_MAC_OUI_REQ SIR_HAL_SET_SCAN_MAC_OUI_REQ +#define WMA_TSF_GPIO_PIN SIR_HAL_TSF_GPIO_PIN_REQ #ifdef DHCP_SERVER_OFFLOAD #define WMA_SET_DHCP_SERVER_OFFLOAD_CMD SIR_HAL_SET_DHCP_SERVER_OFFLOAD @@ -467,6 +468,9 @@ #define WMA_ADD_BCN_FILTER_CMDID SIR_HAL_ADD_BCN_FILTER_CMDID #define WMA_REMOVE_BCN_FILTER_CMDID SIR_HAL_REMOVE_BCN_FILTER_CMDID +#define WDA_BPF_GET_CAPABILITIES_REQ SIR_HAL_BPF_GET_CAPABILITIES_REQ +#define WDA_BPF_SET_INSTRUCTIONS_REQ SIR_HAL_BPF_SET_INSTRUCTIONS_REQ + /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_data.c b/core/wma/src/wma_data.c index 572b7d91a1d8..b49200cbc46a 100644 --- a/core/wma/src/wma_data.c +++ b/core/wma/src/wma_data.c @@ -999,6 +999,7 @@ QDF_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(uint32_t mcc_adaptive_scheduler) { tp_wma_handle wma = NULL; + uint32_t pdev_id; wma = cds_get_context(QDF_MODULE_ID_WMA); if (NULL == wma) { @@ -1006,8 +1007,17 @@ QDF_STATUS wma_set_enable_disable_mcc_adaptive_scheduler(uint32_t return QDF_STATUS_E_FAULT; } + /* In WMI_RESMGR_ADAPTIVE_OCS_ENABLE_DISABLE_CMDID fw cannot + * determine the PDEV on its own, Host needs to specify the PDEV + * ID in the command. + */ + if (wma->wlan_resource_config.use_pdev_id) + pdev_id = WMA_MAC_TO_PDEV_MAP(0); + else + pdev_id = WMI_PDEV_ID_SOC; + return wmi_unified_set_enable_disable_mcc_adaptive_scheduler_cmd( - wma->wmi_handle, mcc_adaptive_scheduler); + wma->wmi_handle, mcc_adaptive_scheduler, pdev_id); } /** @@ -2675,11 +2685,15 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen, chanfreq = wma_handle->interfaces[vdev_id].scan_info.chan_freq; WMA_LOGI("%s: Preauth frame on channel %d", __func__, chanfreq); } else if (pFc->subType == SIR_MAC_MGMT_PROBE_RSP) { - chanfreq = wma_handle->interfaces[vdev_id].mhz; - WMA_LOGI("%s: Probe response frame on channel %d", __func__, - chanfreq); - WMA_LOGI("%s: Probe response frame on vdev id %d", __func__, - vdev_id); + if ((wma_is_vdev_in_ap_mode(wma_handle, vdev_id)) && + (0 != wma_handle->interfaces[vdev_id].mhz)) + chanfreq = wma_handle->interfaces[vdev_id].mhz; + else + chanfreq = channel_freq; + WMA_LOGI("%s: Probe response frame on channel %d vdev:%d", + __func__, chanfreq, vdev_id); + if (wma_is_vdev_in_ap_mode(wma_handle, vdev_id) && !chanfreq) + WMA_LOGE("%s: AP oper chan is zero", __func__); } else if (pFc->subType == SIR_MAC_MGMT_ACTION) { chanfreq = channel_freq; } else { @@ -2704,14 +2718,19 @@ QDF_STATUS wma_tx_packet(void *wma_context, void *tx_frame, uint16_t frmLen, mgmt_param.tx_complete_cb = tx_frm_download_comp_cb; mgmt_param.tx_ota_post_proc_cb = tx_frm_ota_comp_cb; mgmt_param.chanfreq = chanfreq; - mgmt_param.wmi_desc = wmi_desc_get(wma_handle); mgmt_param.pdata = pData; mgmt_param.qdf_ctx = cds_get_context(QDF_MODULE_ID_QDF_DEVICE); - - status = wmi_mgmt_unified_cmd_send(wma_handle->wmi_handle, - &mgmt_param); - if (status) - wmi_desc_put(wma_handle, mgmt_param.wmi_desc); + mgmt_param.wmi_desc = wmi_desc_get(wma_handle); + if (NULL == mgmt_param.wmi_desc) { + WMA_LOGE(FL("Failed to get wmi descriptor")); + status = QDF_STATUS_E_FAILURE; + } else { + status = wmi_mgmt_unified_cmd_send( + wma_handle->wmi_handle, + &mgmt_param); + if (status) + wmi_desc_put(wma_handle, mgmt_param.wmi_desc); + } } else { /* Hand over the Tx Mgmt frame to TxRx */ status = ol_txrx_mgmt_send_ext(txrx_vdev, tx_frame, diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index 7526499d390c..c0ebf22a7339 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -54,6 +54,7 @@ #include "lim_session_utils.h" #include "cds_utils.h" +#include "cds_concurrency.h" #if !defined(REMOVE_PKT_LOG) #include "pktlog_ac.h" @@ -73,6 +74,8 @@ #include <cdp_txrx_cfg.h> #include <cdp_txrx_cmn.h> +#include "cds_concurrency.h" + /** * wma_find_vdev_by_addr() - find vdev_id from mac address * @wma: wma handle @@ -204,6 +207,8 @@ enum wlan_op_mode wma_get_txrx_vdev_type(uint32_t type) vdev_type = wlan_op_mode_ocb; break; case WMI_VDEV_TYPE_MONITOR: + vdev_type = wlan_op_mode_monitor; + break; default: WMA_LOGE("Invalid vdev type %u", type); vdev_type = wlan_op_mode_unknown; @@ -790,6 +795,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, tpAniSirGlobal mac_ctx = cds_get_context(QDF_MODULE_ID_PE); if (NULL == mac_ctx) { WMA_LOGE("%s: Failed to get mac_ctx", __func__); + cds_set_do_hw_mode_change_flag(false); return -EINVAL; } #endif /* FEATURE_AP_MCC_CH_AVOIDANCE */ @@ -798,12 +804,14 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *) cmd_param_info; if (!param_buf) { WMA_LOGE("Invalid start response event buffer"); + cds_set_do_hw_mode_change_flag(false); return -EINVAL; } resp_event = param_buf->fixed_param; if (!resp_event) { WMA_LOGE("Invalid start response event buffer"); + cds_set_do_hw_mode_change_flag(false); return -EINVAL; } @@ -820,8 +828,20 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, resp_event->cfgd_rx_streams; wma->interfaces[resp_event->vdev_id].chain_mask = resp_event->chain_mask; - wma->interfaces[resp_event->vdev_id].mac_id = - resp_event->mac_id; + if (wma->wlan_resource_config.use_pdev_id) { + if (resp_event->pdev_id == WMI_PDEV_ID_SOC) { + WMA_LOGE("%s: soc level id received for mac id", + __func__); + QDF_BUG(0); + return -EINVAL; + } + wma->interfaces[resp_event->vdev_id].mac_id = + WMA_PDEV_TO_MAC_MAP(resp_event->pdev_id); + } else { + wma->interfaces[resp_event->vdev_id].mac_id = + resp_event->mac_id; + } + WMA_LOGI("%s: vdev:%d tx ss=%d rx ss=%d chain mask=%d mac=%d", __func__, resp_event->vdev_id, @@ -845,6 +865,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, wma->interfaces[resp_event->vdev_id].bssid, ¶m) != QDF_STATUS_SUCCESS) { WMA_LOGE("%s : failed to send vdev up", __func__); + cds_set_do_hw_mode_change_flag(false); return -EEXIST; } qdf_atomic_set(&wma->interfaces[resp_event->vdev_id]. @@ -859,6 +880,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, if (!req_msg) { WMA_LOGE("%s: Failed to lookup request message for vdev %d", __func__, resp_event->vdev_id); + cds_set_do_hw_mode_change_flag(false); return -EINVAL; } @@ -877,6 +899,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, if (!params) { WMA_LOGE("%s: channel switch params is NULL for vdev %d", __func__, resp_event->vdev_id); + cds_set_do_hw_mode_change_flag(false); return -EINVAL; } @@ -889,8 +912,11 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, } params->smpsMode = host_map_smps_mode(resp_event->smps_mode); params->status = resp_event->status; - if (resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT && - (iface->type == WMI_VDEV_TYPE_STA)) { + if (((resp_event->resp_type == WMI_VDEV_RESTART_RESP_EVENT) && + (iface->type == WMI_VDEV_TYPE_STA)) || + ((resp_event->resp_type == WMI_VDEV_START_RESP_EVENT) && + (iface->type == WMI_VDEV_TYPE_MONITOR))) { + param.vdev_id = resp_event->vdev_id; param.assoc_id = iface->aid; status = wmi_unified_vdev_up_send(wma->wmi_handle, @@ -901,6 +927,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, __func__, resp_event->vdev_id); wma->interfaces[resp_event->vdev_id].vdev_up = false; + cds_set_do_hw_mode_change_flag(false); } else { wma->interfaces[resp_event->vdev_id].vdev_up = true; @@ -920,6 +947,7 @@ int wma_vdev_start_resp_handler(void *handle, uint8_t *cmd_param_info, iface->bssid, ¶m) != QDF_STATUS_SUCCESS) { WMA_LOGE(FL("failed to send vdev up")); + cds_set_do_hw_mode_change_flag(false); return -EEXIST; } iface->vdev_up = true; @@ -1552,7 +1580,8 @@ ol_txrx_vdev_handle wma_vdev_attach(tp_wma_handle wma_handle, if (((self_sta_req->type == WMI_VDEV_TYPE_AP) && (self_sta_req->sub_type == WMI_UNIFIED_VDEV_SUBTYPE_P2P_DEVICE)) || - (self_sta_req->type == WMI_VDEV_TYPE_OCB)) { + (self_sta_req->type == WMI_VDEV_TYPE_OCB) || + (self_sta_req->type == WMI_VDEV_TYPE_MONITOR)) { WMA_LOGA("Creating self peer %pM, vdev_id %hu", self_sta_req->self_mac_addr, self_sta_req->session_id); status = wma_create_peer(wma_handle, txrx_pdev, @@ -1777,7 +1806,7 @@ QDF_STATUS wma_vdev_start(tp_wma_handle wma, */ params.is_dfs = req->is_dfs; params.is_restart = isRestart; - if (req->is_dfs) { + if ((QDF_GLOBAL_MONITOR_MODE != cds_get_conparam()) && req->is_dfs) { params.flag_dfs = WMI_CHAN_FLAG_DFS; temp_chan_info |= (1 << WMI_CHAN_FLAG_DFS); params.dis_hw_ack = true; @@ -3790,6 +3819,7 @@ static void wma_add_sta_req_sta_mode(tp_wma_handle wma, tpAddStaParams params) ¶m) != QDF_STATUS_SUCCESS) { WMA_LOGP("%s: Failed to send vdev up cmd: vdev %d bssid %pM", __func__, params->smesessionId, params->bssId); + cds_set_do_hw_mode_change_flag(false); status = QDF_STATUS_E_FAILURE; } else { wma->interfaces[params->smesessionId].vdev_up = true; diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 447aa417635b..00c2df030d6f 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -267,6 +267,192 @@ end: wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY); } +#ifdef WLAN_FEATURE_TSF +/** + * wma_vdev_tsf_handler() - handle tsf event indicated by FW + * @handle: wma context + * @data: event buffer + * @data len: length of event buffer + * + * Return: 0 on success + */ +int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len) +{ + cds_msg_t tsf_msg = {0}; + WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf; + wmi_vdev_tsf_report_event_fixed_param *tsf_event; + struct stsf *ptsf; + + if (data == NULL) { + WMA_LOGE("%s: invalid pointer", __func__); + return -EINVAL; + } + ptsf = qdf_mem_malloc(sizeof(*ptsf)); + if (NULL == ptsf) { + WMA_LOGE("%s: failed to allocate tsf data structure", __func__); + return -ENOMEM; + } + + param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data; + tsf_event = param_buf->fixed_param; + + ptsf->vdev_id = tsf_event->vdev_id; + ptsf->tsf_low = tsf_event->tsf_low; + ptsf->tsf_high = tsf_event->tsf_high; + + WMA_LOGD("%s: receive WMI_VDEV_TSF_REPORT_EVENTID ", __func__); + WMA_LOGD("%s: vdev_id = %u,tsf_low =%u, tsf_high = %u", __func__, + ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high); + + tsf_msg.type = eWNI_SME_TSF_EVENT; + tsf_msg.bodyptr = ptsf; + tsf_msg.bodyval = 0; + + if (QDF_STATUS_SUCCESS != + cds_mq_post_message(CDS_MQ_ID_SME, &tsf_msg)) { + + WMA_LOGP("%s: Failed to post eWNI_SME_TSF_EVENT", __func__); + qdf_mem_free(ptsf); + return -EINVAL; + } + return 0; +} + +/** + * wma_capture_tsf() - send wmi to fw to capture tsf + * @wma_handle: wma handler + * @vdev_id: vdev id + * + * Return: wmi send state + */ +QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + wmi_buf_t buf; + wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; + int ret; + int len = sizeof(*cmd); + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: failed to allocate memory for cap tsf cmd", + __func__); + return QDF_STATUS_E_NOMEM; + } + + cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf); + cmd->vdev_id = vdev_id; + cmd->tsf_action = TSF_TSTAMP_CAPTURE_REQ; + + WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_REQ", __func__, + cmd->vdev_id); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); + if (ret != EOK) { + WMA_LOGE("wmi_unified_cmd_send returned Error %d", status); + status = QDF_STATUS_E_FAILURE; + goto error; + } + + return QDF_STATUS_SUCCESS; + +error: + if (buf) + wmi_buf_free(buf); + return status; +} + +/** + * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO + * @wma_handle: wma handler + * @vdev_id: vdev id + * + * Return: wmi send state + */ +QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + wmi_buf_t buf; + wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; + int ret; + int len = sizeof(*cmd); + uint8_t *buf_ptr; + + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + if (!buf) { + WMA_LOGP("%s: failed to allocate memory for reset tsf gpio", + __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr; + cmd->vdev_id = vdev_id; + cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET; + + WMA_LOGD("%s :vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", __func__, + cmd->vdev_id); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); + + if (ret != EOK) { + WMA_LOGE("wmi_unified_cmd_send returned Error %d", status); + status = QDF_STATUS_E_FAILURE; + goto error; + } + return QDF_STATUS_SUCCESS; + +error: + if (buf) + wmi_buf_free(buf); + return status; +} + +/** + * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin + * @handle: wma handler + * @pin: GPIO pin id + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin) +{ + tp_wma_handle wma = (tp_wma_handle)handle; + struct pdev_params pdev_param = {0}; + int32_t ret; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not set gpio", __func__); + return QDF_STATUS_E_INVAL; + } + + WMA_LOGD("%s: set tsf gpio pin: %d", __func__, pin); + + pdev_param.param_id = WMI_PDEV_PARAM_WNTS_CONFIG; + pdev_param.param_value = pin; + ret = wmi_unified_pdev_param_send(wma->wmi_handle, + &pdev_param, + WMA_WILDCARD_PDEV_ID); + if (ret) { + WMA_LOGE("%s: Failed to set tsf gpio pin (%d)", __func__, ret); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} +#endif + #ifdef FEATURE_WLAN_LPHB /** * wma_lphb_conf_hbenable() - enable command of LPHB configuration requests @@ -3060,7 +3246,7 @@ QDF_STATUS wma_enable_wow_in_fw(WMA_HANDLE handle) #endif /* CONFIG_CNSS */ qdf_event_reset(&wma->target_suspend); - wma->wow_nack = 0; + wma->wow_nack = false; host_credits = wmi_get_host_credits(wma->wmi_handle); wmi_pending_cmds = wmi_get_pending_cmds(wma->wmi_handle); @@ -5739,14 +5925,14 @@ QDF_STATUS wma_suspend_target(WMA_HANDLE handle, int disable_target_intr) /** * wma_target_suspend_acknowledge() - update target susspend status - * @context: wma context + * @context: HTC_INIT_INFO->context + * @wow_nack: true when wow is rejected * * Return: none */ -void wma_target_suspend_acknowledge(void *context) +void wma_target_suspend_acknowledge(void *context, bool wow_nack) { tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); - int wow_nack = *((int *)context); if (NULL == wma) { WMA_LOGE("%s: wma is NULL", __func__); @@ -6718,3 +6904,172 @@ QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma, return ret; } +/** + * wma_get_bpf_caps_event_handler() - Event handler for get bpf capability + * @handle: WMA global handle + * @cmd_param_info: command event data + * @len: Length of @cmd_param_info + * + * Return: 0 on Success or Errno on failure + */ +int wma_get_bpf_caps_event_handler(void *handle, + u_int8_t *cmd_param_info, + u_int32_t len) +{ + WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf; + wmi_bpf_capability_info_evt_fixed_param *event; + struct sir_bpf_get_offload *bpf_get_offload; + tpAniSirGlobal pmac = (tpAniSirGlobal)cds_get_context( + QDF_MODULE_ID_PE); + + if (!pmac) { + WMA_LOGE("%s: Invalid pmac", __func__); + return -EINVAL; + } + if (!pmac->sme.pbpf_get_offload_cb) { + WMA_LOGE("%s: Callback not registered", __func__); + return -EINVAL; + } + + param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info; + event = param_buf->fixed_param; + bpf_get_offload = qdf_mem_malloc(sizeof(*bpf_get_offload)); + + if (!bpf_get_offload) { + WMA_LOGP("%s: Memory allocation failed.", __func__); + return -ENOMEM; + } + + bpf_get_offload->bpf_version = event->bpf_version; + bpf_get_offload->max_bpf_filters = event->max_bpf_filters; + bpf_get_offload->max_bytes_for_bpf_inst = + event->max_bytes_for_bpf_inst; + WMA_LOGD("%s: BPF capabilities version: %d max bpf filter size: %d", + __func__, bpf_get_offload->bpf_version, + bpf_get_offload->max_bytes_for_bpf_inst); + + WMA_LOGD("%s: sending bpf capabilities event to hdd", __func__); + pmac->sme.pbpf_get_offload_cb(pmac->hHdd, bpf_get_offload); + qdf_mem_free(bpf_get_offload); + return 0; +} + +/** + * wma_get_bpf_capabilities - Send get bpf capability to firmware + * @wma_handle: wma handle + * + * Return: QDF_STATUS enumeration. + */ +QDF_STATUS wma_get_bpf_capabilities(tp_wma_handle wma) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + wmi_bpf_get_capability_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len; + u_int8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE(FL("WMA is closed, can not issue get BPF capab")); + return QDF_STATUS_E_INVAL; + } + + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BPF_OFFLOAD)) { + WMA_LOGE(FL("BPF cababilities feature bit not enabled")); + return QDF_STATUS_E_FAILURE; + } + + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_bpf_get_capability_cmd_fixed_param)); + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_BPF_GET_CAPABILITY_CMDID)) { + WMA_LOGE(FL("Failed to send BPF capability command")); + wmi_buf_free(wmi_buf); + return QDF_STATUS_E_FAILURE; + } + return status; +} + +/** + * wma_set_bpf_instructions - Set bpf instructions to firmware + * @wma: wma handle + * @bpf_set_offload: Bpf offload information to set to firmware + * + * Return: QDF_STATUS enumeration + */ +QDF_STATUS wma_set_bpf_instructions(tp_wma_handle wma, + struct sir_bpf_set_offload *bpf_set_offload) +{ + wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint32_t len = 0, len_aligned = 0; + u_int8_t *buf_ptr; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE("%s: WMA is closed, can not issue set BPF capability", + __func__); + return QDF_STATUS_E_INVAL; + } + + if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, + WMI_SERVICE_BPF_OFFLOAD)) { + WMA_LOGE(FL("BPF offload feature Disabled")); + return QDF_STATUS_E_NOSUPPORT; + } + + if (bpf_set_offload->total_length) { + len_aligned = roundup(bpf_set_offload->current_length, + sizeof(A_UINT32)); + len = len_aligned + WMI_TLV_HDR_SIZE; + } + + len += sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE("%s: wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); + cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr; + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_bpf_set_vdev_instructions_cmd_fixed_param)); + cmd->vdev_id = bpf_set_offload->session_id; + cmd->filter_id = bpf_set_offload->filter_id; + cmd->total_length = bpf_set_offload->total_length; + cmd->current_offset = bpf_set_offload->current_offset; + cmd->current_length = bpf_set_offload->current_length; + + if (bpf_set_offload->total_length) { + buf_ptr += + sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned); + buf_ptr += WMI_TLV_HDR_SIZE; + qdf_mem_copy(buf_ptr, bpf_set_offload->program, + bpf_set_offload->current_length); + qdf_mem_free(bpf_set_offload->program); + } + + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) { + WMA_LOGE(FL("Failed to send config bpf instructions command")); + wmi_buf_free(wmi_buf); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 723ff4921eb8..347c745c95d8 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -247,6 +247,9 @@ static void wma_set_default_tgt_config(tp_wma_handle wma_handle) tgt_cfg.rx_decap_mode = CFG_TGT_RX_DECAP_MODE_NWIFI; } #endif /* PERE_IP_HDR_ALIGNMENT_WAR */ + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) + tgt_cfg.rx_decap_mode = CFG_TGT_RX_DECAP_MODE_RAW; + wma_handle->wlan_resource_config = tgt_cfg; } @@ -919,6 +922,12 @@ static void wma_process_cli_set_cmd(tp_wma_handle wma, privcmd->param_value, privcmd->param_sec_value); break; + case GEN_PARAM_CAPTURE_TSF: + ret = wma_capture_tsf(wma, privcmd->param_value); + break; + case GEN_PARAM_RESET_TSF_GPIO: + ret = wma_reset_tsf_gpio(wma, privcmd->param_value); + break; #ifdef CONFIG_ATH_PCIE_ACCESS_DEBUG case GEN_PARAM_DUMP_PCIE_ACCESS_LOG: htc_dump(wma->htc_handle, PCIE_DUMP, false); @@ -1672,6 +1681,13 @@ QDF_STATUS wma_open(void *cds_context, wma_handle->wma_runtime_resume_lock = qdf_runtime_lock_init("wma_runtime_resume"); + /* Initialize max_no_of_peers for wma_get_number_of_peers_supported() */ + wma_init_max_no_of_peers(wma_handle, mac_params->maxStation); + /* Cap maxStation based on the target version */ + mac_params->maxStation = wma_get_number_of_peers_supported(wma_handle); + /* Reinitialize max_no_of_peers based on the capped maxStation value */ + wma_init_max_no_of_peers(wma_handle, mac_params->maxStation); + /* initialize default target config */ wma_set_default_tgt_config(wma_handle); @@ -1733,8 +1749,6 @@ QDF_STATUS wma_open(void *cds_context, if (cds_get_conparam() == QDF_GLOBAL_FTM_MODE) wma_utf_attach(wma_handle); #endif /* QCA_WIFI_FTM */ - wma_init_max_no_of_peers(wma_handle, mac_params->maxStation); - mac_params->maxStation = wma_get_number_of_peers_supported(wma_handle); mac_params->maxBssId = WMA_MAX_SUPPORTED_BSS; mac_params->frameTransRequired = 0; @@ -2052,6 +2066,10 @@ QDF_STATUS wma_open(void *cds_context, WMI_PEER_DELETE_RESP_EVENTID, wma_peer_delete_handler, WMA_RX_SERIALIZER_CTX); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_BPF_CAPABILIY_INFO_EVENTID, + wma_get_bpf_caps_event_handler, + WMA_RX_SERIALIZER_CTX); return QDF_STATUS_SUCCESS; err_dbglog_init: @@ -2263,7 +2281,7 @@ static int wma_flush_complete_evt_handler(void *handle, reason_code); status = cds_set_log_completion(WLAN_LOG_TYPE_FATAL, WLAN_LOG_INDICATOR_FIRMWARE, - reason_code); + reason_code, false); if (QDF_STATUS_SUCCESS != status) { WMA_LOGE("%s: Failed to set log trigger params", __func__); @@ -2284,23 +2302,24 @@ static int wma_flush_complete_evt_handler(void *handle, } /** - * wma_soc_set_hw_mode_resp_evt_handler() - Set HW mode resp evt handler + * wma_pdev_set_hw_mode_resp_evt_handler() - Set HW mode resp evt handler * @handle: WMI handle * @event: Event recevied from FW * @len: Length of the event * - * Event handler for WMI_SOC_SET_HW_MODE_RESP_EVENTID that is sent to host - * driver in response to a WMI_SOC_SET_HW_MODE_CMDID being sent to WLAN firmware + * Event handler for WMI_PDEV_SET_HW_MODE_RESP_EVENTID that is sent to host + * driver in response to a WMI_PDEV_SET_HW_MODE_CMDID being sent to WLAN + * firmware * * Return: Success on receiving valid params from FW */ -static int wma_soc_set_hw_mode_resp_evt_handler(void *handle, +static int wma_pdev_set_hw_mode_resp_evt_handler(void *handle, uint8_t *event, uint32_t len) { - WMI_SOC_SET_HW_MODE_RESP_EVENTID_param_tlvs *param_buf; - wmi_soc_set_hw_mode_response_event_fixed_param *wmi_event; - wmi_soc_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry; + WMI_PDEV_SET_HW_MODE_RESP_EVENTID_param_tlvs *param_buf; + wmi_pdev_set_hw_mode_response_event_fixed_param *wmi_event; + wmi_pdev_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry; uint32_t i; struct sir_set_hw_mode_resp *hw_mode_resp; tp_wma_handle wma = (tp_wma_handle) handle; @@ -2322,9 +2341,9 @@ static int wma_soc_set_hw_mode_resp_evt_handler(void *handle, return QDF_STATUS_E_NULL_VALUE; } - param_buf = (WMI_SOC_SET_HW_MODE_RESP_EVENTID_param_tlvs *) event; + param_buf = (WMI_PDEV_SET_HW_MODE_RESP_EVENTID_param_tlvs *) event; if (!param_buf) { - WMA_LOGE("Invalid WMI_SOC_SET_HW_MODE_RESP_EVENTID event"); + WMA_LOGE("Invalid WMI_PDEV_SET_HW_MODE_RESP_EVENTID event"); /* Need to send response back to upper layer to free * active command list */ @@ -2341,13 +2360,20 @@ static int wma_soc_set_hw_mode_resp_evt_handler(void *handle, wmi_event->cfgd_hw_mode_index, wmi_event->num_vdev_mac_entries); vdev_mac_entry = - param_buf->wmi_soc_set_hw_mode_response_vdev_mac_mapping; + param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping; /* Store the vdev-mac map in WMA and prepare to send to PE */ for (i = 0; i < wmi_event->num_vdev_mac_entries; i++) { - uint32_t vdev_id, mac_id; + uint32_t vdev_id, mac_id, pdev_id; vdev_id = vdev_mac_entry[i].vdev_id; - mac_id = vdev_mac_entry[i].mac_id; + pdev_id = vdev_mac_entry[i].pdev_id; + if (pdev_id == WMI_PDEV_ID_SOC) { + WMA_LOGE("%s: soc level id received for mac id)", + __func__); + QDF_BUG(0); + goto fail; + } + mac_id = WMA_PDEV_TO_MAC_MAP(vdev_mac_entry[i].pdev_id); WMA_LOGI("%s: vdev_id:%d mac_id:%d", __func__, vdev_id, mac_id); @@ -2370,7 +2396,7 @@ static int wma_soc_set_hw_mode_resp_evt_handler(void *handle, WMA_LOGI("%s: Updated: old_hw_mode_index:%d new_hw_mode_index:%d", __func__, wma->old_hw_mode_index, wma->new_hw_mode_index); - wma_send_msg(wma, SIR_HAL_SOC_SET_HW_MODE_RESP, + wma_send_msg(wma, SIR_HAL_PDEV_SET_HW_MODE_RESP, (void *) hw_mode_resp, 0); return QDF_STATUS_SUCCESS; @@ -2380,33 +2406,33 @@ fail: hw_mode_resp->status = SET_HW_MODE_STATUS_ECANCELED; hw_mode_resp->cfgd_hw_mode_index = 0; hw_mode_resp->num_vdev_mac_entries = 0; - wma_send_msg(wma, SIR_HAL_SOC_SET_HW_MODE_RESP, + wma_send_msg(wma, SIR_HAL_PDEV_SET_HW_MODE_RESP, (void *) hw_mode_resp, 0); return QDF_STATUS_E_FAILURE; } /** - * wma_soc_hw_mode_transition_evt_handler() - HW mode transition evt handler + * wma_pdev_hw_mode_transition_evt_handler() - HW mode transition evt handler * @handle: WMI handle * @event: Event recevied from FW * @len: Length of the event * - * Event handler for WMI_SOC_HW_MODE_TRANSITION_EVENTID that indicates an + * Event handler for WMI_PDEV_HW_MODE_TRANSITION_EVENTID that indicates an * asynchronous hardware mode transition. This event notifies the host driver * that firmware independently changed the hardware mode for some reason, such * as Coex, LFR 3.0, etc * * Return: Success on receiving valid params from FW */ -static int wma_soc_hw_mode_transition_evt_handler(void *handle, +static int wma_pdev_hw_mode_transition_evt_handler(void *handle, uint8_t *event, uint32_t len) { uint32_t i; - WMI_SOC_HW_MODE_TRANSITION_EVENTID_param_tlvs *param_buf; - wmi_soc_hw_mode_transition_event_fixed_param *wmi_event; - wmi_soc_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry; + WMI_PDEV_HW_MODE_TRANSITION_EVENTID_param_tlvs *param_buf; + wmi_pdev_hw_mode_transition_event_fixed_param *wmi_event; + wmi_pdev_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry; struct sir_hw_mode_trans_ind *hw_mode_trans_ind; tp_wma_handle wma = (tp_wma_handle) handle; @@ -2416,10 +2442,10 @@ static int wma_soc_hw_mode_transition_evt_handler(void *handle, return QDF_STATUS_E_NULL_VALUE; } - param_buf = (WMI_SOC_HW_MODE_TRANSITION_EVENTID_param_tlvs *) event; + param_buf = (WMI_PDEV_HW_MODE_TRANSITION_EVENTID_param_tlvs *) event; if (!param_buf) { /* This is an async event. So, not sending any event to LIM */ - WMA_LOGE("Invalid WMI_SOC_HW_MODE_TRANSITION_EVENTID event"); + WMA_LOGE("Invalid WMI_PDEV_HW_MODE_TRANSITION_EVENTID event"); return QDF_STATUS_E_FAILURE; } @@ -2439,13 +2465,22 @@ static int wma_soc_hw_mode_transition_evt_handler(void *handle, wmi_event->new_hw_mode_index, wmi_event->num_vdev_mac_entries); vdev_mac_entry = - param_buf->wmi_soc_set_hw_mode_response_vdev_mac_mapping; + param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping; /* Store the vdev-mac map in WMA and prepare to send to HDD */ for (i = 0; i < wmi_event->num_vdev_mac_entries; i++) { - uint32_t vdev_id, mac_id; + uint32_t vdev_id, mac_id, pdev_id; vdev_id = vdev_mac_entry[i].vdev_id; - mac_id = vdev_mac_entry[i].mac_id; + pdev_id = vdev_mac_entry[i].pdev_id; + + if (pdev_id == WMI_PDEV_ID_SOC) { + WMA_LOGE("%s: soc level id received for mac id)", + __func__); + QDF_BUG(0); + return QDF_STATUS_E_FAILURE; + } + + mac_id = WMA_PDEV_TO_MAC_MAP(vdev_mac_entry[i].pdev_id); WMA_LOGI("%s: vdev_id:%d mac_id:%d", __func__, vdev_id, mac_id); @@ -2462,32 +2497,32 @@ static int wma_soc_hw_mode_transition_evt_handler(void *handle, __func__, wma->old_hw_mode_index, wma->new_hw_mode_index); /* Pass the message to PE */ - wma_send_msg(wma, SIR_HAL_SOC_HW_MODE_TRANS_IND, + wma_send_msg(wma, SIR_HAL_PDEV_HW_MODE_TRANS_IND, (void *) hw_mode_trans_ind, 0); return QDF_STATUS_SUCCESS; } /** - * wma_soc_set_dual_mode_config_resp_evt_handler() - Dual mode evt handler + * wma_pdev_set_dual_mode_config_resp_evt_handler() - Dual mode evt handler * @handle: WMI handle * @event: Event received from FW * @len: Length of the event * * Notifies the host driver of the completion or failure of a - * WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID command. This event would be returned to + * WMI_PDEV_SET_MAC_CONFIG_CMDID command. This event would be returned to * the host driver once the firmware has completed a reconfiguration of the Scan * and FW mode configuration. This changes could include entering or leaving a * dual mac configuration for either scan and/or more permanent firmware mode. * * Return: Success on receiving valid params from FW */ -static int wma_soc_set_dual_mode_config_resp_evt_handler(void *handle, +static int wma_pdev_set_dual_mode_config_resp_evt_handler(void *handle, uint8_t *event, uint32_t len) { - WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID_param_tlvs *param_buf; - wmi_soc_set_dual_mac_config_response_event_fixed_param *wmi_event; + WMI_PDEV_SET_MAC_CONFIG_RESP_EVENTID_param_tlvs *param_buf; + wmi_pdev_set_mac_config_response_event_fixed_param *wmi_event; tp_wma_handle wma = (tp_wma_handle) handle; struct sir_dual_mac_config_resp *dual_mac_cfg_resp; @@ -2508,7 +2543,7 @@ static int wma_soc_set_dual_mode_config_resp_evt_handler(void *handle, return QDF_STATUS_E_NULL_VALUE; } - param_buf = (WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID_param_tlvs *) + param_buf = (WMI_PDEV_SET_MAC_CONFIG_RESP_EVENTID_param_tlvs *) event; if (!param_buf) { WMA_LOGE("%s: Invalid event", __func__); @@ -2531,7 +2566,7 @@ static int wma_soc_set_dual_mode_config_resp_evt_handler(void *handle, } /* Pass the message to PE */ - wma_send_msg(wma, SIR_HAL_SOC_DUAL_MAC_CFG_RESP, + wma_send_msg(wma, SIR_HAL_PDEV_MAC_CFG_RESP, (void *) dual_mac_cfg_resp, 0); return QDF_STATUS_SUCCESS; @@ -2539,7 +2574,7 @@ static int wma_soc_set_dual_mode_config_resp_evt_handler(void *handle, fail: WMA_LOGE("%s: Sending fail response to LIM", __func__); dual_mac_cfg_resp->status = SET_HW_MODE_STATUS_ECANCELED; - wma_send_msg(wma, SIR_HAL_SOC_DUAL_MAC_CFG_RESP, + wma_send_msg(wma, SIR_HAL_PDEV_MAC_CFG_RESP, (void *) dual_mac_cfg_resp, 0); return QDF_STATUS_E_FAILURE; @@ -2755,6 +2790,16 @@ QDF_STATUS wma_start(void *cds_ctx) goto end; } + status = wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_TSF_REPORT_EVENTID, + wma_vdev_tsf_handler, + WMA_RX_SERIALIZER_CTX); + if (0 != status) { + WMA_LOGP("%s: Failed to register tsf callback", __func__); + qdf_status = QDF_STATUS_E_FAILURE; + goto end; + } + /* Initialize the log flush complete event handler */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, WMI_DEBUG_MESG_FLUSH_COMPLETE_EVENTID, @@ -2766,10 +2811,10 @@ QDF_STATUS wma_start(void *cds_ctx) goto end; } - /* Initialize the WMI_SOC_SET_HW_MODE_RESP_EVENTID event handler */ + /* Initialize the wma_pdev_set_hw_mode_resp_evt_handler event handler */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, - WMI_SOC_SET_HW_MODE_RESP_EVENTID, - wma_soc_set_hw_mode_resp_evt_handler, + WMI_PDEV_SET_HW_MODE_RESP_EVENTID, + wma_pdev_set_hw_mode_resp_evt_handler, WMA_RX_SERIALIZER_CTX); if (status != QDF_STATUS_SUCCESS) { WMA_LOGE("Failed to register set hw mode resp event cb"); @@ -2779,8 +2824,8 @@ QDF_STATUS wma_start(void *cds_ctx) /* Initialize the WMI_SOC_HW_MODE_TRANSITION_EVENTID event handler */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, - WMI_SOC_HW_MODE_TRANSITION_EVENTID, - wma_soc_hw_mode_transition_evt_handler, + WMI_PDEV_HW_MODE_TRANSITION_EVENTID, + wma_pdev_hw_mode_transition_evt_handler, WMA_RX_SERIALIZER_CTX); if (status != QDF_STATUS_SUCCESS) { WMA_LOGE("Failed to register hw mode transition event cb"); @@ -2790,8 +2835,8 @@ QDF_STATUS wma_start(void *cds_ctx) /* Initialize the set dual mac configuration event handler */ status = wmi_unified_register_event_handler(wma_handle->wmi_handle, - WMI_SOC_SET_DUAL_MAC_CONFIG_RESP_EVENTID, - wma_soc_set_dual_mode_config_resp_evt_handler, + WMI_PDEV_SET_MAC_CONFIG_RESP_EVENTID, + wma_pdev_set_dual_mode_config_resp_evt_handler, WMA_RX_SERIALIZER_CTX); if (status != QDF_STATUS_SUCCESS) { WMA_LOGE("Failed to register hw mode transition event cb"); @@ -3901,6 +3946,20 @@ int wma_rx_service_ready_event(void *handle, uint8_t *cmd_param_info, return -EINVAL; } + /* mac_id is replaced with pdev_id in converged firmware to have + * multi-radio support. In order to maintain backward compatibility + * with old fw, host needs to check WMI_SERVICE_DEPRECATED_REPLACE + * in service bitmap from FW and host needs to set use_pdev_id in + * wmi_resource_config to true. If WMI_SERVICE_DEPRECATED_REPLACE + * service is not set, then host shall not expect MAC ID from FW in + * VDEV START RESPONSE event and host shall use PDEV ID. + */ + if (WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap, + WMI_SERVICE_DEPRECATED_REPLACE)) + wma_handle->wlan_resource_config.use_pdev_id = true; + else + wma_handle->wlan_resource_config.use_pdev_id = false; + /* register the Enhanced Green AP event handler */ wma_register_egap_event_handle(wma_handle); @@ -5107,6 +5166,10 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) wma_get_temperature(wma_handle); qdf_mem_free(msg->bodyptr); break; + case WMA_TSF_GPIO_PIN: + wma_set_tsf_gpio_pin(wma_handle, msg->bodyval); + break; + #ifdef DHCP_SERVER_OFFLOAD case WMA_SET_DHCP_SERVER_OFFLOAD_CMD: wma_process_dhcpserver_offload(wma_handle, @@ -5171,8 +5234,8 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) (struct wmi_pcl_chan_weights *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; - case SIR_HAL_SOC_SET_HW_MODE: - wma_send_soc_set_hw_mode_cmd(wma_handle, + case SIR_HAL_PDEV_SET_HW_MODE: + wma_send_pdev_set_hw_mode_cmd(wma_handle, (struct sir_hw_mode *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; @@ -5216,8 +5279,8 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) (struct sir_dcc_update_ndl *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; - case SIR_HAL_SOC_DUAL_MAC_CFG_REQ: - wma_send_soc_set_dual_mac_config(wma_handle, + case SIR_HAL_PDEV_DUAL_MAC_CFG_REQ: + wma_send_pdev_set_dual_mac_config(wma_handle, (struct sir_dual_mac_config *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; @@ -5259,6 +5322,13 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) wma_remove_beacon_filter(wma_handle, msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WDA_BPF_GET_CAPABILITIES_REQ: + wma_get_bpf_capabilities(wma_handle); + break; + case WDA_BPF_SET_INSTRUCTIONS_REQ: + wma_set_bpf_instructions(wma_handle, msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: WMA_LOGD("unknow msg type %x", msg->type); @@ -5347,7 +5417,7 @@ QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle, } /** - * wma_send_soc_set_hw_mode_cmd() - Send WMI_SOC_SET_HW_MODE_CMDID to FW + * wma_send_pdev_set_hw_mode_cmd() - Send WMI_PDEV_SET_HW_MODE_CMDID to FW * @wma_handle: WMA handle * @msg: Structure containing the following parameters * @@ -5360,7 +5430,7 @@ QDF_STATUS wma_send_pdev_set_pcl_cmd(tp_wma_handle wma_handle, * * Return: Success if the cmd is sent successfully to the firmware */ -QDF_STATUS wma_send_soc_set_hw_mode_cmd(tp_wma_handle wma_handle, +QDF_STATUS wma_send_pdev_set_hw_mode_cmd(tp_wma_handle wma_handle, struct sir_hw_mode *msg) { struct sir_set_hw_mode_resp *param; @@ -5395,13 +5465,13 @@ fail: param->cfgd_hw_mode_index = 0; param->num_vdev_mac_entries = 0; WMA_LOGE("%s: Sending HW mode fail response to LIM", __func__); - wma_send_msg(wma_handle, SIR_HAL_SOC_SET_HW_MODE_RESP, + wma_send_msg(wma_handle, SIR_HAL_PDEV_SET_HW_MODE_RESP, (void *) param, 0); return QDF_STATUS_SUCCESS; } /** - * wma_send_soc_set_dual_mac_config() - Set dual mac config to FW + * wma_send_pdev_set_dual_mac_config() - Set dual mac config to FW * @wma_handle: WMA handle * @msg: Dual MAC config parameters * @@ -5409,9 +5479,11 @@ fail: * * Return: QDF_STATUS. 0 on success. */ -QDF_STATUS wma_send_soc_set_dual_mac_config(tp_wma_handle wma_handle, +QDF_STATUS wma_send_pdev_set_dual_mac_config(tp_wma_handle wma_handle, struct sir_dual_mac_config *msg) { + QDF_STATUS status; + if (!wma_handle) { WMA_LOGE("%s: WMA handle is NULL. Cannot issue command", __func__); @@ -5423,11 +5495,17 @@ QDF_STATUS wma_send_soc_set_dual_mac_config(tp_wma_handle wma_handle, return QDF_STATUS_E_NULL_VALUE; } + status = wmi_unified_pdev_set_dual_mac_config_cmd( + wma_handle->wmi_handle, + (struct wmi_dual_mac_config *)msg); + if (QDF_IS_STATUS_ERROR(status)) { + WMA_LOGE("%s: Failed to send WMI_PDEV_SET_DUAL_MAC_CONFIG_CMDID: %d", + __func__, status); + return status; + } - if (wmi_unified_soc_set_dual_mac_config_cmd(wma_handle->wmi_handle, - (struct wmi_dual_mac_config *)msg)) - WMA_LOGE("%s: Failed to send WMI_SOC_SET_DUAL_MAC_CONFIG_CMDID", - __func__); + wma_handle->dual_mac_cfg.req_scan_config = msg->scan_config; + wma_handle->dual_mac_cfg.req_fw_mode_config = msg->fw_mode_config; return QDF_STATUS_SUCCESS; } diff --git a/core/wma/src/wma_mgmt.c b/core/wma/src/wma_mgmt.c index e7a0ca05d3ab..60ac1ba4454a 100644 --- a/core/wma/src/wma_mgmt.c +++ b/core/wma/src/wma_mgmt.c @@ -2343,6 +2343,7 @@ void wma_send_beacon(tp_wma_handle wma, tpSendbeaconParams bcn_info) ¶m); if (QDF_IS_STATUS_ERROR(status)) { WMA_LOGE("%s : failed to send vdev up", __func__); + cds_set_do_hw_mode_change_flag(false); return; } wma->interfaces[vdev_id].vdev_up = true; diff --git a/core/wma/src/wma_scan_roam.c b/core/wma/src/wma_scan_roam.c index fc08eef58e72..841b04e8acb8 100644 --- a/core/wma/src/wma_scan_roam.c +++ b/core/wma/src/wma_scan_roam.c @@ -51,12 +51,14 @@ #include "qdf_types.h" #include "qdf_mem.h" #include "ol_txrx_peer_find.h" +#include "ol_htt_api.h" #include "wma_types.h" #include "lim_api.h" #include "lim_session_utils.h" #include "cds_utils.h" +#include "cds_concurrency.h" #if !defined(REMOVE_PKT_LOG) #include "pktlog_ac.h" @@ -237,19 +239,21 @@ QDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, cmd->repeat_probe_time = cmd->dwell_time_active / WMA_SCAN_NPROBES_DEFAULT; - /* CSR sends only one value restTime for staying on home channel - * to continue data traffic. Rome fw has facility to monitor the traffic - * and move to next channel. Stay on the channel for at least half - * of the requested time and then leave if there is no traffic. + /* CSR sends min_rest_Time, max_rest_time and idle_time + * for staying on home channel to continue data traffic. + * Rome fw has facility to monitor the traffic + * and move to next channel. Stay on the channel for min_rest_time + * and then leave if there is no traffic. */ - cmd->min_rest_time = scan_req->restTime / 2; + cmd->min_rest_time = scan_req->min_rest_time; cmd->max_rest_time = scan_req->restTime; /* Check for traffic at idle_time interval after min_rest_time. * Default value is 25 ms to allow full use of max_rest_time * when voice packets are running at 20 ms interval. */ - cmd->idle_time = WMA_SCAN_IDLE_TIME_DEFAULT; + cmd->idle_time = scan_req->idle_time; + /* Large timeout value for full scan cycle, 30 seconds */ cmd->max_scan_time = WMA_HW_DEF_SCAN_MAX_DURATION; @@ -295,20 +299,6 @@ QDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, WMA_3PORT_CONC_SCAN_MAX_BURST_DURATION; break; } - if (wma_is_sap_active(wma_handle)) { - /* Background scan while SoftAP is sending beacons. - * Max duration of CTS2self is 32 ms, which limits - * the dwell time. - */ - cmd->dwell_time_active = - QDF_MIN(scan_req->maxChannelTime, - (WMA_CTS_DURATION_MS_MAX - - WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME)); - cmd->dwell_time_passive = - cmd->dwell_time_active; - cmd->burst_duration = 0; - break; - } if (wma_handle->miracast_value && wma_is_mcc_24G(wma_handle)) { cmd->max_rest_time = @@ -414,6 +404,20 @@ QDF_STATUS wma_get_buf_start_scan_cmd(tp_wma_handle wma_handle, } } + if (wma_is_sap_active(wma_handle)) { + /* P2P/STA scan while SoftAP is sending beacons. + * Max duration of CTS2self is 32 ms, which limits the + * dwell time. + */ + cmd->dwell_time_active = + QDF_MIN(scan_req->maxChannelTime, + (WMA_CTS_DURATION_MS_MAX - + WMA_ROAM_SCAN_CHANNEL_SWITCH_TIME)); + cmd->dwell_time_passive = + cmd->dwell_time_active; + cmd->burst_duration = 0; + } + cmd->n_probes = (cmd->repeat_probe_time > 0) ? cmd->dwell_time_active / cmd->repeat_probe_time : 0; if (scan_req->channelList.numChannels) { @@ -2078,15 +2082,12 @@ int wma_roam_synch_event_handler(void *handle, uint8_t *event, goto cleanup_label; } bss_desc_ptr = qdf_mem_malloc(sizeof(tSirBssDescription) + ie_len); - roam_synch_ind_ptr->join_rsp = qdf_mem_malloc(sizeof(tSirSmeJoinRsp)); - if ((NULL == roam_synch_ind_ptr->join_rsp) || (NULL == bss_desc_ptr)) { + if (NULL == bss_desc_ptr) { WMA_LOGE("LFR3: mem alloc failed!"); QDF_ASSERT(bss_desc_ptr != NULL); - QDF_ASSERT(roam_synch_ind_ptr->join_rsp != NULL); status = -ENOMEM; goto cleanup_label; } - qdf_mem_zero(roam_synch_ind_ptr->join_rsp, sizeof(tSirSmeJoinRsp)); qdf_mem_zero(bss_desc_ptr, sizeof(tSirBssDescription) + ie_len); wma->pe_roam_synch_cb((tpAniSirGlobal)wma->mac_context, roam_synch_ind_ptr, bss_desc_ptr); @@ -2446,6 +2447,112 @@ void wma_process_roam_synch_complete(WMA_HANDLE handle, uint8_t vdev_id) #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ /** + * wma_switch_channel() - WMA api to switch channel dynamically + * @wma: Pointer of WMA context + * @req: Pointer vdev_start having channel switch info. + * + * Return: 0 for success, otherwise appropriate error code + */ +QDF_STATUS wma_switch_channel(tp_wma_handle wma, struct wma_vdev_start_req *req) +{ + + wmi_buf_t buf; + wmi_channel *cmd; + int32_t len, ret; + WLAN_PHY_MODE chanmode; + struct wma_txrx_node *intr = wma->interfaces; + tpAniSirGlobal pmac; + + pmac = cds_get_context(QDF_MODULE_ID_PE); + + if (pmac == NULL) { + WMA_LOGE("%s: vdev start failed as pmac is NULL", __func__); + return QDF_STATUS_E_FAILURE; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + cmd = (wmi_channel *)wmi_buf_data(buf); + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_channel, + WMITLV_GET_STRUCT_TLVLEN(wmi_channel)); + + /* Fill channel info */ + cmd->mhz = cds_chan_to_freq(req->chan); + chanmode = wma_chan_to_mode(req->chan, req->chan_width, + req->vht_capable, req->dot11_mode); + + intr[req->vdev_id].chanmode = chanmode; /* save channel mode */ + intr[req->vdev_id].ht_capable = req->ht_capable; + intr[req->vdev_id].vht_capable = req->vht_capable; + intr[req->vdev_id].config.gtx_info.gtxRTMask[0] = + CFG_TGT_DEFAULT_GTX_HT_MASK; + intr[req->vdev_id].config.gtx_info.gtxRTMask[1] = + CFG_TGT_DEFAULT_GTX_VHT_MASK; + intr[req->vdev_id].config.gtx_info.gtxUsrcfg = + CFG_TGT_DEFAULT_GTX_USR_CFG; + intr[req->vdev_id].config.gtx_info.gtxPERThreshold = + CFG_TGT_DEFAULT_GTX_PER_THRESHOLD; + intr[req->vdev_id].config.gtx_info.gtxPERMargin = + CFG_TGT_DEFAULT_GTX_PER_MARGIN; + intr[req->vdev_id].config.gtx_info.gtxTPCstep = + CFG_TGT_DEFAULT_GTX_TPC_STEP; + intr[req->vdev_id].config.gtx_info.gtxTPCMin = + CFG_TGT_DEFAULT_GTX_TPC_MIN; + intr[req->vdev_id].config.gtx_info.gtxBWMask = + CFG_TGT_DEFAULT_GTX_BW_MASK; + intr[req->vdev_id].mhz = cmd->mhz; + + WMI_SET_CHANNEL_MODE(cmd, chanmode); + cmd->band_center_freq1 = cmd->mhz; + + if (chanmode == MODE_11AC_VHT80) + cmd->band_center_freq1 = + cds_chan_to_freq(req->ch_center_freq_seg0); + + if ((chanmode == MODE_11NA_HT40) || (chanmode == MODE_11NG_HT40) || + (chanmode == MODE_11AC_VHT40)) { + if (req->chan_width == CH_WIDTH_80MHZ) + cmd->band_center_freq1 += 10; + else + cmd->band_center_freq1 -= 10; + } + cmd->band_center_freq2 = 0; + + /* Set half or quarter rate WMI flags */ + if (req->is_half_rate) + WMI_SET_CHANNEL_FLAG(cmd, WMI_CHAN_FLAG_HALF_RATE); + else if (req->is_quarter_rate) + WMI_SET_CHANNEL_FLAG(cmd, WMI_CHAN_FLAG_QUARTER_RATE); + + /* Find out min, max and regulatory power levels */ + WMI_SET_CHANNEL_REG_POWER(cmd, req->max_txpow); + WMI_SET_CHANNEL_MAX_TX_POWER(cmd, req->max_txpow); + + + WMA_LOGE("%s: freq %d channel %d chanmode %d center_chan %d center_freq2 %d reg_info_1: 0x%x reg_info_2: 0x%x, req->max_txpow: 0x%x", + __func__, cmd->mhz, req->chan, chanmode, + cmd->band_center_freq1, cmd->band_center_freq2, + cmd->reg_info_1, cmd->reg_info_2, req->max_txpow); + + + ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len, + WMI_PDEV_SET_CHANNEL_CMDID); + + if (ret < 0) { + WMA_LOGP("%s: Failed to send vdev start command", __func__); + qdf_nbuf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** * wma_set_channel() - set channel * @wma: wma handle * @params: switch channel parameters @@ -2521,17 +2628,30 @@ void wma_set_channel(tp_wma_handle wma, tpSwitchChannelParams params) (params->restart_on_chan_switch == true)) wma->interfaces[req.vdev_id].is_channel_switch = true; - status = wma_vdev_start(wma, &req, + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam() && + wma_is_vdev_up(vdev_id)) { + status = wma_switch_channel(wma, &req); + if (status != QDF_STATUS_SUCCESS) + WMA_LOGE("%s: wma_switch_channel failed %d\n", __func__, + status); + + ol_htt_mon_note_chan(pdev, req.chan); + } else { + status = wma_vdev_start(wma, &req, wma->interfaces[req.vdev_id].is_channel_switch); - if (status != QDF_STATUS_SUCCESS) { - wma_remove_vdev_req(wma, req.vdev_id, - WMA_TARGET_REQ_TYPE_VDEV_START); - WMA_LOGP("%s: vdev start failed status = %d", __func__, status); - goto send_resp; - } + if (status != QDF_STATUS_SUCCESS) { + wma_remove_vdev_req(wma, req.vdev_id, + WMA_TARGET_REQ_TYPE_VDEV_START); + WMA_LOGP("%s: vdev start failed status = %d", __func__, status); + goto send_resp; + } + + if (wma->interfaces[req.vdev_id].is_channel_switch) + wma->interfaces[req.vdev_id].is_channel_switch = false; - if (wma->interfaces[req.vdev_id].is_channel_switch) - wma->interfaces[req.vdev_id].is_channel_switch = false; + if (QDF_GLOBAL_MONITOR_MODE == cds_get_conparam()) + ol_htt_mon_note_chan(pdev, req.chan); + } return; send_resp: WMA_LOGD("%s: channel %d ch_width %d txpower %d status %d", __func__, diff --git a/target/inc/wlan_tgt_def_config.h b/target/inc/wlan_tgt_def_config.h index 0a142008cde2..b1a2582fa19d 100644 --- a/target/inc/wlan_tgt_def_config.h +++ b/target/inc/wlan_tgt_def_config.h @@ -125,6 +125,8 @@ #define CFG_TGT_RX_DECAP_MODE (0x2) /* Decap to native Wifi header */ #define CFG_TGT_RX_DECAP_MODE_NWIFI (0x1) +/* Decap to raw mode header */ +#define CFG_TGT_RX_DECAP_MODE_RAW (0x0) /* maximum number of pending scan requests */ #define CFG_TGT_DEFAULT_SCAN_MAX_REQS 0x4 diff --git a/uapi/linux/osapi_linux.h b/uapi/linux/osapi_linux.h index 21f8ff629ab1..a62b96d3f613 100644 --- a/uapi/linux/osapi_linux.h +++ b/uapi/linux/osapi_linux.h @@ -231,7 +231,6 @@ void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q); #include "ath_carr_pltfrm.h" #endif /* QCA_PARTNER_PLATFORM */ -#define SLOTS_PER_DATAPATH_TX 2 #else /* __KERNEL__ */ #ifdef __GNUC__ |
