diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb index 75baf29cc..9471f93d7 100644 --- a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb +++ b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm.bb @@ -35,6 +35,7 @@ FW_QCA65X4_SDIO_PROPRIETARY = " \ file://qca65X4_sdio_proprietary/qwlan30.bin \ file://qca65X4_sdio_proprietary/utf30.bin \ " +FW_QCA65X4_SDIO_CCX = "file://qca65X4_sdio_proprietary/qwlan30-ccx.bin" # Firmware files for QCA6574 (Qualcomm proprietary driver) FW_QCA65X4_PCIE_PROPRIETARY = " \ @@ -44,6 +45,7 @@ FW_QCA65X4_PCIE_PROPRIETARY = " \ file://qca65X4_pcie_proprietary/qwlan30.bin \ file://qca65X4_pcie_proprietary/utf.bin \ " +FW_QCA65X4_PCIE_CCX = "" # Firmware files for QCA6574 (Qualcomm community driver) # NOTE: the community file 'board.bin' must be substituted by proprietary @@ -60,13 +62,24 @@ FW_QCA6574_WIFI_COMMUNITY = " \ FW_QUALCOMM_WIFI ?= "${FW_QCA65X4_SDIO_PROPRIETARY}" FW_QUALCOMM_WIFI:ccimx8x = "${@oe.utils.conditional('QUALCOMM_WIFI_DRIVER', 'community', '${FW_QCA6574_WIFI_COMMUNITY}', '${FW_QCA65X4_PCIE_PROPRIETARY}', d)}" +FW_QUALCOMM_CCX ?= "${FW_QCA65X4_SDIO_CCX}" +FW_QUALCOMM_CCX:ccimx8x = "${@oe.utils.conditional('QUALCOMM_WIFI_DRIVER', 'community', '', '${FW_QCA65X4_PCIE_CCX}', d)}" + SRC_URI = " \ ${FW_QUALCOMM_BT} \ ${FW_QUALCOMM_WIFI} \ + ${@oe.utils.vartrue('QUALCOMM_FW_CCX_TAGS', '${FW_QUALCOMM_CCX}', '', d)} \ " S = "${WORKDIR}" +do_unpack[postfuncs] += "${@oe.utils.vartrue('QUALCOMM_FW_CCX_TAGS', 'copy_ccx_fw', '', d)}" +copy_ccx_fw() { + FW_CCX_FILE="$(echo ${FW_QUALCOMM_CCX} | sed -e 's,file\:\/\/,,g')" + FW_NOCCX_FILE="$(echo ${FW_CCX_FILE} | sed -e 's,-ccx,,g')" + cp --remove-destination ${WORKDIR}/${FW_CCX_FILE} ${WORKDIR}/${FW_NOCCX_FILE} +} + do_install() { # BT firmware (remove 'file://' from variable with files list) BT_FW_FILES=$(echo ${FW_QUALCOMM_BT} | sed -e 's,file\:\/\/,,g') diff --git a/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_sdio_proprietary/qwlan30-ccx.bin b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_sdio_proprietary/qwlan30-ccx.bin new file mode 100644 index 000000000..633fc6d93 Binary files /dev/null and b/meta-digi-arm/recipes-bsp/firmware-qualcomm/firmware-qualcomm/qca65X4_sdio_proprietary/qwlan30-ccx.bin differ diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb index 8c11a96d8..4d8d6d7a1 100644 --- a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm.bb @@ -25,8 +25,14 @@ SRC_URI:append = " \ file://81-qcom-wifi.rules \ " +FILES_SDIO_CCX = " \ + file://WCNSS_qcom_cfg-ccx.ini \ + file://0001-add-CCX-tags-support-for-kernel-v5.15.patch \ +" + FILES_SDIO = " \ file://modprobe-qualcomm.conf \ + ${@oe.utils.vartrue('QUALCOMM_FW_CCX_TAGS', '${FILES_SDIO_CCX}', '', d)} \ " SRC_URI:append = "${@oe.utils.conditional('QUALCOMM_WIFI_INTERFACE', 'sdio' , '${FILES_SDIO}', '', d)}" @@ -68,6 +74,11 @@ do_install:append() { install -m 0644 ${WORKDIR}/git/firmware_bin/WCNSS_qcom_cfg.ini ${D}${base_libdir}/firmware/wlan/qcom_cfg.ini install -d ${D}${sysconfdir}/udev/rules.d install -m 0644 ${WORKDIR}/81-qcom-wifi.rules ${D}${sysconfdir}/udev/rules.d/ + + # Overwrite "qcom_cfg.ini" if QUALCOMM_FW_CCX_TAGS is enabled + if [ -f "${WORKDIR}/WCNSS_qcom_cfg-ccx.ini" ]; then + cp --remove-destination ${WORKDIR}/WCNSS_qcom_cfg-ccx.ini ${D}${base_libdir}/firmware/wlan/qcom_cfg.ini + fi } do_install:append:ccimx6ul() { diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/0001-add-CCX-tags-support-for-kernel-v5.15.patch b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/0001-add-CCX-tags-support-for-kernel-v5.15.patch new file mode 100644 index 000000000..9e64e87c1 --- /dev/null +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/0001-add-CCX-tags-support-for-kernel-v5.15.patch @@ -0,0 +1,1681 @@ +From: Isaac Hermida +Date: Thu, 25 Aug 2022 10:15:31 +0200 +Subject: [PATCH] add CCX tags support for kernel v5.15 + +https://onedigi.atlassian.net/browse/DEL-8038 + +Signed-off-by: Isaac Hermida +--- + CORE/HDD/inc/CcxTagDefs.h | 396 +++++++++++++ + CORE/HDD/inc/wlan_hdd_ccx_tag.h | 19 + + CORE/HDD/src/wlan_hdd_ccx_tag.c | 833 ++++++++++++++++++++++++++++ + CORE/HDD/src/wlan_hdd_main.c | 20 + + CORE/MAC/inc/aniGlobal.h | 4 + + CORE/MAC/inc/qwlan_version.h | 3 +- + CORE/MAC/src/include/sirParams.h | 6 + + CORE/SERVICES/COMMON/wmi_tlv_defs.h | 19 +- + CORE/SERVICES/COMMON/wmi_unified.h | 75 ++- + CORE/SERVICES/WMA/wma.c | 80 +++ + CORE/SERVICES/WMI/wmi_unified.c | 3 + + Kbuild | 2 + + 12 files changed, 1456 insertions(+), 4 deletions(-) + create mode 100644 CORE/HDD/inc/CcxTagDefs.h + create mode 100644 CORE/HDD/inc/wlan_hdd_ccx_tag.h + create mode 100644 CORE/HDD/src/wlan_hdd_ccx_tag.c + +diff --git a/CORE/HDD/inc/CcxTagDefs.h b/CORE/HDD/inc/CcxTagDefs.h +new file mode 100644 +index 000000000000..b0b337c4ec47 +--- /dev/null ++++ b/CORE/HDD/inc/CcxTagDefs.h +@@ -0,0 +1,396 @@ ++/****************************************************************/ ++/* */ ++/* Copyright 2018 Digi International, Inc. All Rights Reserved. */ ++/* */ ++/****************************************************************/ ++ ++#ifndef CCX_TAG_DEFS_H_ ++#define CCX_TAG_DEFS_H_ ++ ++#include ++ ++/* Fixed Netlink Communication Fields */ ++#define CCX_TAG_FAMILY_NAME ("CCX_TAG") ++ ++/* Netlink Attributes */ ++typedef enum CcxTagAttrTypeTag ++{ ++ /* Reserved position of 0, enforced by the Netlink protocol. Unused by both API and driver.*/ ++ CCX_TAG_ATTR_UNUSED, ++ ++ /* Identifier of command that initiated a response. API to Driver and Driver to API.*/ ++ CCX_TAG_ATTR_CMD, ++ ++ /* Identifier of command instance to pair responses to original commands. API to Driver and Driver to API.*/ ++ CCX_TAG_ATTR_SEQUENCE, ++ ++ /* Identifier of response to command. Driver to API.*/ ++ CCX_TAG_ATTR_RSP, ++ ++ /* Protocol version of API. API to Driver.*/ ++ CCX_TAG_ATTR_API_VERSION, ++ ++ /* Protocol version of driver. Driver to API.*/ ++ CCX_TAG_ATTR_DRIVER_VERSION, ++ ++ /* Packet command and payload data. API to Driver.*/ ++ CCX_TAG_ATTR_TAG_COMMAND, ++ ++ /* Packet transmission operational state and results. Driver to API.*/ ++ CCX_TAG_ATTR_TAG_STATUS, ++ ++ /* Indicates the total number of attribute types.*/ ++ CCX_TAG_ATTR_COUNT, ++ ++ /* Indicates no attribute type is specified.*/ ++ CCX_TAG_ATTR_UNDEFINED, ++ ++ /* Indicates the attribute type specified is not valid.*/ ++ CCX_TAG_ATTR_INVALID ++ ++}CcxTagAttrType; ++ ++/* Netlink Commands */ ++typedef enum CcxTagCmdTypeTag ++{ ++ /* Push the API version to the driver and pull the driver */ ++ /* version to the API. This also performs a reset of the driver. */ ++ /* Must be first valid entry to ensure command can always be used, */ ++ /* regardless of protocol version. */ ++ /* */ ++ /* Input Attributes: */ ++ /* CCX_TAG_ATTR_API_VERSION */ ++ /* */ ++ /* Output Attributes: */ ++ /* CCX_TAG_ATTR_CMD_ECHO */ ++ /* CCX_TAG_ATTR_OP_STATE */ ++ /* CCX_TAG_ATTR_OP_ERROR */ ++ /* CCX_TAG_ATTR_DRIVER_VERSION */ ++ /* */ ++ CCX_TAG_CMD_CHECK_VERSION, ++ ++ /* Reset the current state within the driver. */ ++ /* */ ++ /* Input Attributes: */ ++ /* None */ ++ /* */ ++ /* Output Attributes: */ ++ /* CCX_TAG_ATTR_CMD_ECHO */ ++ /* CCX_TAG_ATTR_OP_STATE */ ++ /* CCX_TAG_ATTR_OP_ERROR */ ++ /* */ ++ CCX_TAG_CMD_RESET, ++ ++ /* Send a CCX Tag packet out over the air. */ ++ /* */ ++ /* Input Attributes: */ ++ /* CCX_TAG_ATTR_PACKET */ ++ /* */ ++ /* Output Attributes: */ ++ /* CCX_TAG_ATTR_CMD_ECHO */ ++ /* CCX_TAG_ATTR_OP_STATE */ ++ /* CCX_TAG_ATTR_OP_ERROR */ ++ /* */ ++ CCX_TAG_CMD_TRANSMIT, ++ ++ /* Obtain the current state within the driver. */ ++ /* */ ++ /* Input Attributes: */ ++ /* None */ ++ /* */ ++ /* Output Attributes: */ ++ /* CCX_TAG_ATTR_CMD_ECHO */ ++ /* CCX_TAG_ATTR_OP_STATE */ ++ /* CCX_TAG_ATTR_OP_ERROR */ ++ /* CCX_TAG_ATTR_ATTEMPT_COUNT */ ++ /* CCX_TAG_ATTR_FAILURE_COUNT */ ++ /* */ ++ CCX_TAG_CMD_STATUS, ++ ++ /* Indicates the total number of commands. */ ++ CCX_TAG_CMD_COUNT, ++ ++ /* Indicates a placeholder command for unset variables. */ ++ CCX_TAG_CMD_UNDEFINED, ++ ++ /* Indicates a placeholder command for the invalid range. */ ++ CCX_TAG_CMD_INVALID, ++ ++}CcxTagCmdType; ++ ++/* Netlink Responses */ ++typedef enum CcxTagDriverResponseTypeTag ++{ ++ /* The driver operation ran to completion without errors. */ ++ CCX_TAG_DRVR_RSP_OK, ++ ++ /* The driver failed to parse the Netlink message received. */ ++ CCX_TAG_DRVR_RSP_ERR_NL_PARSE, ++ ++ /* The driver version conflicts with the API version received. */ ++ CCX_TAG_DRVR_RSP_ERR_TAG_VERSION, ++ ++ /* The driver detected an incorrect size for the control data */ ++ /* block within the transmit message received. */ ++ CCX_TAG_DRVR_RSP_ERR_CTRL_SIZE, ++ ++ /* The driver detected an incorrect size for the packet data */ ++ /* block within the transmit message received. */ ++ CCX_TAG_DRVR_RSP_ERR_PACKET_SIZE, ++ ++ /* The driver detected an incorrect offset for either the channel */ ++ /* or fragment byte offset within the transmit message received. */ ++ CCX_TAG_DRVR_RSP_ERR_OFFSET_OVERRUN, ++ ++ /* The driver could not process the command received because */ ++ /* another operation is already in progress. */ ++ CCX_TAG_DRVR_RSP_ERR_OP_IN_PROG, ++ ++ /* The driver encountered an error during the */ ++ /* downstream handling of the command. */ ++ CCX_TAG_DRVR_RSP_ERR_OP_FAILED, ++ ++ /* Shortcut to total. */ ++ CCX_TAG_DRVR_RSP_COUNT, ++ ++ /* Placeholder for uninitialized variable. */ ++ CCX_TAG_DRVR_RSP_UNDEFINED, ++ ++ /* Placeholder for invalid enumeration in variable. */ ++ CCX_TAG_DRVR_RSP_INVALID ++}CcxTagDriverResponseType; ++ ++/* Driver State Machine States */ ++typedef enum CcxTagDriverOpStateTag ++{ ++ /* The driver has not yet processed a command. */ ++ CCX_TAG_DRVR_OP_IDLE, ++ ++ /* The driver is currently processing a command. */ ++ CCX_TAG_DRVR_OP_IN_PROG, ++ ++ /* The driver has finished processing a command, */ ++ /* and the operation completed successfully. */ ++ CCX_TAG_DRVR_OP_COMPLETE, ++ ++ /* The driver has encountered an unrecoverable error. */ ++ CCX_TAG_DRVR_OP_UNRECOVERABLE, ++ ++ /* Shortcut to total. */ ++ CCX_TAG_DRVR_OP_STATE_COUNT, ++ ++ /* Placeholder for uninitialized variable. */ ++ CCX_TAG_DRVR_OP_STATE_UNDEFINED, ++ ++ /* Placeholder for invalid enumeration in variable. */ ++ CCX_TAG_DRVR_OP_STATE_INVALID ++}CcxTagDriverOpState; ++ ++/* Wireless Module Firmware Result Codes. */ ++typedef enum CcxTagFirmwareStatusTag ++{ ++ /* The CCX Tag command was properly processed, */ ++ /* though transmit failures may have happened. */ ++ CCX_TAG_FW_STATUS_OK, ++ ++ /* Generic error. The transmit failed to */ ++ /* complete for an unknown reason. */ ++ CCX_TAG_FW_STATUS_ERROR = -1, ++ ++ /* Firmware was unable to allocate memory for the transmission. */ ++ CCX_TAG_FW_STATUS_MEM = 2, ++ ++ /* No free descriptors were available for the transmission. */ ++ CCX_TAG_FW_STATUS_NO_DESC = 4, ++ ++ /* An invalid parameter was found in the WMI command. */ ++ CCX_TAG_FW_STATUS_INVPRM = 14, ++ ++ /* The transmit operation was cancelled due to a */ ++ /* higher priority operation in the module. */ ++ CCX_TAG_FW_STATUS_CANCEL = 16, ++ ++ /* There was a hardware failure detected during the transmission. */ ++ CCX_TAG_FW_STATUS_HWFAIL = 23 ++ ++}CcxTagFirmwareStatus; ++ ++/* *** CCX Tag Attribute Format - Packet Attribute *** ++ * ++ * ControlDataTag ++ * - First segment of CCX Tag message ++ * - Length of control data specified in first 16 bits ++ * ++ * MPDU Header ++ * - Starts immediately after the control data, ++ * without additional padding ++ * - Length specified in control data ++ * ++ * Content Header ++ * - Starts immediately after the MPDU header, ++ * without additional padding ++ * - Length specified in control data ++ * ++ * Content Payload ++ * - Starts immediately after the content header, ++ * without additional padding ++ * - Length specified in control data ++ * ++ * Unspecified ++ * - MPDU footer, added by firmware ++ */ ++ ++ ++typedef struct CcxTagControlDataTag ++{ ++ /* The size of the packed control data header in the IPC message. */ ++ uint8_t ControlDataSize; ++ ++ /* This identifies the version of the IPC message format. */ ++ uint8_t ControlDataVersion; ++ ++ /* This specifies the packet area to insert the current burst */ ++ /* during transmission, in octets from the start of the MPDU header. */ ++ /* RawByteBuffer[Offset] |= Fragment */ ++ uint16_t FragmentOffsetOctets; ++ ++ /* This specifies the packet area to insert the active channel */ ++ /* during transmission, in octets from the start of the MPDU header. */ ++ /* RawByteBuffer[Offset] |= Channel */ ++ uint16_t ChannelOffsetOctets; ++ ++ /* The size of the packed MPDU header in the IPC message. */ ++ uint16_t MpduHeaderSize; ++ ++ /* The size of the packed CCX Tag content header in the IPC message. */ ++ uint16_t ContentHeaderSize; ++ ++ /* The size of the packed CCX Tag content payload in the IPC message. */ ++ uint16_t ContentPayloadSize; ++}CcxTagControlData; ++ ++#define CCX_TAG_CHANNEL_OFFSET (35) ++#define CCX_TAG_FRAGMENT_OFFSET (22) ++ ++typedef enum CcxTagVersionTag ++{ ++ CCX_TAG_VERSION = 1 ++}CcxTagVersion; ++ ++typedef enum CcxTagMacLengthTag ++{ ++ CCX_TAG_MAC_LENGTH = 6 ++}CcxTagMacLength; ++ ++typedef uint8_t CcxTagMacAddress[CCX_TAG_MAC_LENGTH]; ++ ++#define CCX_TAG_MC_DST_ADDR ("01:40:96:00:00:03") ++ ++#define CCX_TAG_UNUSED_ADDR ("00:00:00:00:00:00") ++ ++typedef struct CcxTagMpduHeaderTag ++{ ++ uint8_t FCS1; ++ uint8_t FCS2; ++ uint16_t Duration; ++ CcxTagMacAddress MAC1; ++ CcxTagMacAddress MAC2; ++ CcxTagMacAddress MAC3; ++ uint16_t SequenceControl; ++ CcxTagMacAddress MAC4; ++}CcxTagMpduHeader; ++ ++/* Fixed CCX Tag MPDU Header Fields */ ++#define CCX_TAG_FCS1_FIELD (0x08) ++#define CCX_TAG_FCS2_FIELD (0x03) ++#define CCX_TAG_DURATION_FIELD (0x00) ++ ++typedef struct CcxTagContentHeaderTag ++{ ++ union ++ { ++ uint8_t Word; ++ struct ++ { ++ uint8_t ContentVersion : 4; ++ uint8_t ContentPad : 4; ++ }Bits; ++ }ContentInfo; ++ uint8_t TransmitPower; ++ uint8_t TransmitChannel; ++ uint8_t RegulatoryClass; ++ uint8_t BurstLength; ++}CcxTagContentHeader; ++ ++/* Fixed CCX Tag Content Fields */ ++#define CCX_TAG_CONTENT_VERSION (0x0) ++#define CCX_TAG_DEFAULT_TX_POWER (0x0) ++#define CCX_TAG_DEFAULT_REG_CLASS (0x0) ++#define CCX_TAG_DEFAULT_BURST_LENGTH (3) ++ ++/* This structure is used internally within the wireless driver. */ ++typedef struct CcxTagWmiHeaderTag ++{ ++ /* This specifies the packet area to insert the current burst */ ++ /* during transmission, in bytes from the start of the MPDU header. */ ++ uint16_t FragmentOffsetOctets; ++ ++ /* This specifies the packet area to insert the active channel */ ++ /* during transmission, in bytes from the start of the MPDU header. */ ++ uint16_t ChannelOffsetOctets; ++ ++ CcxTagMpduHeader MpduHeader; ++ ++ CcxTagContentHeader ContentHeader; ++ ++ uint16_t ContentPayloadLength; ++}CcxTagWmiHeader; ++ ++/* This type defines common sizes used within the API and driver. */ ++typedef enum CcxTagDimensionTag ++{ ++ CCX_TAG_MPDU_HEADER_SIZE = 30, ++ ++ CCX_TAG_CONTENT_MAX_SIZE = 2312, ++ ++ CCX_TAG_CONTENT_HEADER_SIZE = 5, ++ ++ CCX_TAG_CONTENT_PAYLOAD_MAX_SIZE = (CCX_TAG_CONTENT_MAX_SIZE - CCX_TAG_CONTENT_HEADER_SIZE), ++ ++ CCX_TAG_PACKET_MIN_SIZE = (CCX_TAG_MPDU_HEADER_SIZE + CCX_TAG_CONTENT_HEADER_SIZE), ++ ++ CCX_TAG_PACKET_MAX_SIZE = (CCX_TAG_MPDU_HEADER_SIZE + CCX_TAG_CONTENT_HEADER_SIZE + CCX_TAG_CONTENT_PAYLOAD_MAX_SIZE), ++ ++ CCX_TAG_CONTROL_DATA_SIZE = sizeof(CcxTagControlData), ++ ++ CCX_TAG_IPC_MSG_MIN_SIZE = (CCX_TAG_PACKET_MIN_SIZE + CCX_TAG_CONTROL_DATA_SIZE), ++ ++ CCX_TAG_IPC_MSG_MAX_SIZE = (CCX_TAG_PACKET_MAX_SIZE + CCX_TAG_CONTROL_DATA_SIZE) ++}CcxTagDimension; ++ ++typedef struct CcxTagStatusDataTag ++{ ++ /* The size of the packed status data header in the IPC message. */ ++ uint8_t StatusDataSize; ++ ++ /* This identifies the version of the IPC message format. */ ++ uint8_t StatusDataVersion; ++ ++ /* This specifies the current state of the driver. */ ++ CcxTagDriverOpState DriverOpState; ++ ++ /* This specifies the result of transmission, if the driver op */ ++ /* state shows that a transmission has completed. */ ++ CcxTagFirmwareStatus FirmwareStatus; ++ ++ /* The size of the packed CCX Tag content header in the IPC message. */ ++ uint16_t AttemptCount; ++ ++ /* The size of the packed CCX Tag content payload in the IPC message. */ ++ uint16_t FailureCount; ++}CcxTagStatusData; ++ ++/* Fixed CCX Tag Status Fields */ ++#define CCX_TAG_STATUS_VERSION (0x0) ++ ++#endif /* CCX_TAG_DEFS_H_ */ +diff --git a/CORE/HDD/inc/wlan_hdd_ccx_tag.h b/CORE/HDD/inc/wlan_hdd_ccx_tag.h +new file mode 100644 +index 000000000000..edc29332a2c0 +--- /dev/null ++++ b/CORE/HDD/inc/wlan_hdd_ccx_tag.h +@@ -0,0 +1,19 @@ ++/****************************************************************/ ++/* */ ++/* Copyright 2018 Digi International, Inc. All Rights Reserved. */ ++/* */ ++/****************************************************************/ ++ ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ ++#ifndef __WLAN_HDD_CCX_TAG_H__ ++#define __WLAN_HDD_CCX_TAG_H__ ++ ++int ccx_tag_activate_service(void *pAdapter); ++ ++int ccx_tag_deactivate_service(void); ++ ++#endif /* __WLAN_HDD_CCX_TAG_H__ */ ++ ++#endif /* FEATURE_CCX_TAG_SUPPORT */ ++ +diff --git a/CORE/HDD/src/wlan_hdd_ccx_tag.c b/CORE/HDD/src/wlan_hdd_ccx_tag.c +new file mode 100644 +index 000000000000..03697601bcb0 +--- /dev/null ++++ b/CORE/HDD/src/wlan_hdd_ccx_tag.c +@@ -0,0 +1,833 @@ ++/****************************************************************/ ++/* */ ++/* Copyright 2018 Digi International, Inc. All Rights Reserved. */ ++/* */ ++/****************************************************************/ ++ ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "qwlan_version.h" ++#include "vos_utils.h" ++#include "wma.h" ++#include "sirParams.h" ++#include "wmi_unified_api.h" ++ ++#include "CcxTagDefs.h" ++ ++static struct hdd_context_s *pHddCtx; ++ ++static uint32_t HDD_CCX_TAG_DRVR_VERSION = 1; ++static uint32_t hdd_ccx_tag_api_version = 0; ++static struct mutex hdd_ccx_tag_mutex; ++static CcxTagDriverOpState hdd_ccx_tag_drvr_op_state = CCX_TAG_DRVR_OP_IDLE; ++static CcxTagFirmwareStatus hdd_ccx_tag_fw_status = CCX_TAG_FW_STATUS_ERROR; ++static uint16_t hdd_ccx_tag_fw_attempts = 0; ++static uint16_t hdd_ccx_tag_fw_failures = 0; ++static int hdd_ccx_tag_fw_msgs_outstanding = 0; ++ ++/* handlers */ ++static int ccx_tag_check_version_cmd_handler(struct sk_buff *skb, struct genl_info *info); ++static int ccx_tag_reset_cmd_handler(struct sk_buff *skb, struct genl_info *info); ++static int ccx_tag_transmit_cmd_handler(struct sk_buff *skb, struct genl_info *info); ++static int ccx_tag_status_cmd_handler(struct sk_buff *skb, struct genl_info *info); ++ ++/* attribute policy */ ++static struct nla_policy ccx_tag_genl_policy[CCX_TAG_ATTR_COUNT] = ++{ ++ /* Reserved position of 0. */ ++ [CCX_TAG_ATTR_UNUSED] = { .type = NLA_STRING }, ++ ++ /* Identifier of command that initiated a response. API to Driver and Driver to API. */ ++ [CCX_TAG_ATTR_CMD] = { .type = NLA_BINARY, .len = sizeof(uint16_t) }, ++ ++ /* Identifier of command instance to pair responses to original commands. API to Driver and Driver to API. */ ++ [CCX_TAG_ATTR_SEQUENCE] = { .type = NLA_BINARY, .len = sizeof(uint16_t) }, ++ ++ /* Protocol version of API. API to Driver. */ ++ [CCX_TAG_ATTR_API_VERSION] = { .type = NLA_BINARY, .len = sizeof(uint32_t) }, ++ ++ /* Protocol version of driver. Driver to API. */ ++ [CCX_TAG_ATTR_DRIVER_VERSION] = { .type = NLA_BINARY, .len = sizeof(uint32_t) }, ++ ++ /* Packet data. API to Driver. */ ++ [CCX_TAG_ATTR_TAG_COMMAND] = { .type = NLA_BINARY, .len = CCX_TAG_IPC_MSG_MAX_SIZE }, ++ ++ /* Current operational error code, when in the error operational state. Driver to API. */ ++ [CCX_TAG_ATTR_TAG_STATUS] = { .type = NLA_BINARY, .len = sizeof(CcxTagDriverResponseType) }, ++}; ++ ++/* operation definition */ ++static struct genl_ops ccx_tag_gnl_ops_table[CCX_TAG_CMD_COUNT] = ++{ ++ { ++ .cmd = CCX_TAG_CMD_CHECK_VERSION, ++ .flags = 0, ++ .doit = ccx_tag_check_version_cmd_handler, ++ .dumpit = NULL, ++ }, ++ { ++ .cmd = CCX_TAG_CMD_RESET, ++ .flags = 0, ++ .doit = ccx_tag_reset_cmd_handler, ++ .dumpit = NULL, ++ }, ++ { ++ .cmd = CCX_TAG_CMD_TRANSMIT, ++ .flags = 0, ++ .doit = ccx_tag_transmit_cmd_handler, ++ .dumpit = NULL, ++ }, ++ { ++ .cmd = CCX_TAG_CMD_STATUS, ++ .flags = 0, ++ .doit = ccx_tag_status_cmd_handler, ++ .dumpit = NULL, ++ } ++}; ++ ++/* family definition */ ++static struct genl_family ccx_tag_gnl_family = ++{ ++ .hdrsize = 0, ++ .name = "CCX_TAG", ++ .version = 1, ++ .policy = ccx_tag_genl_policy, ++ .maxattr = CCX_TAG_ATTR_COUNT, ++ .ops = ccx_tag_gnl_ops_table, ++ .n_ops = ARRAY_SIZE(ccx_tag_gnl_ops_table), ++}; ++ ++ ++void RawBlockDisplay(uint8_t const * data, uint16_t length) ++{ ++ uint16_t byte = 0; ++ ++ if (length > 128) ++ { ++ length = 128; ++ } ++ ++ while (byte < length) ++ { ++ if (byte % 10 == 0) ++ { ++ printk(KERN_DEBUG "%3u: ", byte); ++ } ++ printk(KERN_CONT "0x%02X ", data[byte]); ++ byte++; ++ if (byte % 10 == 0) ++ { ++ printk(KERN_CONT "\n"); ++ } ++ } ++ ++ if (byte % 10 != 0) ++ { ++ printk(KERN_CONT "\n"); ++ } ++} ++ ++static void SendAttrData(uint16_t cmd_type, uint16_t seq_num, ++ uint16_t rsp_type, CcxTagAttrType attr_type, ++ uint8_t const * msg_buf, uint16_t msg_len, ++ struct genl_info *info) ++{ ++ int flags = 0; ++ int ret = 0; ++ int status = 0; ++ int has_attr = 0; ++ ++ /* Allocate a message buffer. */ ++ struct sk_buff * skb = NULL; ++ struct nlmsghdr * nlh = NULL; ++ ++ if ((attr_type > CCX_TAG_ATTR_UNUSED) ++ && (attr_type < CCX_TAG_ATTR_COUNT)) ++ { ++ if ((!msg_buf) || (msg_len == 0)) ++ { ++ /* Error - Invalid attribute parameters. Abandon Send. */ ++ goto nla_send_end; ++ } ++ else ++ { ++ has_attr = 1; ++ } ++ } ++ ++ /* Allocate the raw netlink socket buffer first. */ ++ skb = genlmsg_new(msg_len, GFP_KERNEL); ++ if (!skb) ++ { ++ /* Error - Socket buffer allocation failed. Abandon Send. */ ++ goto nla_put_failure; ++ } ++ ++ /* Set up the message header first. Use the same */ ++ /* sequence number to indicate that this is a reply to */ ++ /* the original command message. */ ++ nlh = genlmsg_put(skb, 0, info->snd_seq, ++ &ccx_tag_gnl_family, flags, cmd_type); ++ if (nlh == NULL) ++ { ++ /* Error - Message header fill failed. Abandon Send. */ ++ goto nla_put_failure; ++ } ++ ++ /* Add message command echo as an attribute. */ ++ ret = nla_put(skb, CCX_TAG_ATTR_CMD, sizeof(cmd_type), &cmd_type); ++ if (ret != 0) ++ { ++ /* Error - Message cmd fill failed. Abandon Send. */ ++ goto nla_put_failure; ++ } ++ ++ /* Add message sequence as an attribute. */ ++ ret = nla_put(skb, CCX_TAG_ATTR_SEQUENCE, sizeof(seq_num), &seq_num); ++ if (ret != 0) ++ { ++ /* Error - Message seq fill failed. Abandon Send. */ ++ goto nla_put_failure; ++ } ++ ++ /* Add message response as an attribute. */ ++ ret = nla_put(skb, CCX_TAG_ATTR_RSP, sizeof(rsp_type), &rsp_type); ++ if (ret != 0) ++ { ++ /* Error - Message rsp fill failed. Abandon Send. */ ++ goto nla_put_failure; ++ } ++ ++ if (has_attr) ++ { ++ /* Add message data as an attribute. */ ++ ret = nla_put(skb, attr_type, msg_len, msg_buf); ++ if (ret != 0) ++ { ++ /* Error - Message data fill failed. Abandon Send. */ ++ goto nla_put_failure; ++ } ++ } ++ ++ /* Finalize the message. */ ++ genlmsg_end(skb, nlh); ++ ++ /* Send the message. */ ++ ret = genlmsg_unicast(genl_info_net(info), skb, info->snd_portid); ++ ++ status = (ret == 0); ++ ++ goto nla_send_end; ++ ++nla_put_failure: ++ ++ if (skb) ++ { ++ nlmsg_free(skb); ++ } ++ status = 0; ++ ++nla_send_end: ++ ++ return; ++} ++ ++static int RecvCcxTagWmaRsp(WMA_HANDLE handle, u_int8_t* data, u_int32_t len) ++{ ++ WMI_STA_TAG_PKT_INJ_COMP_EVENTID_param_tlvs *param_buf = NULL; ++ wmi_sta_tag_pkt_inj_comp_fixed_param *wmi_event = NULL; ++ ++ param_buf = (WMI_STA_TAG_PKT_INJ_COMP_EVENTID_param_tlvs *)data; ++ if (param_buf) ++ { ++ wmi_event = param_buf->fixed_param; ++ if (wmi_event) ++ { ++ mutex_lock(&hdd_ccx_tag_mutex); ++ if (hdd_ccx_tag_drvr_op_state == CCX_TAG_DRVR_OP_IN_PROG) ++ { ++ hdd_ccx_tag_drvr_op_state = CCX_TAG_DRVR_OP_COMPLETE; ++ hdd_ccx_tag_fw_status = wmi_event->txStatus; ++ hdd_ccx_tag_fw_attempts = wmi_event->totalTxAttempts; ++ hdd_ccx_tag_fw_failures = wmi_event->totalTxFailures; ++ } ++ else ++ { ++ /* Unexpected callback from firmware. Report error. */ ++ hdd_ccx_tag_drvr_op_state = CCX_TAG_DRVR_OP_IDLE; ++ hdd_ccx_tag_fw_status = CCX_TAG_FW_STATUS_ERROR; ++ hdd_ccx_tag_fw_attempts = 0; ++ hdd_ccx_tag_fw_failures = 0; ++ } ++ mutex_unlock(&hdd_ccx_tag_mutex); ++ } ++ } ++ ++ return VOS_STATUS_SUCCESS; ++} ++ ++static VOS_STATUS SendCcxTagWmaCmd(CcxTagWmiHeader const * pHeader, u8 const * pData) ++{ ++ VOS_STATUS status = VOS_STATUS_SUCCESS; ++ CcxTagWmiHeader * pCcxTagReqHeader = NULL; ++ tANI_U32 reqLen = 0; ++ ++ mutex_lock(&hdd_ccx_tag_mutex); ++ ++ if ((NULL == pHeader) || ((pHeader->ContentPayloadLength > 0) && (NULL == pData))) ++ { ++ status = VOS_STATUS_E_INVAL; ++ } ++ ++ if (status == VOS_STATUS_SUCCESS) ++ { ++ reqLen = sizeof(CcxTagWmiHeader) + pHeader->ContentPayloadLength; ++ ++ pCcxTagReqHeader = vos_mem_malloc(reqLen); ++ if (NULL == pCcxTagReqHeader) ++ { ++ status = VOS_STATUS_E_NOMEM; ++ } ++ } ++ ++ if (status == VOS_STATUS_SUCCESS) ++ { ++ u8 * pCcxTagReqPayload = (u8 *)&pCcxTagReqHeader[1]; ++ vos_msg_t msg; ++ ++ vos_mem_set((u8*)(pCcxTagReqHeader), reqLen, 0); ++ ++ /* Now copy over the information to the CCX Tag REQ to WMI message. */ ++ vos_mem_copy(pCcxTagReqHeader, pHeader, ++ sizeof(CcxTagWmiHeader)); ++ ++ vos_mem_copy(pCcxTagReqPayload, pData, ++ pHeader->ContentPayloadLength); ++ ++ /* Create the message to be passed to HAL. */ ++ msg.type = SIR_HAL_CCX_TAG_REQ; ++ msg.bodyptr = pCcxTagReqHeader; ++ msg.bodyval = 0; ++ ++ status = vos_mq_post_message(VOS_MQ_ID_WDA, &msg); ++ if (status != VOS_STATUS_SUCCESS) ++ { ++ vos_mem_free(pCcxTagReqHeader); ++ } ++ } ++ ++ mutex_unlock(&hdd_ccx_tag_mutex); ++ ++ return status; ++} ++ ++static void ResetDriver(void) ++{ ++ if (hdd_ccx_tag_drvr_op_state != CCX_TAG_DRVR_OP_UNRECOVERABLE) ++ { ++ mutex_lock(&hdd_ccx_tag_mutex); ++ ++ hdd_ccx_tag_api_version = 0; ++ hdd_ccx_tag_drvr_op_state = CCX_TAG_DRVR_OP_IDLE; ++ hdd_ccx_tag_fw_status = CCX_TAG_FW_STATUS_ERROR; ++ hdd_ccx_tag_fw_attempts = 0; ++ hdd_ccx_tag_fw_failures = 0; ++ hdd_ccx_tag_fw_msgs_outstanding = 0; ++ ++ mutex_unlock(&hdd_ccx_tag_mutex); ++ } ++} ++ ++/* This function registers a handler to receive netlink message */ ++/* from a userspace application using the CCX Tags API. */ ++int ccx_tag_activate_service(void *pAdapter) ++{ ++ int rc; ++ tp_wma_handle wma_handle = NULL; ++ int status = -1; ++ CcxTagDriverOpState op_state = CCX_TAG_DRVR_OP_UNRECOVERABLE; ++ ++ pHddCtx = (struct hdd_context_s*) pAdapter; ++ ++ mutex_init(&hdd_ccx_tag_mutex); ++ ++ /* Register the CCX Tag family with the general netlink service. */ ++ rc = genl_register_family(&ccx_tag_gnl_family); ++ ++ if (rc == 0) ++ { ++ wma_handle = vos_get_context(VOS_MODULE_ID_WDA, pHddCtx->pvosContext); ++ ++ if (wma_handle != NULL) ++ { ++ status = wmi_unified_register_event_handler( ++ wma_handle->wmi_handle, ++ WMI_STA_TAG_PKT_INJ_COMP_EVENTID, ++ RecvCcxTagWmaRsp); ++ if (status == 0) ++ { ++ ResetDriver(); ++ op_state = CCX_TAG_DRVR_OP_IDLE; ++ } ++ } ++ } ++ ++ hdd_ccx_tag_drvr_op_state = op_state; ++ ++ return rc; ++} ++ ++int ccx_tag_deactivate_service(void) ++{ ++ int rc; ++ tp_wma_handle wma_handle = NULL; ++ int status; ++ CcxTagDriverOpState op_state = CCX_TAG_DRVR_OP_UNRECOVERABLE; ++ ++ /* Deregister the CCX Tag family from the general netlink service. */ ++ rc = genl_unregister_family(&ccx_tag_gnl_family); ++ ++ if (rc == 0) ++ { ++ wma_handle = vos_get_context(VOS_MODULE_ID_WDA, pHddCtx->pvosContext); ++ ++ if (wma_handle != NULL) ++ { ++ status = wmi_unified_unregister_event_handler( ++ wma_handle->wmi_handle, ++ WMI_STA_TAG_PKT_INJ_COMP_EVENTID); ++ if (status == 0) ++ { ++ ResetDriver(); ++ op_state = CCX_TAG_DRVR_OP_IDLE; ++ } ++ } ++ } ++ ++ mutex_destroy(&hdd_ccx_tag_mutex); ++ ++ hdd_ccx_tag_drvr_op_state = op_state; ++ ++ return rc; ++} ++ ++void TagConfigDisplay(CcxTagMpduHeader const * MpduHeaderBuffer, uint16_t MpduHeaderBufferLength, ++ CcxTagContentHeader const * ContentHeaderBuffer, uint16_t ContentHeaderBufferLength, ++ uint8_t const * ContentPayloadBlock, ++ uint16_t ContentPayloadBlockLength) ++{ ++ printk(KERN_DEBUG "CCX Tag Header: \n"); ++ RawBlockDisplay((uint8_t const *)MpduHeaderBuffer, MpduHeaderBufferLength); ++ ++ printk(KERN_DEBUG "CCX Tag Content: \n"); ++ RawBlockDisplay((uint8_t const *)ContentHeaderBuffer, ContentHeaderBufferLength); ++ ++ if (ContentPayloadBlockLength > 0) ++ { ++ printk(KERN_DEBUG "CCX Tag Data: \n"); ++ RawBlockDisplay(ContentPayloadBlock, ContentPayloadBlockLength); ++ } ++} ++ ++/* Parse an attribute from the command. */ ++/* The expected length is for each attribute is known, */ ++/* so simply fail if it doesn't match the actual. */ ++static int ccx_tag_parse_attr(struct nlattr ** attrs, CcxTagAttrType type, ++ void * attr_buf, uint16_t attr_len) ++{ ++ int parse_status = 0; ++ ++ if (attrs && (type < CCX_TAG_ATTR_COUNT) && (attr_len > 0)) ++ { ++ struct nlattr * attr = attrs[type]; ++ if (attr != NULL) ++ { ++ uint32_t payload_len = attr->nla_len - NLA_HDRLEN; ++ if (payload_len == (uint32_t)attr_len) ++ { ++ if (attr_buf != NULL) ++ { ++ uint8_t const * data_buf = (uint8_t const *)attr; ++ memcpy(attr_buf, &data_buf[NLA_HDRLEN], attr_len); ++ parse_status = 1; ++ } ++ } ++ } ++ } ++ ++ return parse_status; ++} ++ ++int ccx_tag_parse_transmit_attr(struct nlattr ** attrs, ++ CcxTagAttrType type, ++ CcxTagControlData * ctrl_data, ++ CcxTagMpduHeader * mpdu_hdr, ++ CcxTagContentHeader * cont_hdr, ++ uint8_t const ** cont_data, ++ uint16_t * cont_len) ++{ ++ int parse_status = 0; ++ uint8_t const * payload_data = NULL; ++ uint32_t payload_len = 0; ++ ++ if (attrs && (type == CCX_TAG_ATTR_TAG_COMMAND)) ++ { ++ struct nlattr * attr = attrs[type]; ++ if (attr != NULL) ++ { ++ uint32_t lower_lim = (uint32_t)CCX_TAG_IPC_MSG_MIN_SIZE; ++ uint32_t upper_lim = (uint32_t)CCX_TAG_IPC_MSG_MAX_SIZE; ++ ++ payload_len = attr->nla_len - NLA_HDRLEN; ++ if ((payload_len >= lower_lim) && (payload_len <= upper_lim)) ++ { ++ uint8_t const * data_buf = (uint8_t const *)attr; ++ payload_data = &data_buf[NLA_HDRLEN]; ++ } ++ } ++ } ++ ++ if ((payload_data != NULL) ++ && (payload_len >= (CCX_TAG_CONTROL_DATA_SIZE + CCX_TAG_PACKET_MIN_SIZE))) ++ { ++ if ((ctrl_data != NULL) && (mpdu_hdr != NULL) && (cont_hdr != NULL) ++ && (cont_data != NULL) && (cont_len != NULL)) ++ { ++ size_t tmp_len = sizeof(CcxTagControlData); ++ memcpy(ctrl_data, payload_data, tmp_len); ++ payload_data = &payload_data[tmp_len]; ++ payload_len -= tmp_len; ++ ++ tmp_len = sizeof(CcxTagMpduHeader); ++ memcpy(mpdu_hdr, payload_data, tmp_len); ++ payload_data = &payload_data[tmp_len]; ++ payload_len -= tmp_len; ++ ++ tmp_len = sizeof(CcxTagContentHeader); ++ memcpy(cont_hdr, payload_data, tmp_len); ++ payload_data = &payload_data[tmp_len]; ++ payload_len -= tmp_len; ++ ++ *cont_len = payload_len; ++ if (payload_len > 0) ++ { ++ *cont_data = payload_data; ++ } ++ ++ if (1) ++ { ++ printk(KERN_DEBUG "Kernel Cfg - Frag: %u Chan: %u \n", ++ ctrl_data->FragmentOffsetOctets, ctrl_data->ChannelOffsetOctets); ++ ++ TagConfigDisplay(mpdu_hdr, ctrl_data->MpduHeaderSize, ++ cont_hdr, ctrl_data->ContentHeaderSize, ++ *cont_data, ctrl_data->ContentPayloadSize); ++ } ++ ++ parse_status = 1; ++ } ++ } ++ ++ return parse_status; ++} ++ ++/* ++ * Callback functions invoked by Generic Netlink service for all netlink ++ * messages (from user space). ++ */ ++ ++static int ccx_tag_check_version_cmd_handler(struct sk_buff *skb, struct genl_info *info) ++{ ++ CcxTagDriverResponseType rsp_err = CCX_TAG_DRVR_RSP_OK; ++ ++ uint16_t cmd_buf = CCX_TAG_CMD_INVALID; ++ uint16_t seq_buf = 0; ++ uint16_t rsp_buf = CCX_TAG_DRVR_RSP_INVALID; ++ uint32_t version_buf = 0; ++ ++ /* Process the message for a valid command. */ ++ if (!info) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ else ++ { ++ int parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_CMD, &cmd_buf, sizeof(cmd_buf)); ++ ++ if (parse_ok) ++ { ++ parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_SEQUENCE, &seq_buf, sizeof(seq_buf)); ++ } ++ ++ if (parse_ok) ++ { ++ parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_API_VERSION, &version_buf, sizeof(version_buf)); ++ } ++ ++ if (!parse_ok) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ } ++ ++ /* Process the contents of the message, if valid. */ ++ if (rsp_err == CCX_TAG_DRVR_RSP_OK) ++ { ++ hdd_ccx_tag_api_version = version_buf; ++ ++ ResetDriver(); ++ } ++ ++ /* Reply with the driver version, regardless of parse results. */ ++ rsp_buf = (uint16_t)rsp_err; ++ SendAttrData(cmd_buf, seq_buf, rsp_buf, ++ CCX_TAG_ATTR_DRIVER_VERSION, ++ (uint8_t *)&HDD_CCX_TAG_DRVR_VERSION, ++ sizeof(HDD_CCX_TAG_DRVR_VERSION), info); ++ ++ return 0; ++} ++ ++static int ccx_tag_reset_cmd_handler(struct sk_buff *skb, struct genl_info *info) ++{ ++ CcxTagDriverResponseType rsp_err = CCX_TAG_DRVR_RSP_OK; ++ ++ uint16_t cmd_buf = CCX_TAG_CMD_INVALID; ++ uint16_t seq_buf = 0; ++ uint16_t rsp_buf = CCX_TAG_DRVR_RSP_INVALID; ++ ++ if (!info) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ else ++ { ++ int parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_CMD, &cmd_buf, sizeof(cmd_buf)); ++ ++ if (parse_ok) ++ { ++ parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_SEQUENCE, &seq_buf, sizeof(seq_buf)); ++ } ++ ++ if (!parse_ok) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ } ++ ++ /* Process the contents of the message, if valid. */ ++ if (rsp_err == CCX_TAG_DRVR_RSP_OK) ++ { ++ ResetDriver(); ++ } ++ ++ /* Reply with the driver version, regardless of parse results. */ ++ rsp_buf = (uint16_t)rsp_err; ++ SendAttrData(cmd_buf, seq_buf, rsp_buf, ++ CCX_TAG_ATTR_UNDEFINED, NULL, 0, ++ info); ++ ++ return 0; ++} ++ ++static int ccx_tag_transmit_cmd_handler(struct sk_buff *skb, struct genl_info *info) ++{ ++ CcxTagDriverResponseType rsp_err = CCX_TAG_DRVR_RSP_OK; ++ ++ uint16_t cmd_buf = CCX_TAG_CMD_INVALID; ++ uint16_t seq_buf = 0; ++ uint16_t rsp_buf = CCX_TAG_DRVR_RSP_INVALID; ++ CcxTagControlData ctrl_data; ++ CcxTagMpduHeader mpdu_hdr; ++ CcxTagContentHeader cont_hdr; ++ uint8_t const * cont_data; ++ uint16_t cont_len = 0; ++ ++ /* Netlink Message Completeness Validation */ ++ if (!info) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ else ++ { ++ int parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_CMD, &cmd_buf, sizeof(cmd_buf)); ++ ++ if (parse_ok) ++ { ++ parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_SEQUENCE, &seq_buf, sizeof(seq_buf)); ++ } ++ ++ if (parse_ok) ++ { ++ parse_ok = ccx_tag_parse_transmit_attr( ++ info->attrs, CCX_TAG_ATTR_TAG_COMMAND, ++ &ctrl_data, &mpdu_hdr, &cont_hdr, &cont_data, &cont_len); ++ } ++ ++ if (!parse_ok) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ } ++ ++ /* Netlink Message Detailed Content Validation */ ++ if (rsp_err == CCX_TAG_DRVR_RSP_OK) ++ { ++ if (ctrl_data.ControlDataVersion != CCX_TAG_VERSION) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_TAG_VERSION; ++ } ++ else if (ctrl_data.ControlDataSize != sizeof(CcxTagControlData)) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_CTRL_SIZE; ++ } ++ else if (ctrl_data.ContentPayloadSize != cont_len) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_PACKET_SIZE; ++ } ++ else ++ { ++ uint16_t packet_size = ctrl_data.MpduHeaderSize ++ + ctrl_data.ContentHeaderSize ++ + ctrl_data.ContentPayloadSize; ++ if ((ctrl_data.FragmentOffsetOctets >= packet_size) ++ || (ctrl_data.ChannelOffsetOctets >= packet_size)) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_OFFSET_OVERRUN; ++ } ++ ++ } ++ } ++ ++ /* Internal Driver State Validation */ ++ if (rsp_err == CCX_TAG_DRVR_RSP_OK) ++ { ++ mutex_lock(&hdd_ccx_tag_mutex); ++ ++ if ((hdd_ccx_tag_drvr_op_state >= CCX_TAG_DRVR_OP_STATE_COUNT) ++ || (hdd_ccx_tag_drvr_op_state == CCX_TAG_DRVR_OP_UNRECOVERABLE)) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_OP_FAILED; ++ } ++ else if (hdd_ccx_tag_drvr_op_state == CCX_TAG_DRVR_OP_IN_PROG) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_OP_IN_PROG; ++ } ++ ++ mutex_unlock(&hdd_ccx_tag_mutex); ++ } ++ ++ /* Firmware Command Issuance */ ++ if (rsp_err == CCX_TAG_DRVR_RSP_OK) ++ { ++ CcxTagWmiHeader wmi_hdr; ++ VOS_STATUS status = VOS_STATUS_SUCCESS; ++ ++ wmi_hdr.ChannelOffsetOctets = ctrl_data.ChannelOffsetOctets; ++ wmi_hdr.FragmentOffsetOctets = ctrl_data.FragmentOffsetOctets; ++ wmi_hdr.ContentPayloadLength = ctrl_data.ContentPayloadSize; ++ ++ memcpy(&wmi_hdr.MpduHeader, &mpdu_hdr, sizeof(wmi_hdr.MpduHeader)); ++ memcpy(&wmi_hdr.ContentHeader, &cont_hdr, sizeof(wmi_hdr.ContentHeader)); ++ ++ status = SendCcxTagWmaCmd(&wmi_hdr, cont_data); ++ ++ if (status == VOS_STATUS_SUCCESS) ++ { ++ mutex_lock(&hdd_ccx_tag_mutex); ++ hdd_ccx_tag_drvr_op_state = CCX_TAG_DRVR_OP_IN_PROG; ++ hdd_ccx_tag_fw_msgs_outstanding++; ++ mutex_unlock(&hdd_ccx_tag_mutex); ++ } ++ else ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_OP_FAILED; ++ } ++ } ++ ++ /* Reply with the driver version, regardless of parse results. */ ++ rsp_buf = (uint16_t)rsp_err; ++ SendAttrData(cmd_buf, seq_buf, rsp_buf, ++ CCX_TAG_ATTR_UNDEFINED, NULL, 0, ++ info); ++ ++ return 0; ++} ++ ++static int ccx_tag_status_cmd_handler(struct sk_buff *skb, struct genl_info *info) ++{ ++ CcxTagDriverResponseType rsp_err = CCX_TAG_DRVR_RSP_OK; ++ ++ uint16_t cmd_buf = CCX_TAG_CMD_INVALID; ++ uint16_t seq_buf = 0; ++ uint16_t rsp_buf = CCX_TAG_DRVR_RSP_INVALID; ++ CcxTagStatusData status; ++ ++ if (!info) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ else ++ { ++ int parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_CMD, &cmd_buf, sizeof(cmd_buf)); ++ ++ if (parse_ok) ++ { ++ parse_ok = ccx_tag_parse_attr(info->attrs, ++ CCX_TAG_ATTR_SEQUENCE, &seq_buf, sizeof(seq_buf)); ++ } ++ ++ if (!parse_ok) ++ { ++ rsp_err = CCX_TAG_DRVR_RSP_ERR_NL_PARSE; ++ } ++ } ++ ++ /* Firmware Response Collection */ ++ if (rsp_err == CCX_TAG_DRVR_RSP_OK) ++ { ++ mutex_lock(&hdd_ccx_tag_mutex); ++ status.DriverOpState = hdd_ccx_tag_drvr_op_state; ++ mutex_unlock(&hdd_ccx_tag_mutex); ++ ++ status.FirmwareStatus = hdd_ccx_tag_fw_status; ++ status.AttemptCount = hdd_ccx_tag_fw_attempts; ++ status.FailureCount = hdd_ccx_tag_fw_failures; ++ } ++ else ++ { ++ status.DriverOpState = CCX_TAG_DRVR_OP_STATE_UNDEFINED; ++ status.FirmwareStatus = CCX_TAG_FW_STATUS_ERROR; ++ status.AttemptCount = 0; ++ status.FailureCount = 0; ++ } ++ ++ status.StatusDataSize = sizeof(status); ++ status.StatusDataVersion = CCX_TAG_STATUS_VERSION; ++ ++ rsp_buf = (uint16_t)rsp_err; ++ SendAttrData(cmd_buf, seq_buf, rsp_buf, ++ CCX_TAG_ATTR_TAG_STATUS, (uint8_t *)&status, sizeof(status), ++ info); ++ ++ return 0; ++} ++ ++#endif +diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c +index 05600538cda5..4d21d850a22e 100644 +--- a/CORE/HDD/src/wlan_hdd_main.c ++++ b/CORE/HDD/src/wlan_hdd_main.c +@@ -71,6 +71,9 @@ + #include + #include + #include ++#ifdef FEATURE_CCX_TAG_SUPPORT ++#include ++#endif + #include + #include + #include +@@ -15509,6 +15512,13 @@ int _readwrite_file(const char *filename, char *rbuf, + break; + } + ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ // Clean up the CCX Tag Netlink bridge ++ if (ccx_tag_deactivate_service() != 0) ++ { ++ hddLog(LOGE, FL("Cannot deallocate CCX Tag resource")); ++ } ++#endif + if (wbuf) { + ret = vfs_write( + filp, wbuf, length, &filp->f_pos); +@@ -17610,6 +17620,16 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc) + goto err_ptt_sock_activate_svc; + } + ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ //Initialize the CCX Tag service ++ if (ccx_tag_activate_service(pHddCtx) != 0) ++ { ++ hddLog(VOS_TRACE_LEVEL_FATAL, ++ "%s: ccx_tag_activate_service failed", __func__); ++ goto err_ptt_sock_activate_svc; ++ } ++#endif ++ + //Initialize the CNSS-DIAG service + if (cnss_diag_activate_service() < 0) + { +diff --git a/CORE/MAC/inc/aniGlobal.h b/CORE/MAC/inc/aniGlobal.h +index cf78093490f5..2f1677fa5168 100644 +--- a/CORE/MAC/inc/aniGlobal.h ++++ b/CORE/MAC/inc/aniGlobal.h +@@ -74,6 +74,10 @@ + #include "oemDataInternal.h" + #endif + ++#ifdef FEATURE_CCX_TAG_SUPPORT ++#include "CcxTagDefs.h" ++#endif ++ + #if defined WLAN_FEATURE_VOWIFI + #include "smeRrmInternal.h" + #include "rrmGlobal.h" +diff --git a/CORE/MAC/inc/qwlan_version.h b/CORE/MAC/inc/qwlan_version.h +index 5d5ee0c2124f..ec245797b79b 100644 +--- a/CORE/MAC/inc/qwlan_version.h ++++ b/CORE/MAC/inc/qwlan_version.h +@@ -44,8 +44,7 @@ BRIEF DESCRIPTION: + #define QWLAN_VERSION_EXTRA "X" + #define QWLAN_VERSION_BUILD 213 + +-#define QWLAN_VERSIONSTR "4.0.11.213X" +- ++#define QWLAN_VERSIONSTR "4.0.11.295X" + + #define AR6320_REV1_VERSION 0x5000000 + #define AR6320_REV1_1_VERSION 0x5000001 +diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h +index 67eb0eab64c4..97d2194d31c4 100644 +--- a/CORE/MAC/src/include/sirParams.h ++++ b/CORE/MAC/src/include/sirParams.h +@@ -823,6 +823,12 @@ struct sir_mgmt_msg { + #define SIR_HAL_THERM_THROT_SET_CONF_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 383) + #define SIR_HAL_THERM_MGMT_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 384) + #define SIR_HAL_SET_HPCS_PULSE_PARMAS (SIR_HAL_ITC_MSG_TYPES_BEGIN + 387) ++ ++#ifdef FEATURE_CCX_TAG_SUPPORT ++#define SIR_HAL_CCX_TAG_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 390) ++#define SIR_HAL_CCX_TAG_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 391) ++#endif ++ + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) + + // CFG message types +diff --git a/CORE/SERVICES/COMMON/wmi_tlv_defs.h b/CORE/SERVICES/COMMON/wmi_tlv_defs.h +index 3215790ac023..fb4ee7298086 100644 +--- a/CORE/SERVICES/COMMON/wmi_tlv_defs.h ++++ b/CORE/SERVICES/COMMON/wmi_tlv_defs.h +@@ -958,6 +958,11 @@ typedef enum { + WMITLV_TAG_STRUC_wmi_request_wlm_stats_cmd_fixed_param, + WMITLV_TAG_STRUC_wmi_wlm_stats_event_fixed_param, + WMITLV_TAG_STRUC_wmi_wlm_link_stats, ++ //Cisco tag packet injection - note that below enumerations should have ++ //the same tag value as from firmware. Any change causes firmware to ++ //reject the WMI command ++ WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_cmd_fixed_param = 0x2a3, ++ WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_event_fixed_param = 0x2a4, + } WMITLV_TAG_ID; + + /* +@@ -1349,6 +1354,7 @@ typedef enum { + OP(WMI_PEER_UNMAP_RESPONSE_CMDID) \ + OP(WMI_ROAM_BSS_LOAD_CONFIG_CMDID) \ + OP(WMI_VDEV_GET_MWS_COEX_INFO_CMDID) \ ++ OP(WMI_STA_TAG_PKT_INJ_CMDID) \ + OP(WMI_REQUEST_WLM_STATS_CMDID) \ + /* add new CMD_LIST elements above this line */ + +@@ -1568,10 +1574,10 @@ typedef enum { + OP(WMI_VDEV_GET_MWS_COEX_TDM_STATE_EVENTID) \ + OP(WMI_VDEV_GET_MWS_COEX_IDRX_STATE_EVENTID) \ + OP(WMI_VDEV_GET_MWS_COEX_ANTENNA_SHARING_STATE_EVENTID) \ ++ OP(WMI_STA_TAG_PKT_INJ_COMP_EVENTID) \ + OP(WMI_WLM_STATS_EVENTID) \ + /* add new EVT_LIST elements above this line */ + +- + /* TLV definitions of WMI commands */ + + /* Init Cmd */ +@@ -5238,6 +5244,17 @@ WMITLV_CREATE_PARAM_STRUC(WMI_MOTION_DET_BASE_LINE_HOST_EVENTID); + WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_esp_estimate_event_fixed_param, wmi_esp_estimate_event_fixed_param, fixed_param, WMITLV_SIZE_FIX) + WMITLV_CREATE_PARAM_STRUC(WMI_ESP_ESTIMATE_EVENTID); + ++/* Cisco Tag Packet Injection Command WMI_STA_TAG_PKT_INJ_CMDID = 0x3C001 */ ++#define WMITLV_TABLE_WMI_STA_TAG_PKT_INJ_CMDID(id,op,buf,len) \ ++ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_cmd_fixed_param, wmi_sta_tag_pkt_injection_cmd_fixed_param, fixed_param, WMITLV_SIZE_FIX) \ ++ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_ARRAY_BYTE, A_UINT8, buffer, WMITLV_SIZE_VAR) ++WMITLV_CREATE_PARAM_STRUC(WMI_STA_TAG_PKT_INJ_CMDID); ++ ++/* Cisco Tag Packet Injection completion event, WMI_STA_TAG_PKT_INJ_COMP_EVENTID = 0x3C002*/ ++#define WMITLV_TABLE_WMI_STA_TAG_PKT_INJ_COMP_EVENTID(id,op,buf,len) \ ++ WMITLV_ELEM(id,op,buf,len, WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_event_fixed_param, wmi_sta_tag_pkt_inj_comp_fixed_param, fixed_param, WMITLV_SIZE_FIX) ++WMITLV_CREATE_PARAM_STRUC(WMI_STA_TAG_PKT_INJ_COMP_EVENTID); ++ + #ifdef __cplusplus + } + #endif +diff --git a/CORE/SERVICES/COMMON/wmi_unified.h b/CORE/SERVICES/COMMON/wmi_unified.h +index 2332e8711a9d..a8070b2d7cc9 100644 +--- a/CORE/SERVICES/COMMON/wmi_unified.h ++++ b/CORE/SERVICES/COMMON/wmi_unified.h +@@ -250,13 +250,14 @@ typedef enum { + WMI_GRP_MONITOR, /* 0x39 */ + WMI_GRP_REGULATORY, /* 0x3a */ + WMI_GRP_HW_DATA_FILTER, /* 0x3b */ +- WMI_GRP_WLM, /* 0x3c WLAN Latency Manager */ ++ WMI_GRP_USER_DEF = 0x3C, + WMI_GRP_11K_OFFLOAD, /* 0x3d */ + WMI_GRP_TWT, /* 0x3e TWT (Target Wake Time) for STA and AP */ + WMI_GRP_MOTION_DET, /* 0x3f */ + WMI_GRP_SPATIAL_REUSE, /* 0x40 */ + WMI_GRP_ESP, /* 0x41 Estimate Service Parameters (802.11mc) */ + WMI_GRP_HPCS_PULSE, /* 0x42 High Precision Clock Synchronization */ ++ WMI_GRP_WLM, /* 0x3c WLAN Latency Manager */ + } WMI_GRP_ID; + + #define WMI_CMD_GRP_START_ID(grp_id) (((grp_id) << 12) | 0x1) +@@ -1195,6 +1196,10 @@ typedef enum { + + /** WMI commands related to High Precision Clock Synchronization feature **/ + WMI_HPCS_PULSE_START_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_HPCS_PULSE), ++ ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ WMI_STA_TAG_PKT_INJ_CMDID = WMI_CMD_GRP_START_ID(WMI_GRP_USER_DEF), ++#endif /* FEATURE_CCX_TAG_SUPPORT */ + } WMI_CMD_ID; + + typedef enum { +@@ -1789,6 +1794,9 @@ typedef enum { + + /** WMI events related to Estimation of Service Parameters (802.11mc) */ + WMI_ESP_ESTIMATE_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_ESP), ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ WMI_STA_TAG_PKT_INJ_COMP_EVENTID = WMI_EVT_GRP_START_ID(WMI_GRP_USER_DEF) + 1, ++#endif /* FEATURE_CCX_TAG_SUPPORT */ + } WMI_EVT_ID; + + /* defines for OEM message sub-types */ +@@ -21904,6 +21912,71 @@ typedef struct { + A_UINT32 is_tdm_running; + } wmi_vdev_get_mws_coex_dpwb_state_fixed_param; + ++#ifdef FEATURE_CCX_TAG_SUPPORT ++/*WMI_STA_TAG_PKT_INJ_CMDID fixed parameters*/ ++typedef struct ++{ ++ /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_cmd_fixed_param */ ++ A_UINT32 tlv_header; ++ ++ /* Offset of channel field in the frame to be injected */ ++ A_UINT8 channel_offset; ++ ++ /* Offset of fragment count field in the frame to be injected (should be 22) */ ++ A_UINT8 fragment_offset; ++ ++ /*padding to 4-byte boundary*/ ++ A_UINT8 pad[2]; ++ ++ /* This should be same as the frame length including 802.11 header, for firmware buffer allocation */ ++ A_UINT32 frame_length; ++ ++ /** ++ This structure will be followed by TLV for data buffer. ++ It includes 802.11 header with 4-address format. ++ Tag for data buffer = WMITLV_TAG_ARRAY_BYTE ++ Length for data buffer = depends on the frame to be injected, ++ but rounded to next 32-bit boundary ++ A_UINT8 buffer[]; ++ */ ++}wmi_sta_tag_pkt_injection_cmd_fixed_param; ++ ++/* Error Codes used in Tx Status field in event from firmware: */ ++/* Command was properly processed, Tx failures may have happened. */ ++#define PKT_INJ_TX_STATUS_OK 0 ++/* Generic error. The transmit failed to complete for an unknown reason. */ ++#define PKT_INJ_TX_STATUS_ERROR -1 ++/* Unable to allocate memory for the transmit. */ ++#define PKT_INJ_TX_STATUS_MEM 2 ++/* No free descriptors available. */ ++#define PKT_INJ_TX_STATUS_NODESC 4 ++/* Invalid parameter in the WMI command. */ ++#define PKT_INJ_TX_STATUS_INVPRM 14 ++/* The transmit operation was cancelled due to a higher priority operation. */ ++#define PKT_INJ_TX_STATUS_CANCEL 16 ++/* Hardware failure. */ ++#define PKT_INJ_TX_STATUS_HWFAIL 23 ++ ++/* WMI_STA_TAG_PKT_INJ_COMP_EVENTID fixed parameters*/ ++ ++#endif /* FEATURE_CCX_TAG_SUPPORT */ ++ ++typedef struct ++{ ++ /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_completion */ ++ A_UINT32 tlv_header; ++ ++ /* Total number of transmit attempts by firmware */ ++ A_UINT32 totalTxAttempts; ++ ++ /* Total number of transmit failures observed by firmware */ ++ A_UINT32 totalTxFailures; ++ ++ /* Overall transmit status, see PKT_INJ_TX_STATUS_XXX */ ++ A_INT32 txStatus; ++}wmi_sta_tag_pkt_inj_comp_fixed_param; ++/* ADD NEW DEFS HERE */ ++ + typedef struct { + A_UINT32 tlv_header; /* TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_vdev_get_mws_coex_tdm_state_fixed_param */ + A_UINT32 vdev_id; +diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c +index be13660667c7..337ae97be0a1 100644 +--- a/CORE/SERVICES/WMA/wma.c ++++ b/CORE/SERVICES/WMA/wma.c +@@ -30227,6 +30227,77 @@ VOS_STATUS wma_ProcessAddPeriodicTxPtrnInd(WMA_HANDLE handle, + return VOS_STATUS_SUCCESS; + } + ++#ifdef FEATURE_CCX_TAG_SUPPORT ++static void wma_ccx_tag_req(tp_wma_handle wma_handle, ++ CcxTagWmiHeader * ccxTagReqHeader) ++{ ++ if ((ccxTagReqHeader != NULL) ++ && (wma_handle != NULL) ++ && (wma_handle->wmi_handle != NULL)) ++ { ++ ++ uint8_t * ccxTagReqPayload = (uint8_t *)&ccxTagReqHeader[1]; ++ uint32_t packet_size = sizeof(ccxTagReqHeader->MpduHeader) ++ + sizeof(ccxTagReqHeader->ContentHeader) ++ + ccxTagReqHeader->ContentPayloadLength; ++ uint32_t packet_size_aligned = roundup(packet_size, sizeof(A_UINT32)); ++ uint32_t len = sizeof(wmi_sta_tag_pkt_injection_cmd_fixed_param) + ++ WMI_TLV_HDR_SIZE + packet_size_aligned; ++ ++ wmi_buf_t wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len); ++ if (wmi_buf != NULL) ++ { ++ int ret = 0; ++ u_int8_t * buf_ptr = (u_int8_t *)wmi_buf_data(wmi_buf); ++ wmi_sta_tag_pkt_injection_cmd_fixed_param * cmd = ++ (wmi_sta_tag_pkt_injection_cmd_fixed_param *)buf_ptr; ++ ++ /*memset the contents to 0*/ ++ memset(buf_ptr, 0, len); ++ ++ /*Filling the packet injection fixed parameter structure*/ ++ WMITLV_SET_HDR(&cmd->tlv_header, ++ WMITLV_TAG_STRUC_wmi_sta_tag_pkt_injection_cmd_fixed_param, ++ WMITLV_GET_STRUCT_TLVLEN(wmi_sta_tag_pkt_injection_cmd_fixed_param)); ++ ++ /* Set the offset per the configured values. */ ++ cmd->channel_offset = (A_UINT8)ccxTagReqHeader->ChannelOffsetOctets; ++ cmd->fragment_offset = (A_UINT8)ccxTagReqHeader->FragmentOffsetOctets; ++ cmd->frame_length = packet_size; ++ ++ /*Move pointer to end of fixed parameters*/ ++ buf_ptr += sizeof(wmi_sta_tag_pkt_injection_cmd_fixed_param); ++ ++ /*Set TLV Header for the packet*/ ++ WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, packet_size_aligned); ++ buf_ptr += WMI_TLV_HDR_SIZE; ++ ++ /*Copy the data packet segments after TLV Header*/ ++ vos_mem_copy(buf_ptr, &ccxTagReqHeader->MpduHeader, ++ sizeof(ccxTagReqHeader->MpduHeader)); ++ buf_ptr += sizeof(ccxTagReqHeader->MpduHeader); ++ ++ vos_mem_copy(buf_ptr, &ccxTagReqHeader->ContentHeader, ++ sizeof(ccxTagReqHeader->ContentHeader)); ++ buf_ptr += sizeof(ccxTagReqHeader->ContentHeader); ++ ++ vos_mem_copy(buf_ptr, ccxTagReqPayload, ccxTagReqHeader->ContentPayloadLength); ++ buf_ptr += ccxTagReqHeader->ContentPayloadLength; ++ ++ /*Send the WMI command payload to firmware*/ ++ ret = wmi_unified_cmd_send(wma_handle->wmi_handle, ++ wmi_buf, len, ++ WMI_STA_TAG_PKT_INJ_CMDID); ++ ++ if (ret != EOK) ++ { ++ wmi_buf_free(wmi_buf); ++ } ++ } ++ } ++} ++#endif /* FEATURE_CCX_TAG_SUPPORT */ ++ + /* + * FUNCTION: wma_ProcessDelPeriodicTxPtrnInd + * WMI command sent to firmware to del patterns +@@ -35469,6 +35540,15 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg) + (u_int32_t *)msg->bodyptr); + vos_mem_free(msg->bodyptr); + break; ++ ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ case SIR_HAL_CCX_TAG_REQ: ++ wma_ccx_tag_req(wma_handle, ++ (CcxTagWmiHeader *)msg->bodyptr); ++ vos_mem_free(msg->bodyptr); ++ break; ++#endif /* FEATURE_CCX_TAG_SUPPORT */ ++ + case WDA_GET_FW_STATUS_REQ: + wma_send_echo_request(wma_handle); + break; +diff --git a/CORE/SERVICES/WMI/wmi_unified.c b/CORE/SERVICES/WMI/wmi_unified.c +index f25b7966e22e..40c2ceb4234b 100644 +--- a/CORE/SERVICES/WMI/wmi_unified.c ++++ b/CORE/SERVICES/WMI/wmi_unified.c +@@ -811,6 +811,9 @@ static u_int8_t* get_wmi_cmd_string(WMI_CMD_ID wmi_command) + CASE_RETURN_STRING(WMI_ROAM_BSS_LOAD_CONFIG_CMDID); + CASE_RETURN_STRING(WMI_VDEV_GET_MWS_COEX_INFO_CMDID); + CASE_RETURN_STRING(WMI_REQUEST_WLM_STATS_CMDID); ++#ifdef FEATURE_CCX_TAG_SUPPORT ++ CASE_RETURN_STRING(WMI_STA_TAG_PKT_INJ_CMDID); ++#endif + } + return "Invalid WMI cmd"; + } +diff --git a/Kbuild b/Kbuild +index fdad10c753a3..1ff42e6dedd4 100644 +--- a/Kbuild ++++ b/Kbuild +@@ -447,6 +447,7 @@ HDD_INC := -I$(WLAN_ROOT)/$(HDD_INC_DIR) \ + -I$(WLAN_ROOT)/$(HDD_SRC_DIR) + + HDD_OBJS := $(HDD_SRC_DIR)/wlan_hdd_assoc.o \ ++ $(HDD_SRC_DIR)/wlan_hdd_ccx_tag.o \ + $(HDD_SRC_DIR)/wlan_hdd_cfg.o \ + $(HDD_SRC_DIR)/wlan_hdd_debugfs.o \ + $(HDD_SRC_DIR)/wlan_hdd_dev_pwr.o \ +@@ -1053,6 +1054,7 @@ CDEFINES := -DANI_LITTLE_BYTE_ENDIAN \ + -DFEATURE_WLAN_WAPI \ + -DWLAN_FEATURE_11W \ + -DFEATURE_OEM_DATA_SUPPORT\ ++ -DFEATURE_CCX_TAG_SUPPORT \ + -DSOFTAP_CHANNEL_RANGE \ + -DWLAN_AP_STA_CONCURRENCY \ + -DFEATURE_WLAN_SCAN_PNO \ diff --git a/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/WCNSS_qcom_cfg-ccx.ini b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/WCNSS_qcom_cfg-ccx.ini new file mode 100644 index 000000000..122895bcc --- /dev/null +++ b/meta-digi-arm/recipes-kernel/kernel-module-qualcomm/kernel-module-qualcomm/WCNSS_qcom_cfg-ccx.ini @@ -0,0 +1,710 @@ +# This file allows user to override the factory + +# defaults for the WLAN Driver + + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan +gEnableIdleScan=0 + + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + + +# Enable BMPS or not +gEnableBmps=1 + +# Enable suspend or not + +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter + +gEnableSuspend=3 + +# Phy Mode (auto, b, g, n, etc) +# Valid values are 0-9, with 0 = Auto, 4 = 11n, 9 = 11ac +# 1 = 11abg, 2 = 11b, 3 = 11g, 5 = 11g only, 6 = 11n only +# 7 = 11b only 8 = 11ac only. +gDot11Mode=0 + + +# CSR Roaming Enable(1) Disable(0) + +gRoamingTime=0 + + +# Assigned MAC Addresses - This will be used until NV items are in place + +# Each byte of MAC address is represented in Hex format as XX + +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD + +Intf3MacAddress=000AF58989FC + + +# UAPSD service interval for VO,VI, BE, BK traffic + +InfraUapsdVoSrvIntv=0 + +InfraUapsdViSrvIntv=0 + +InfraUapsdBeSrvIntv=0 + +InfraUapsdBkSrvIntv=0 + +# Flag to allow STA send AddTspec even when ACM is Off +gAddTSWhenACMIsOff=1 + +# Make 1x1 the default antenna configuration + +gNumRxAnt=1 + + +# Beacon filtering frequency (unit in beacon intervals) + +gNthBeaconFilter=50 + + +# Enable WAPI or not + +# WAPIIsEnabled=0 + + +# Flags to filter Mcast abd Bcast RX packets. + +# Value 0: No filtering, 1: Filter all Multicast. + +# 2: Filter all Broadcast. 3: Filter all Mcast abd Bcast + +McastBcastFilter=3 + + +#Flag to enable HostARPOffload feature or not + +hostArpOffload=1 + +#Flag to enable TCPChkSumOffld feature or not + +gEnableTCPChkSumOffld=1 + +#Flag to enable HostNSOffload feature or not + +hostNSOffload=1 + +#Flag to enable IPChkSumOffld feature or not + +gEnableIPChecksumOffload=1 + +#SoftAP Related Parameters + +# AP MAc addr + +gAPMacAddr=000AF589dcab + + +# 802.11n Protection flag + +gEnableApProt=1 + + +#Enable OBSS protection + +gEnableApOBSSProt=1 + + +#Enable/Disable UAPSD for SoftAP + +gEnableApUapsd=1 + + +# Fixed Rate + +gFixedRate=0 + + +# Maximum Tx power + +# gTxPowerCap=30 + + +# Fragmentation Threshold + +# gFragmentationThreshold=2346 + + +# RTS threshold + +RTSThreshold=1048576 + + +# Intra-BSS forward + +gDisableIntraBssFwd=0 + + +# WMM Enable/Disable + +WmmIsEnabled=0 + + +# 802.11d support + +g11dSupportEnabled=0 + +# 802.11h support + +g11hSupportEnabled=1 + +# DFS Master Capability +gEnableDFSMasterCap=1 + +# ESE Support and fast transition +EseEnabled=1 +ImplicitQosIsEnabled=0 +gNeighborScanTimerPeriod=200 + +gNeighborLookupThreshold=76 +gNeighborReassocThreshold=81 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 +gMaxNeighborReqTries=3 + +# Legacy (non-ESE, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1 +# To disable, set FastRoamEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=3 + +# If the RSSI of any available candidate is better than currently associated +# AP by at least gImmediateRoamRssiDiff, then being to roam immediately (without +# registering for reassoc threshold). +# NOTE: Value of 0 means that we would register for reassoc threshold. +gImmediateRoamRssiDiff=10 + +# To enable, set gRoamIntraBand=1 (Roaming within band) +# To disable, set gRoamIntraBand=0 (Roaming across band) +gRoamIntraBand=0 + +# SAP Country code + +# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. + +# Example + +# US Indoor, USI + +# Korea Outdoor, KRO + +# Japan without optional byte, JP + +# France without optional byte, FR + +#gAPCntryCode=USI + + +#Short Guard Interval Enable/disable + +gShortGI20Mhz=1 + +gShortGI40Mhz=1 + + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled + +gAPAutoShutOff=0 + +#Auto Shutdown wlan : Value in Seconds. 0 means disabled. Max 1 day = 86400 sec +gWlanAutoShutdown = 0 + + +# Listen Energy Detect Mode Configuration + +# Valid values 0-128 + +# 128 means disable Energy Detect feature + +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. + +# 10-128 are reserved. + +# The EDET threshold mapping is as follows in 3dB step: + +# 0 = -60 dBm + +# 1 = -63 dBm + +# 2 = -66 dBm + +# ... + +# 7 = -81 dBm + +# 8 = -84 dBm + +# 9 = -87 dBm + +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: + +# + +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. + +# + +gEnablePhyAgcListenMode=128 + + +#Preferred band (both or 2.4 only or 5 only) + +BandCapability=0 + + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) + +enableBeaconEarlyTermination=0 + +beaconEarlyTerminationWakeInterval=3 + + +#Channel Bonding +gChannelBondingMode24GHz=1 +gChannelBondingMode5GHz=1 + + +#Enable Keep alive with non-zero period value + +gStaKeepAlivePeriod = 30 + +#Say gGoKeepAlivePeriod(5 seconds) and gGoLinkMonitorPeriod(10 seconds). +#For every 10 seconds DUT send Qos Null frame(i.e., Keep Alive frame if link is idle for last 10 seconds.) +#For both active and power save clients. + +#Power save clients: DUT set TIM bit from 10th second onwards and till client honors TIM bit. +#If doesn't honor for 5 seconds then DUT remove client. + +#Active clients: DUT send Qos Null frame for 10th seconds onwards if it is not success still we try on +#11th second if not tries on 12th and so on till 15th second. Hence before disconnection DUT will send 5 NULL frames. +#Hence in any case DUT will detect client got removed in (10+5) seconds. i.e., (gGoKeepAlivePeriod + gGoLinkMonitorPeriod).. + +#gGoLinkMonitorPeriod/ gApLinkMonitorPeriod is period where link is idle and it is period +#where we send NULL frame. + +gApLinkMonitorPeriod = 30 + +gGoLinkMonitorPeriod = 10 + +#gGoKeepAlivePeriod/gApKeepAlivePeriod is time to spend to check whether frame are succeed to send or not. +#Hence total effective detection time is gGoLinkMonitorPeriod+ gGoKeepAlivePeriod/gApLinkMonitorPeriod+ gApKeepAlivePeriod. + + +gGoKeepAlivePeriod = 3 + +gApKeepAlivePeriod = 10 + + +#If set will start with active scan after driver load, otherwise will start with + +#passive scan to find out the domain + +gEnableBypass11d=1 + + +#If set to 0, will not scan DFS channels + +gEnableDFSChnlScan=1 + +# Enable DFS channel roam +# 0: DISABLE, 1: ENABLED_NORMAL, 2: ENABLED_ACTIVE +gAllowDFSChannelRoam=1 + +gVhtChannelWidth=2 + + +# Enable Automatic Tx Power control + +gEnableAutomaticTxPowerControl=1 + +# 0 for OLPC 1 for CLPC and SCPC +gEnableCloseLoop=1 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +# VHT Tx/Rx MCS values +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gVhtRxMCS=2 +gVhtTxMCS=0 + +# VHT Tx/Rx MCS values for 2x2 +# Valid values are 0,1,2. If commented out, the default value is 0. +# 0=MCS0-7, 1=MCS0-8, 2=MCS0-9 +gEnable2x2=1 +gVhtRxMCS2x2=2 +gVhtTxMCS2x2=2 + +#tx_nss_2g - Config Param to change tx nss for 2.4G band +#rx_nss_2g - Config Param to change rx nss for 2.4G band +#tx_nss_5g - Config Param to change tx nss for 5G band +#rx_nss_5g - Config Param to change rx nss for 5G band +#per vdev for 2.4ghz frequency connections +#This ini is used to change the num of tx spatial streams for eg:- +#0x01249249 - change all vdev's tx nss for 2.4ghz connections to 1 each +#0x02492492 - change all vdev's tx nss for 2.4ghz connections to 2 each +#Bits VDEV Type +#BIT[0:2] STA +#BIT[3:5] SAP +#BIT[6:8] P2P GO +#BIT[9:11] P2P Client +#BIT[12:14] TDLS +#BIT[15:17] IBSS +#BIT[18:20] P2P device +#BIT[21:23] OCB +#BIT[24:26] NAN +#BIT[27:31] Reserved +tx_nss_2g=0x02492492 +rx_nss_2g=0x02492492 +tx_nss_5g=0x02492492 +rx_nss_5g=0x02492492 + +# This ini disables/enables chainmask setting on 2x2, mainly used for ROME +# BT/WLAN chainmask assignment. +# 0, Disable +# 1, Enable +enableBTChainSeparation=0 + +# Set txchainmask and rxchainmask +# These parameters are used only if gEnable2x2 is 0 +# Valid values are 1,2 +# Set gSetTxChainmask1x1=1 or gSetRxChainmask1x1=1 to select chain0. +# Set gSetTxChainmask1x1=2 or gSetRxChainmask1x1=2 to select chain1. +gSetTxChainmask1x1=0 +gSetRxChainmask1x1=0 + +# Chain mask for 2G and 5G: 1 for chain0, 2 for chain1, 3 for: chain0 and chain1 +rx_chain_mask_5g=3 +tx_chain_mask_5g=3 +rx_chain_mask_2g=3 +tx_chain_mask_2g=3 + +# Dual mac disable +gDualMacFeatureDisable=1 + +#Drop beacon on mismatch channel +drop_bcn_on_chan_mismatch=0 + +# Scan Timing Parameters +# gPassiveMaxChannelTime=110 +# gPassiveMinChannelTime=60 +gActiveMaxChannelTime=80 +gActiveMinChannelTime=40 + +#If set to 0, MCC is not allowed. +gEnableMCCMode=1 + +# MCC to SCC Switch mode: 0-Disable 1-Enable 2-Force SCC if same band +gWlanMccToSccSwitchMode = 0 + +# Band Switch Enable/Disable for MCC to SCC +gWlanBandSwitchEnable = 0 + +# 1=enable STBC; 0=disable STBC +gEnableRXSTBC=1 + +# 1=enable tx STBC; 0=disable +gEnableTXSTBC=1 + +# 1=enable rx LDPC; 0=disable +gEnableRXLDPC=1 + +# Enable Tx beamforming in VHT20MHz +# Valid values are 0,1. If commented out, the default value is 0. +# 0=disable, 1=enable +gEnableTxBFin20MHz=1 + +# Enable Active mode offload +gEnableActiveModeOffload=1 + +#Enable Scan Results Aging based on number of scans +gScanResultAgeCount=1 + +#Enable Power saving mechanism Based on Android Framework +#If set to 0 Driver internally control the Power saving mechanism +#If set to 1 Android Framwrok control the Power saving mechanism +isAndroidPsEn=0 + +#Enable thermal mitigation +gThermalMitigationEnable=0 + +gEnableFastRoamInConcurrency=1 + +#List of Country codes for which 11ac needs to be disabled +#Each country code must be delimited by comma(,) +gListOfNon11acCountryCode=RU,UA,ZA + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmRandIntvl=100 + +#Scan offload +gEnableDirectedScanOffload=1 + +#FlexConnect Power Factor +#Default is set to 0 (disable) +gFlexConnectPowerFactor=0 + +#Disable split scan, the FW will take care of it +gNumChanCombinedConc=60 + +#Enable Power Save offload +gEnablePowerSaveOffload=2 + +#Enable firmware uart print +gEnablefwprint=0 + +#Enable firmware log +gEnablefwlog=1 +# Additional firmware log levels +gFwDebugLogLevel=4 +gFwDebugModuleLoglevel=1,0,2,0,4,0,5,0,6,0,7,4,8,0,9,0,11,0,13,0,17,0,18,0,19,0,27,0,29,0,31,0,35,0,36,0,38,0 + +#IPA config +gIPAConfig=0 +gIPADescSize=800 +gIPAPreFilterEnable=1 +gIPARMEnable=1 +gIPAIPv6Enable=1 + +#P2P Listen offload +gEnableP2pListenOffload=1 + +# Maximum MPDU length (VHT only. Valid values: 0->3895 octets, 1->7991 octets, 2->11454 octets) +gVhtMpduLen=2 + +# Maximum number of wow filters required +#gMaxWoWFilters=22 + +# WOW Enable/Disable. +# 0 - Disable both magic pattern match and pattern byte match. +# 1 - Enable magic pattern match on all interfaces. +# 2 - Enable pattern byte match on all interfaces. +# 3 - Enable both magic patter and pattern byte match on all interfaces. +# Default value of gEnableWoW is 3. +# gEnableWoW=0 + +# Enable or Disable MCC Adaptive Scheduler at the FW +# 1=Enable (default), 0=Disable +gEnableMCCAdaptiveScheduler=1 + +#Enable or Disable p2p device address administered +isP2pDeviceAddrAdministrated=0 + +# RX packet handling options +# 0: no rx thread, no RPS, for MDM +# 1: RX thread +# 2: RPS +rxhandle=2 + +# Set RPS CPU MAP as 0xe for the 4 RX queues +# This allows use of CPU1-CPU3 but not CPU0 for 4 RX queues +rpsRxQueueCpuMapList=c + +# Remove Overlap channel restriction +gEnableOverLapCh=0 + +#Enable VHT on 2.4Ghz +gEnableVhtFor24GHzBand=1 + +#Enable or Disable 5G early beacon termination +gEnable5gEBT=1 + +#Maximum number of offload peers supported +# gMaxOffloadPeers=2 + +# controlling the following offload patterns +# through ini parameter. Default value is 1 +# to disable set it to zero. ssdp = 0 +# Setup multicast pattern for mDNS 224.0.0.251, +# SSDP 239.255.255.250 and LLMNR 224.0.0.252 + + +ssdp = 0 + +#Enable Memory Deep Sleep +gEnableMemDeepSleep=1 + +# Bus bandwidth threshold values in terms of number of packets +gBusBandwidthHighThreshold=2000 +gBusBandwidthMediumThreshold=500 +gBusBandwidthLowThreshold=150 + +# IPA bandwidth voting +gIPAHighBandwidthMbps=800 +gIPAMediumBandwidthMbps=400 +gIPALowBandwidthMbps=200 + +# Bus bandwidth compute timeout value in ms +gBusBandwidthComputeInterval=100 + +# Regulatory Setting; 0=STRICT; 1=CUSTOM +gRegulatoryChangeCountry=0 +# RA filtering rate limit param, the current value would not +# help if the lifetime in RA is less than 3*60=3min. Then +# we need to change it, though it is uncommon. +# gRAFilterEnable=0 +gRArateLimitInterval=600 + +# Maximum number of concurrent connections +gMaxConcurrentActiveSessions=2 + +# Disable/Enable GreenAP +# 0 to disable, 1 to enable, default: 1 +gEnableGreenAp=1 + +# Radar PRI multiplier +gDFSradarMappingPriMultiplier=4 + +gPNOScanSupport=0 + +# Enable/Disable RX full reorder offload +gReorderOffloadSupported=1 + +# Enable/Disable LPASS support +# 0 to disable, 1 to enable +gEnableLpassSupport=0 + +# Whether userspace country code setting shld have priority +gCountryCodePriority=1 + +# Enable(1)/Disable(0) SIFS burst +gEnableSifsBurst=0 + +# Enable/Disable channel avoidance for SAP in SCC scenario +# 0 - disable +# 1 - enable +gSapSccChanAvoidance=0 + +# Inactivity time (in ms) to end TX Service Period while in IBSS power save mode +gIbssTxSpEndInactivityTime=10 + +# Enable/Disable Roaming Offload Support (a.k.a Key Management Offload) +# 0 to disable, 1 to enable +gRoamOffloadEnabled=0 + +# Enable support for TDLS +# 0 - disable +# 1 - enable +gEnableTDLSSupport=1 + +# Enable support for Implicit Trigger of TDLS. That is, wlan driver shall +# initiate TDLS Discovery towards a peer whenever setup criteria (throughput +# and RSSI) is met and then will initiate teardown when teardown criteria +# (idle packet count and RSSI) is met. +# 0 - disable +# 1 - enable +gEnableTDLSImplicitTrigger=1 + +# Enable TDLS External Control. That is, user space application has to +# first configure a peer MAC in wlan driver towards which TDLS is desired. +# Device will establish TDLS only towards those configured peers whenever +# TDLS criteria (throughput and RSSI threshold) is met and teardown TDLS +# when teardown criteria (idle packet count and RSSI) is met. However, +# device will accept TDLS connection if it is initiated from any other peer, +# even if that peer is not configured. +# 0 - disable +# 1 - enable +# For TDLS External Control, Implicit Trigger must also be enabled. +gTDLSExternalControl=1 + +# Enable support for TDLS off-channel operation +# 0 - disable +# 1 - enable +# TDLS off-channel operation will be invoked when there is only one +# TDLS connection. +gEnableTDLSOffChannel=1 + +IpaUcOffloadEnabled=1 +gIpaUcStaOffload=1 + +gEnableSelfRecovery=1 + +# Enable or Disable Random MAC (Spoofing) +# 1=Enable, 0=Disable (default) +gEnableMacAddrSpoof=0 + +# Enable Auto suspend feature +# When this feature is enabled, it will shutdown the PCIe link +# when inactivity is detected in STA disconnected mode. +# 0 - disable +# 1 - enable +gEnableBusAutoSuspend=0 + +# Enable Runtime PM Feature. +# Enabling this feature will put target wow and shutdown pcie link +# when inactivity is detected in WLAN Driver. +# This feature is inactive when beaconing interfaces are active with +# clients associated. +# 0 - disable +# 1 - enable + +gRuntimePM=1 +# When gRuntimePM is disabled gRuntimeAutoTime won't take effect. +# The Time is in msec. +# 100 is min, 10000 is max, 500 is default. + +gRuntimePMDelay=500 + +# Enable to check FW hash if secure FW feature is enabled. It's for defconfig +# builds only since it will be ignored in performance/release builds. +gEnableFWHashCheck=1 + +# Enable FW to filter out broadcast packets and wakeup host during runtime PM. +# As APPS is awake during runtime PM, if any application needs the broadcast +# packets OEM's can enable this flag. +# FW will filters the broadcast packets and wakeup host to deliver them during +# runtime suspend. +# This flag will take affect when Runtime PM is enabled +gRuntimePmEnableBcastPattern=0 + +# intervals length (in ms) during WLAN P2P (single vdev) + BT Paging +# min 20ms, max 200ms +gBTIntervalPageP2P=30 +gWLIntervalPageP2P=30 + +# intervals length (in ms) during WLAN STA (single vdev) + BT Paging +# min 20ms, max 200ms +gBTIntervalPageSTA=30 +gWLIntervalPageSTA=30 + +# intervals length (in ms) during WLAN SAP (single vdev) + BT Paging +# min 20ms, max 200ms +gBTIntervalPageSAP=30 +gWLIntervalPageSAP=30 + +# Enable OCB/DSRC tx per packet stats, disable it as default because +# it would degrade throughput +gOcbTxPerPktStatsEnable=0 + +# Eanble self recovery on standalone SPs +gEnableFwSelfRecovery=1 + +gSoftApMaxPeers=14 +gEnablePacketLog=0 + +END + +# Note: Configuration parser would not read anything past the END marker