]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'wireless-drivers-next-for-davem-2015-07-31' of git://git.kernel.org/pub...
authorDavid S. Miller <davem@davemloft.net>
Fri, 31 Jul 2015 22:33:23 +0000 (15:33 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 Jul 2015 22:33:23 +0000 (15:33 -0700)
Kalle Valo says:

====================
Major changes:

mwifiex:

* add TX DATA Pause support
* add multichannel and TDLS channel switch support

ath10k:

* enable VHT for IBSS
* initial work to support qca99x0 and the corresponding 10.4 firmware branch
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
74 files changed:
MAINTAINERS
drivers/bcma/main.c
drivers/net/wireless/ath/ath10k/Makefile
drivers/net/wireless/ath/ath10k/bmi.h
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/ce.h
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/htt.c
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/hw.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/mac.h
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/pci.h
drivers/net/wireless/ath/ath10k/swap.c [new file with mode: 0644]
drivers/net/wireless/ath/ath10k/swap.h [new file with mode: 0644]
drivers/net/wireless/ath/ath10k/targaddrs.h
drivers/net/wireless/ath/ath10k/txrx.c
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.h
drivers/net/wireless/ath/ath9k/dfs.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/ath/dfs_pri_detector.c
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/b43/lo.c
drivers/net/wireless/b43/lo.h
drivers/net/wireless/b43/phy_g.c
drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/core.h
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/cw1200/cw1200_spi.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/debug.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/decl.h
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/ie.c
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/tdls.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/uap_cmd.c
drivers/net/wireless/mwifiex/uap_event.c
drivers/net/wireless/mwifiex/usb.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/mwifiex/wmm.c
drivers/net/wireless/mwifiex/wmm.h
drivers/net/wireless/rtlwifi/rtl8192cu/def.h
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
drivers/net/wireless/rtlwifi/rtl8192de/phy.c
drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
drivers/net/wireless/rtlwifi/rtl8821ae/reg.h
drivers/net/wireless/ti/wlcore/rx.c
drivers/net/wireless/ti/wlcore/rx.h
drivers/net/wireless/ti/wlcore/sdio.c

index 6712fd5f4200bd5337910fc7af4d9ffccb706a73..5f5c897820f6c1b40af123953a5847538af2800a 100644 (file)
@@ -6507,7 +6507,7 @@ F:        drivers/net/ethernet/marvell/mvneta.*
 
 MARVELL MWIFIEX WIRELESS DRIVER
 M:     Amitkumar Karwar <akarwar@marvell.com>
-M:     Avinash Patil <patila@marvell.com>
+M:     Nishant Sarmukadam <nishants@marvell.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/mwifiex/
index 9635f1033ce5c46e7aba2863fa04a8bc86421aa9..8d973c4fc84e3185af77b6c4da0a64103be2e7b9 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/of_platform.h>
 
 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
 MODULE_LICENSE("GPL");
@@ -409,6 +410,17 @@ int bcma_bus_register(struct bcma_bus *bus)
                bcma_core_pci_early_init(&bus->drv_pci[0]);
        }
 
+       /* TODO: remove check for IS_BUILTIN(CONFIG_BCMA) check when
+        * of_default_bus_match_table is exported or in some other way
+        * accessible. This is just a temporary workaround.
+        */
+       if (IS_BUILTIN(CONFIG_BCMA) && bus->host_pdev) {
+               struct device *dev = &bus->host_pdev->dev;
+
+               of_platform_populate(dev->of_node, of_default_bus_match_table,
+                                    NULL, dev);
+       }
+
        /* Cores providing flash access go before SPROM init */
        list_for_each_entry(core, &bus->cores, list) {
                if (bcma_is_core_needed_early(core->id.id))
index 9729e69416358a120ef0c97cd3feb034cb0ca6bb..c04fb00e7930219f909939b9ea36140ad3101fb8 100644 (file)
@@ -11,7 +11,8 @@ ath10k_core-y += mac.o \
                 wmi-tlv.o \
                 bmi.o \
                 hw.o \
-                p2p.o
+                p2p.o \
+                swap.o
 
 ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
 ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
index 31a990635490aa07cf74a515e620c90fc1b697c8..df7c7616533b08636374736911ca3f624983a47e 100644 (file)
@@ -178,7 +178,7 @@ struct bmi_target_info {
 };
 
 /* in msec */
-#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
+#define BMI_COMMUNICATION_TIMEOUT_HZ (2 * HZ)
 
 #define BMI_CE_NUM_TO_TARG 0
 #define BMI_CE_NUM_TO_HOST 1
index e508c65b6ba8a6d62ffbcca77e5d8f41ff036ad3..cf28fbebaedcfc9b372d509c6a88fcbc2d808773 100644 (file)
@@ -452,6 +452,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
 {
        struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
        unsigned int nentries_mask = dest_ring->nentries_mask;
+       struct ath10k *ar = ce_state->ar;
        unsigned int sw_index = dest_ring->sw_index;
 
        struct ce_desc *base = dest_ring->base_addr_owner_space;
index 0eddb204d85bb9b08dcb84f55530b25fb3b901e8..5c903e15dd65e6ad7da14caffb1e3a4fd8fe4bfc 100644 (file)
@@ -21,7 +21,7 @@
 #include "hif.h"
 
 /* Maximum number of Copy Engine's supported */
-#define CE_COUNT_MAX 8
+#define CE_COUNT_MAX 12
 #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
 
 /* Descriptor rings must be aligned to this boundary */
@@ -38,8 +38,13 @@ struct ath10k_ce_pipe;
 
 #define CE_DESC_FLAGS_GATHER         (1 << 0)
 #define CE_DESC_FLAGS_BYTE_SWAP      (1 << 1)
-#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
-#define CE_DESC_FLAGS_META_DATA_LSB  2
+
+/* Following desc flags are used in QCA99X0 */
+#define CE_DESC_FLAGS_HOST_INT_DIS     (1 << 2)
+#define CE_DESC_FLAGS_TGT_INT_DIS      (1 << 3)
+
+#define CE_DESC_FLAGS_META_DATA_MASK ar->hw_values->ce_desc_meta_data_mask
+#define CE_DESC_FLAGS_META_DATA_LSB  ar->hw_values->ce_desc_meta_data_lsb
 
 struct ce_desc {
        __le32 addr;
@@ -423,8 +428,10 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
 
 #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
 
-#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB              8
-#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK             0x0000ff00
+#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \
+                               ar->regs->ce_wrap_intr_sum_host_msi_lsb
+#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK \
+                               ar->regs->ce_wrap_intr_sum_host_msi_mask
 #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(x) \
        (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \
                CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB)
index 59496a90ad5e241563f5bcaa8226ebfde87bd478..f79fa6c67ebc3cbcff75a802a426d8ccdb89d979 100644 (file)
@@ -49,6 +49,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
                .has_shifted_cc_wraparound = true,
+               .otp_exe_param = 0,
                .fw = {
                        .dir = QCA988X_HW_2_0_FW_DIR,
                        .fw = QCA988X_HW_2_0_FW_FILE,
@@ -63,6 +64,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .name = "qca6174 hw2.1",
                .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
                .uart_pin = 6,
+               .otp_exe_param = 0,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
                        .fw = QCA6174_HW_2_1_FW_FILE,
@@ -77,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .name = "qca6174 hw3.0",
                .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
                .uart_pin = 6,
+               .otp_exe_param = 0,
                .fw = {
                        .dir = QCA6174_HW_3_0_FW_DIR,
                        .fw = QCA6174_HW_3_0_FW_FILE,
@@ -91,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .name = "qca6174 hw3.2",
                .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
                .uart_pin = 6,
+               .otp_exe_param = 0,
                .fw = {
                        /* uses same binaries as hw3.0 */
                        .dir = QCA6174_HW_3_0_FW_DIR,
@@ -101,8 +105,68 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                        .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
                },
        },
+       {
+               .id = QCA99X0_HW_2_0_DEV_VERSION,
+               .name = "qca99x0 hw2.0",
+               .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
+               .uart_pin = 7,
+               .otp_exe_param = 0x00000700,
+               .continuous_frag_desc = true,
+               .fw = {
+                       .dir = QCA99X0_HW_2_0_FW_DIR,
+                       .fw = QCA99X0_HW_2_0_FW_FILE,
+                       .otp = QCA99X0_HW_2_0_OTP_FILE,
+                       .board = QCA99X0_HW_2_0_BOARD_DATA_FILE,
+                       .board_size = QCA99X0_BOARD_DATA_SZ,
+                       .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
+               },
+       },
 };
 
+static const char *const ath10k_core_fw_feature_str[] = {
+       [ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX] = "wmi-mgmt-rx",
+       [ATH10K_FW_FEATURE_WMI_10X] = "wmi-10.x",
+       [ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX] = "has-wmi-mgmt-tx",
+       [ATH10K_FW_FEATURE_NO_P2P] = "no-p2p",
+       [ATH10K_FW_FEATURE_WMI_10_2] = "wmi-10.2",
+       [ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT] = "multi-vif-ps",
+       [ATH10K_FW_FEATURE_WOWLAN_SUPPORT] = "wowlan",
+       [ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp",
+       [ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
+       [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
+};
+
+static unsigned int ath10k_core_get_fw_feature_str(char *buf,
+                                                  size_t buf_len,
+                                                  enum ath10k_fw_features feat)
+{
+       if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) ||
+           WARN_ON(!ath10k_core_fw_feature_str[feat])) {
+               return scnprintf(buf, buf_len, "bit%d", feat);
+       }
+
+       return scnprintf(buf, buf_len, "%s", ath10k_core_fw_feature_str[feat]);
+}
+
+void ath10k_core_get_fw_features_str(struct ath10k *ar,
+                                    char *buf,
+                                    size_t buf_len)
+{
+       unsigned int len = 0;
+       int i;
+
+       for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
+               if (test_bit(i, ar->fw_features)) {
+                       if (len > 0)
+                               len += scnprintf(buf + len, buf_len - len, ",");
+
+                       len += ath10k_core_get_fw_feature_str(buf + len,
+                                                             buf_len - len,
+                                                             i);
+               }
+       }
+}
+
 static void ath10k_send_suspend_complete(struct ath10k *ar)
 {
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot suspend complete\n");
@@ -355,6 +419,7 @@ out:
 static int ath10k_download_and_run_otp(struct ath10k *ar)
 {
        u32 result, address = ar->hw_params.patch_load_addr;
+       u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
        int ret;
 
        ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
@@ -380,7 +445,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
                return ret;
        }
 
-       ret = ath10k_bmi_execute(ar, address, 0, &result);
+       ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
        if (ret) {
                ath10k_err(ar, "could not execute otp (%d)\n", ret);
                return ret;
@@ -412,6 +477,13 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
                data = ar->firmware_data;
                data_len = ar->firmware_len;
                mode_name = "normal";
+               ret = ath10k_swap_code_seg_configure(ar,
+                               ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW);
+               if (ret) {
+                       ath10k_err(ar, "failed to configure fw code swap: %d\n",
+                                  ret);
+                       return ret;
+               }
                break;
        case ATH10K_FIRMWARE_MODE_UTF:
                data = ar->testmode.utf->data;
@@ -451,6 +523,8 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
        if (!IS_ERR(ar->cal_file))
                release_firmware(ar->cal_file);
 
+       ath10k_swap_code_seg_release(ar);
+
        ar->board = NULL;
        ar->board_data = NULL;
        ar->board_len = 0;
@@ -464,6 +538,7 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
        ar->firmware_len = 0;
 
        ar->cal_file = NULL;
+
 }
 
 static int ath10k_fetch_cal_file(struct ath10k *ar)
@@ -737,6 +812,13 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                        ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n",
                                   ar->htt.op_version);
                        break;
+               case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE:
+                       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                                  "found fw code swap image ie (%zd B)\n",
+                                  ie_len);
+                       ar->swap.firmware_codeswap_data = data;
+                       ar->swap.firmware_codeswap_len = ie_len;
+                       break;
                default:
                        ath10k_warn(ar, "Unknown FW IE: %u\n",
                                    le32_to_cpu(hdr->id));
@@ -1014,6 +1096,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
                ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
                        WMI_STAT_PEER;
+               ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_1:
        case ATH10K_FW_WMI_OP_VERSION_10_2:
@@ -1023,6 +1106,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
                ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
                ar->fw_stats_req_mask = WMI_STAT_PEER;
+               ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
                break;
        case ATH10K_FW_WMI_OP_VERSION_TLV:
                ar->max_num_peers = TARGET_TLV_NUM_PEERS;
@@ -1033,6 +1117,17 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS;
                ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
                        WMI_STAT_PEER;
+               ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
+               break;
+       case ATH10K_FW_WMI_OP_VERSION_10_4:
+               ar->max_num_peers = TARGET_10_4_NUM_PEERS;
+               ar->max_num_stations = TARGET_10_4_NUM_STATIONS;
+               ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
+               ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
+               ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
+               ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
+               ar->fw_stats_req_mask = WMI_STAT_PEER;
+               ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM;
                break;
        case ATH10K_FW_WMI_OP_VERSION_UNSET:
        case ATH10K_FW_WMI_OP_VERSION_MAX:
@@ -1056,6 +1151,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                case ATH10K_FW_WMI_OP_VERSION_TLV:
                        ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
                        break;
+               case ATH10K_FW_WMI_OP_VERSION_10_4:
                case ATH10K_FW_WMI_OP_VERSION_UNSET:
                case ATH10K_FW_WMI_OP_VERSION_MAX:
                        WARN_ON(1);
@@ -1330,6 +1426,13 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
                goto err_free_firmware_files;
        }
 
+       ret = ath10k_swap_code_seg_init(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to initialize code swap segment: %d\n",
+                          ret);
+               goto err_free_firmware_files;
+       }
+
        mutex_lock(&ar->conf_mutex);
 
        ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
@@ -1470,9 +1573,15 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
        switch (hw_rev) {
        case ATH10K_HW_QCA988X:
                ar->regs = &qca988x_regs;
+               ar->hw_values = &qca988x_values;
                break;
        case ATH10K_HW_QCA6174:
                ar->regs = &qca6174_regs;
+               ar->hw_values = &qca6174_values;
+               break;
+       case ATH10K_HW_QCA99X0:
+               ar->regs = &qca99x0_regs;
+               ar->hw_values = &qca99x0_values;
                break;
        default:
                ath10k_err(ar, "unsupported core hardware revision %d\n",
index 78094f23c9dd5264a66d32167680a8af8728a8ff..78e07051b8970415086783674ba2d123cfddc312 100644 (file)
@@ -36,6 +36,7 @@
 #include "spectral.h"
 #include "thermal.h"
 #include "wow.h"
+#include "swap.h"
 
 #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
 #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@@ -327,8 +328,8 @@ struct ath10k_vif {
                        u32 uapsd;
                } sta;
                struct {
-                       /* 127 stations; wmi limit */
-                       u8 tim_bitmap[16];
+                       /* 512 stations */
+                       u8 tim_bitmap[64];
                        u8 tim_len;
                        u32 ssid_len;
                        u8 ssid[IEEE80211_MAX_SSID_LEN];
@@ -545,6 +546,7 @@ struct ath10k {
        u32 ht_cap_info;
        u32 vht_cap_info;
        u32 num_rf_chains;
+       u32 max_spatial_stream;
        /* protected by conf_mutex */
        bool ani_enabled;
 
@@ -560,6 +562,7 @@ struct ath10k {
        struct completion target_suspend;
 
        const struct ath10k_hw_regs *regs;
+       const struct ath10k_hw_values *hw_values;
        struct ath10k_bmi bmi;
        struct ath10k_wmi wmi;
        struct ath10k_htc htc;
@@ -570,6 +573,7 @@ struct ath10k {
                const char *name;
                u32 patch_load_addr;
                int uart_pin;
+               u32 otp_exe_param;
 
                /* This is true if given HW chip has a quirky Cycle Counter
                 * wraparound which resets to 0x7fffffff instead of 0. All
@@ -578,6 +582,12 @@ struct ath10k {
                 */
                bool has_shifted_cc_wraparound;
 
+               /* Some of chip expects fragment descriptor to be continuous
+                * memory for any TX operation. Set continuous_frag_desc flag
+                * for the hardware which have such requirement.
+                */
+               bool continuous_frag_desc;
+
                struct ath10k_hw_params_fw {
                        const char *dir;
                        const char *fw;
@@ -602,6 +612,12 @@ struct ath10k {
 
        const struct firmware *cal_file;
 
+       struct {
+               const void *firmware_codeswap_data;
+               size_t firmware_codeswap_len;
+               struct ath10k_swap_code_seg_info *firmware_swap_code_seg_info;
+       } swap;
+
        char spec_board_id[100];
        bool spec_board_loaded;
 
@@ -617,6 +633,7 @@ struct ath10k {
                bool is_roc;
                int vdev_id;
                int roc_freq;
+               bool roc_notify;
        } scan;
 
        struct {
@@ -675,6 +692,8 @@ struct ath10k {
        int max_num_stations;
        int max_num_vdevs;
        int max_num_tdls_vdevs;
+       int num_active_peers;
+       int num_tids;
 
        struct work_struct offchan_tx_work;
        struct sk_buff_head offchan_tx_queue;
@@ -749,6 +768,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
                                  enum ath10k_hw_rev hw_rev,
                                  const struct ath10k_hif_ops *hif_ops);
 void ath10k_core_destroy(struct ath10k *ar);
+void ath10k_core_get_fw_features_str(struct ath10k *ar,
+                                    char *buf,
+                                    size_t max_len);
 
 int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
 int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
index 8fa606a9c4ddaf3f95b43d80723a0fbcfe59a010..edf6047997a7bef6a131692e6f842517c91fe891 100644 (file)
@@ -124,7 +124,11 @@ EXPORT_SYMBOL(ath10k_info);
 
 void ath10k_print_driver_info(struct ath10k *ar)
 {
-       ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
+       char fw_features[128];
+
+       ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
+
+       ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d features %s\n",
                    ar->hw_params.name,
                    ar->target_version,
                    ar->chip_id,
@@ -137,8 +141,10 @@ void ath10k_print_driver_info(struct ath10k *ar)
                    ar->htt.target_version_major,
                    ar->htt.target_version_minor,
                    ar->wmi.op_version,
+                   ar->htt.op_version,
                    ath10k_cal_mode_str(ar->cal_mode),
-                   ar->max_num_stations);
+                   ar->max_num_stations,
+                   fw_features);
        ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
                    config_enabled(CONFIG_ATH10K_DEBUG),
                    config_enabled(CONFIG_ATH10K_DEBUGFS),
index 6da6ef26143af0caeac2ed8ed76b14f28319b471..4474c3e839db459cd9e18eb33b821a7045da3190 100644 (file)
@@ -102,6 +102,43 @@ static const enum htt_t2h_msg_type htt_tlv_t2h_msg_types[] = {
        [HTT_TLV_T2H_MSG_TYPE_TEST] = HTT_T2H_MSG_TYPE_TEST,
 };
 
+static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = {
+       [HTT_10_4_T2H_MSG_TYPE_VERSION_CONF] = HTT_T2H_MSG_TYPE_VERSION_CONF,
+       [HTT_10_4_T2H_MSG_TYPE_RX_IND] = HTT_T2H_MSG_TYPE_RX_IND,
+       [HTT_10_4_T2H_MSG_TYPE_RX_FLUSH] = HTT_T2H_MSG_TYPE_RX_FLUSH,
+       [HTT_10_4_T2H_MSG_TYPE_PEER_MAP] = HTT_T2H_MSG_TYPE_PEER_MAP,
+       [HTT_10_4_T2H_MSG_TYPE_PEER_UNMAP] = HTT_T2H_MSG_TYPE_PEER_UNMAP,
+       [HTT_10_4_T2H_MSG_TYPE_RX_ADDBA] = HTT_T2H_MSG_TYPE_RX_ADDBA,
+       [HTT_10_4_T2H_MSG_TYPE_RX_DELBA] = HTT_T2H_MSG_TYPE_RX_DELBA,
+       [HTT_10_4_T2H_MSG_TYPE_TX_COMPL_IND] = HTT_T2H_MSG_TYPE_TX_COMPL_IND,
+       [HTT_10_4_T2H_MSG_TYPE_PKTLOG] = HTT_T2H_MSG_TYPE_PKTLOG,
+       [HTT_10_4_T2H_MSG_TYPE_STATS_CONF] = HTT_T2H_MSG_TYPE_STATS_CONF,
+       [HTT_10_4_T2H_MSG_TYPE_RX_FRAG_IND] = HTT_T2H_MSG_TYPE_RX_FRAG_IND,
+       [HTT_10_4_T2H_MSG_TYPE_SEC_IND] = HTT_T2H_MSG_TYPE_SEC_IND,
+       [HTT_10_4_T2H_MSG_TYPE_RC_UPDATE_IND] = HTT_T2H_MSG_TYPE_RC_UPDATE_IND,
+       [HTT_10_4_T2H_MSG_TYPE_TX_INSPECT_IND] =
+                               HTT_T2H_MSG_TYPE_TX_INSPECT_IND,
+       [HTT_10_4_T2H_MSG_TYPE_MGMT_TX_COMPL_IND] =
+                               HTT_T2H_MSG_TYPE_MGMT_TX_COMPLETION,
+       [HTT_10_4_T2H_MSG_TYPE_CHAN_CHANGE] = HTT_T2H_MSG_TYPE_CHAN_CHANGE,
+       [HTT_10_4_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND] =
+                               HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND,
+       [HTT_10_4_T2H_MSG_TYPE_RX_PN_IND] = HTT_T2H_MSG_TYPE_RX_PN_IND,
+       [HTT_10_4_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND] =
+                               HTT_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND,
+       [HTT_10_4_T2H_MSG_TYPE_TEST] = HTT_T2H_MSG_TYPE_TEST,
+       [HTT_10_4_T2H_MSG_TYPE_EN_STATS] = HTT_T2H_MSG_TYPE_EN_STATS,
+       [HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF,
+       [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] =
+                               HTT_T2H_MSG_TYPE_TX_FETCH_IND,
+       [HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF] =
+                               HTT_T2H_MSG_TYPE_TX_FETCH_CONF,
+       [HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] =
+                               HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
+       [HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND] =
+                               HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND,
+};
+
 int ath10k_htt_connect(struct ath10k_htt *htt)
 {
        struct ath10k_htc_svc_conn_req conn_req;
@@ -147,6 +184,10 @@ int ath10k_htt_init(struct ath10k *ar)
                2; /* ip4 dscp or ip6 priority */
 
        switch (ar->htt.op_version) {
+       case ATH10K_FW_HTT_OP_VERSION_10_4:
+               ar->htt.t2h_msg_types = htt_10_4_t2h_msg_types;
+               ar->htt.t2h_msg_types_max = HTT_10_4_T2H_NUM_MSGS;
+               break;
        case ATH10K_FW_HTT_OP_VERSION_10_1:
                ar->htt.t2h_msg_types = htt_10x_t2h_msg_types;
                ar->htt.t2h_msg_types_max = HTT_10X_T2H_NUM_MSGS;
@@ -208,5 +249,9 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
        if (status)
                return status;
 
+       status = ath10k_htt_send_frag_desc_bank_cfg(htt);
+       if (status)
+               return status;
+
        return ath10k_htt_send_rx_ring_cfg_ll(htt);
 }
index 7e8a0d83566379b01fec63235d968a9913639b52..8bdf1e7dd1718ab72199efe70bf1dc476adb0fa2 100644 (file)
@@ -87,6 +87,11 @@ struct htt_data_tx_desc_frag {
        __le32 len;
 } __packed;
 
+struct htt_msdu_ext_desc {
+       __le32 tso_flag[4];
+       struct htt_data_tx_desc_frag frags[6];
+};
+
 enum htt_data_tx_desc_flags0 {
        HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT = 1 << 0,
        HTT_DATA_TX_DESC_FLAGS0_NO_AGGR         = 1 << 1,
@@ -349,6 +354,38 @@ enum htt_tlv_t2h_msg_type {
        HTT_TLV_T2H_NUM_MSGS
 };
 
+enum htt_10_4_t2h_msg_type {
+       HTT_10_4_T2H_MSG_TYPE_VERSION_CONF           = 0x0,
+       HTT_10_4_T2H_MSG_TYPE_RX_IND                 = 0x1,
+       HTT_10_4_T2H_MSG_TYPE_RX_FLUSH               = 0x2,
+       HTT_10_4_T2H_MSG_TYPE_PEER_MAP               = 0x3,
+       HTT_10_4_T2H_MSG_TYPE_PEER_UNMAP             = 0x4,
+       HTT_10_4_T2H_MSG_TYPE_RX_ADDBA               = 0x5,
+       HTT_10_4_T2H_MSG_TYPE_RX_DELBA               = 0x6,
+       HTT_10_4_T2H_MSG_TYPE_TX_COMPL_IND           = 0x7,
+       HTT_10_4_T2H_MSG_TYPE_PKTLOG                 = 0x8,
+       HTT_10_4_T2H_MSG_TYPE_STATS_CONF             = 0x9,
+       HTT_10_4_T2H_MSG_TYPE_RX_FRAG_IND            = 0xa,
+       HTT_10_4_T2H_MSG_TYPE_SEC_IND                = 0xb,
+       HTT_10_4_T2H_MSG_TYPE_RC_UPDATE_IND          = 0xc,
+       HTT_10_4_T2H_MSG_TYPE_TX_INSPECT_IND         = 0xd,
+       HTT_10_4_T2H_MSG_TYPE_MGMT_TX_COMPL_IND      = 0xe,
+       HTT_10_4_T2H_MSG_TYPE_CHAN_CHANGE            = 0xf,
+       HTT_10_4_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND   = 0x10,
+       HTT_10_4_T2H_MSG_TYPE_RX_PN_IND              = 0x11,
+       HTT_10_4_T2H_MSG_TYPE_RX_OFFLOAD_DELIVER_IND = 0x12,
+       HTT_10_4_T2H_MSG_TYPE_TEST                   = 0x13,
+       HTT_10_4_T2H_MSG_TYPE_EN_STATS               = 0x14,
+       HTT_10_4_T2H_MSG_TYPE_AGGR_CONF              = 0x15,
+       HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND           = 0x16,
+       HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF          = 0x17,
+       HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD         = 0x18,
+       /* 0x19 to 0x2f are reserved */
+       HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND     = 0x30,
+       /* keep this last */
+       HTT_10_4_T2H_NUM_MSGS
+};
+
 enum htt_t2h_msg_type {
        HTT_T2H_MSG_TYPE_VERSION_CONF,
        HTT_T2H_MSG_TYPE_RX_IND,
@@ -375,6 +412,10 @@ enum htt_t2h_msg_type {
        HTT_T2H_MSG_TYPE_AGGR_CONF,
        HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
        HTT_T2H_MSG_TYPE_TEST,
+       HTT_T2H_MSG_TYPE_EN_STATS,
+       HTT_T2H_MSG_TYPE_TX_FETCH_IND,
+       HTT_T2H_MSG_TYPE_TX_FETCH_CONF,
+       HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND,
        /* keep this last */
        HTT_T2H_NUM_MSGS
 };
@@ -1430,6 +1471,11 @@ struct ath10k_htt {
 
        /* rx_status template */
        struct ieee80211_rx_status rx_status;
+
+       struct {
+               dma_addr_t paddr;
+               struct htt_msdu_ext_desc *vaddr;
+       } frag_desc;
 };
 
 #define RX_HTT_HDR_STATUS_LEN 64
@@ -1497,6 +1543,7 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
 void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
 int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
 int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
+int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt);
 int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
 int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
                                u8 max_subfrms_ampdu,
index 89eb16b30fc42479a3b1c11a7b9b3fd88c043490..d7d118328f31b2bc96d661cae2c0d8e2591d0ae5 100644 (file)
@@ -1201,7 +1201,6 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
 {
        struct htt_rx_desc *rxd;
        enum rx_msdu_decap_format decap;
-       struct ieee80211_hdr *hdr;
 
        /* First msdu's decapped header:
         * [802.11 header] <-- padded to 4 bytes long
@@ -1215,7 +1214,6 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
         */
 
        rxd = (void *)msdu->data - sizeof(*rxd);
-       hdr = (void *)rxd->rx_hdr_status;
        decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
                   RX_MSDU_START_INFO1_DECAP_FORMAT);
 
@@ -2074,6 +2072,10 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                break;
        case HTT_T2H_MSG_TYPE_CHAN_CHANGE:
                break;
+       case HTT_T2H_MSG_TYPE_EN_STATS:
+       case HTT_T2H_MSG_TYPE_TX_FETCH_IND:
+       case HTT_T2H_MSG_TYPE_TX_FETCH_CONF:
+       case HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND:
        default:
                ath10k_warn(ar, "htt event (%d) not handled\n",
                            resp->hdr.msg_type);
index a60ef7d1d5fcb98278b3838858432f4cb3c8930a..148d5b607c3cf08decf9aba36b82d16e87cf19b9 100644 (file)
@@ -84,6 +84,7 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
 int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
 {
        struct ath10k *ar = htt->ar;
+       int ret, size;
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
                   htt->max_num_pending_tx);
@@ -94,11 +95,31 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
        htt->tx_pool = dma_pool_create("ath10k htt tx pool", htt->ar->dev,
                                       sizeof(struct ath10k_htt_txbuf), 4, 0);
        if (!htt->tx_pool) {
-               idr_destroy(&htt->pending_tx);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto free_idr_pending_tx;
+       }
+
+       if (!ar->hw_params.continuous_frag_desc)
+               goto skip_frag_desc_alloc;
+
+       size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc);
+       htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size,
+                                                 &htt->frag_desc.paddr,
+                                                 GFP_DMA);
+       if (!htt->frag_desc.vaddr) {
+               ath10k_warn(ar, "failed to alloc fragment desc memory\n");
+               ret = -ENOMEM;
+               goto free_tx_pool;
        }
 
+skip_frag_desc_alloc:
        return 0;
+
+free_tx_pool:
+       dma_pool_destroy(htt->tx_pool);
+free_idr_pending_tx:
+       idr_destroy(&htt->pending_tx);
+       return ret;
 }
 
 static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
@@ -121,9 +142,18 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
 
 void ath10k_htt_tx_free(struct ath10k_htt *htt)
 {
+       int size;
+
        idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar);
        idr_destroy(&htt->pending_tx);
        dma_pool_destroy(htt->tx_pool);
+
+       if (htt->frag_desc.vaddr) {
+               size = htt->max_num_pending_tx *
+                                 sizeof(struct htt_msdu_ext_desc);
+               dma_free_coherent(htt->ar->dev, size, htt->frag_desc.vaddr,
+                                 htt->frag_desc.paddr);
+       }
 }
 
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
@@ -201,6 +231,48 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)
        return 0;
 }
 
+int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
+{
+       struct ath10k *ar = htt->ar;
+       struct sk_buff *skb;
+       struct htt_cmd *cmd;
+       int ret, size;
+
+       if (!ar->hw_params.continuous_frag_desc)
+               return 0;
+
+       if (!htt->frag_desc.paddr) {
+               ath10k_warn(ar, "invalid frag desc memory\n");
+               return -EINVAL;
+       }
+
+       size = sizeof(cmd->hdr) + sizeof(cmd->frag_desc_bank_cfg);
+       skb = ath10k_htc_alloc_skb(ar, size);
+       if (!skb)
+               return -ENOMEM;
+
+       skb_put(skb, size);
+       cmd = (struct htt_cmd *)skb->data;
+       cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_FRAG_DESC_BANK_CFG;
+       cmd->frag_desc_bank_cfg.info = 0;
+       cmd->frag_desc_bank_cfg.num_banks = 1;
+       cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc);
+       cmd->frag_desc_bank_cfg.bank_base_addrs[0] =
+                               __cpu_to_le32(htt->frag_desc.paddr);
+       cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id =
+                               __cpu_to_le16(htt->max_num_pending_tx - 1);
+
+       ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
+       if (ret) {
+               ath10k_warn(ar, "failed to send frag desc bank cfg request: %d\n",
+                           ret);
+               dev_kfree_skb_any(skb);
+               return ret;
+       }
+
+       return 0;
+}
+
 int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
 {
        struct ath10k *ar = htt->ar;
index 5997f00afe3b43b677f1718a64a213090c969d92..fef7ccf6e185eacee92b8eee1a22071edff550a5 100644 (file)
@@ -34,8 +34,15 @@ const struct ath10k_hw_regs qca988x_regs = {
        .ce7_base_address               = 0x00059000,
        .soc_reset_control_si0_rst_mask = 0x00000001,
        .soc_reset_control_ce_rst_mask  = 0x00040000,
-       .soc_chip_id_address            = 0x00ec,
-       .scratch_3_address              = 0x0030,
+       .soc_chip_id_address            = 0x000000ec,
+       .scratch_3_address              = 0x00000030,
+       .fw_indicator_address           = 0x00009030,
+       .pcie_local_base_address        = 0x00080000,
+       .ce_wrap_intr_sum_host_msi_lsb  = 0x00000008,
+       .ce_wrap_intr_sum_host_msi_mask = 0x0000ff00,
+       .pcie_intr_fw_mask              = 0x00000400,
+       .pcie_intr_ce_mask_all          = 0x0007f800,
+       .pcie_intr_clr_address          = 0x00000014,
 };
 
 const struct ath10k_hw_regs qca6174_regs = {
@@ -54,8 +61,79 @@ const struct ath10k_hw_regs qca6174_regs = {
        .ce7_base_address                       = 0x00036000,
        .soc_reset_control_si0_rst_mask         = 0x00000000,
        .soc_reset_control_ce_rst_mask          = 0x00000001,
-       .soc_chip_id_address                    = 0x000f0,
-       .scratch_3_address                      = 0x0028,
+       .soc_chip_id_address                    = 0x000000f0,
+       .scratch_3_address                      = 0x00000028,
+       .fw_indicator_address                   = 0x0003a028,
+       .pcie_local_base_address                = 0x00080000,
+       .ce_wrap_intr_sum_host_msi_lsb          = 0x00000008,
+       .ce_wrap_intr_sum_host_msi_mask         = 0x0000ff00,
+       .pcie_intr_fw_mask                      = 0x00000400,
+       .pcie_intr_ce_mask_all                  = 0x0007f800,
+       .pcie_intr_clr_address                  = 0x00000014,
+};
+
+const struct ath10k_hw_regs qca99x0_regs = {
+       .rtc_state_cold_reset_mask              = 0x00000400,
+       .rtc_soc_base_address                   = 0x00080000,
+       .rtc_wmac_base_address                  = 0x00000000,
+       .soc_core_base_address                  = 0x00082000,
+       .ce_wrapper_base_address                = 0x0004d000,
+       .ce0_base_address                       = 0x0004a000,
+       .ce1_base_address                       = 0x0004a400,
+       .ce2_base_address                       = 0x0004a800,
+       .ce3_base_address                       = 0x0004ac00,
+       .ce4_base_address                       = 0x0004b000,
+       .ce5_base_address                       = 0x0004b400,
+       .ce6_base_address                       = 0x0004b800,
+       .ce7_base_address                       = 0x0004bc00,
+       /* Note: qca99x0 supports upto 12 Copy Engines. Other than address of
+        * CE0 and CE1 no other copy engine is directly referred in the code.
+        * It is not really neccessary to assign address for newly supported
+        * CEs in this address table.
+        *      Copy Engine             Address
+        *      CE8                     0x0004c000
+        *      CE9                     0x0004c400
+        *      CE10                    0x0004c800
+        *      CE11                    0x0004cc00
+        */
+       .soc_reset_control_si0_rst_mask         = 0x00000001,
+       .soc_reset_control_ce_rst_mask          = 0x00000100,
+       .soc_chip_id_address                    = 0x000000ec,
+       .scratch_3_address                      = 0x00040050,
+       .fw_indicator_address                   = 0x00040050,
+       .pcie_local_base_address                = 0x00000000,
+       .ce_wrap_intr_sum_host_msi_lsb          = 0x0000000c,
+       .ce_wrap_intr_sum_host_msi_mask         = 0x00fff000,
+       .pcie_intr_fw_mask                      = 0x00100000,
+       .pcie_intr_ce_mask_all                  = 0x000fff00,
+       .pcie_intr_clr_address                  = 0x00000010,
+};
+
+const struct ath10k_hw_values qca988x_values = {
+       .rtc_state_val_on               = 3,
+       .ce_count                       = 8,
+       .msi_assign_ce_max              = 7,
+       .num_target_ce_config_wlan      = 7,
+       .ce_desc_meta_data_mask         = 0xFFFC,
+       .ce_desc_meta_data_lsb          = 2,
+};
+
+const struct ath10k_hw_values qca6174_values = {
+       .rtc_state_val_on               = 3,
+       .ce_count                       = 8,
+       .msi_assign_ce_max              = 7,
+       .num_target_ce_config_wlan      = 7,
+       .ce_desc_meta_data_mask         = 0xFFFC,
+       .ce_desc_meta_data_lsb          = 2,
+};
+
+const struct ath10k_hw_values qca99x0_values = {
+       .rtc_state_val_on               = 5,
+       .ce_count                       = 12,
+       .msi_assign_ce_max              = 12,
+       .num_target_ce_config_wlan      = 10,
+       .ce_desc_meta_data_mask         = 0xFFF0,
+       .ce_desc_meta_data_lsb          = 4,
 };
 
 void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
index 85cca29375fee8f08ab09975c31cc3130194176e..9172285175461ab359f9a7b552a7276b664000a9 100644 (file)
@@ -72,6 +72,18 @@ enum qca6174_chip_id_rev {
 #define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin"
 #define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234
 
+/* QCA99X0 1.0 definitions (unsupported) */
+#define QCA99X0_HW_1_0_CHIP_ID_REV     0x0
+
+/* QCA99X0 2.0 definitions */
+#define QCA99X0_HW_2_0_DEV_VERSION     0x01000000
+#define QCA99X0_HW_2_0_CHIP_ID_REV     0x1
+#define QCA99X0_HW_2_0_FW_DIR          ATH10K_FW_DIR "/QCA99X0/hw2.0"
+#define QCA99X0_HW_2_0_FW_FILE         "firmware.bin"
+#define QCA99X0_HW_2_0_OTP_FILE        "otp.bin"
+#define QCA99X0_HW_2_0_BOARD_DATA_FILE "board.bin"
+#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
+
 #define ATH10K_FW_API2_FILE            "firmware-2.bin"
 #define ATH10K_FW_API3_FILE            "firmware-3.bin"
 
@@ -112,6 +124,9 @@ enum ath10k_fw_ie_type {
         * FW API 5 and above.
         */
        ATH10K_FW_IE_HTT_OP_VERSION = 6,
+
+       /* Code swap image for firmware binary */
+       ATH10K_FW_IE_FW_CODE_SWAP_IMAGE = 7,
 };
 
 enum ath10k_fw_wmi_op_version {
@@ -122,6 +137,7 @@ enum ath10k_fw_wmi_op_version {
        ATH10K_FW_WMI_OP_VERSION_10_2 = 3,
        ATH10K_FW_WMI_OP_VERSION_TLV = 4,
        ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5,
+       ATH10K_FW_WMI_OP_VERSION_10_4 = 6,
 
        /* keep last */
        ATH10K_FW_WMI_OP_VERSION_MAX,
@@ -137,6 +153,8 @@ enum ath10k_fw_htt_op_version {
 
        ATH10K_FW_HTT_OP_VERSION_TLV = 3,
 
+       ATH10K_FW_HTT_OP_VERSION_10_4 = 4,
+
        /* keep last */
        ATH10K_FW_HTT_OP_VERSION_MAX,
 };
@@ -144,6 +162,7 @@ enum ath10k_fw_htt_op_version {
 enum ath10k_hw_rev {
        ATH10K_HW_QCA988X,
        ATH10K_HW_QCA6174,
+       ATH10K_HW_QCA99X0,
 };
 
 struct ath10k_hw_regs {
@@ -164,16 +183,38 @@ struct ath10k_hw_regs {
        u32 soc_reset_control_ce_rst_mask;
        u32 soc_chip_id_address;
        u32 scratch_3_address;
+       u32 fw_indicator_address;
+       u32 pcie_local_base_address;
+       u32 ce_wrap_intr_sum_host_msi_lsb;
+       u32 ce_wrap_intr_sum_host_msi_mask;
+       u32 pcie_intr_fw_mask;
+       u32 pcie_intr_ce_mask_all;
+       u32 pcie_intr_clr_address;
 };
 
 extern const struct ath10k_hw_regs qca988x_regs;
 extern const struct ath10k_hw_regs qca6174_regs;
+extern const struct ath10k_hw_regs qca99x0_regs;
+
+struct ath10k_hw_values {
+       u32 rtc_state_val_on;
+       u8 ce_count;
+       u8 msi_assign_ce_max;
+       u8 num_target_ce_config_wlan;
+       u16 ce_desc_meta_data_mask;
+       u8 ce_desc_meta_data_lsb;
+};
+
+extern const struct ath10k_hw_values qca988x_values;
+extern const struct ath10k_hw_values qca6174_values;
+extern const struct ath10k_hw_values qca99x0_values;
 
 void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
                                u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
 
 #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
 #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
+#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
 
 /* Known pecularities:
  *  - current FW doesn't support raw rx mode (last tested v599)
@@ -310,8 +351,73 @@ enum ath10k_hw_rate_cck {
 #define TARGET_TLV_NUM_MSDU_DESC               (1024 + 32)
 #define TARGET_TLV_NUM_WOW_PATTERNS            22
 
+/* Diagnostic Window */
+#define CE_DIAG_PIPE   7
+
+#define NUM_TARGET_CE_CONFIG_WLAN ar->hw_values->num_target_ce_config_wlan
+
+/* Target specific defines for 10.4 firmware */
+#define TARGET_10_4_NUM_VDEVS                  16
+#define TARGET_10_4_NUM_STATIONS               32
+#define TARGET_10_4_NUM_PEERS                  ((TARGET_10_4_NUM_STATIONS) + \
+                                                (TARGET_10_4_NUM_VDEVS))
+#define TARGET_10_4_ACTIVE_PEERS               0
+
+/* TODO: increase qcache max client limit to 512 after
+ * testing with 512 client.
+ */
+#define TARGET_10_4_NUM_QCACHE_PEERS_MAX       256
+#define TARGET_10_4_QCACHE_ACTIVE_PEERS                50
+#define TARGET_10_4_NUM_OFFLOAD_PEERS          0
+#define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS  0
+#define TARGET_10_4_NUM_PEER_KEYS              2
+#define TARGET_10_4_TGT_NUM_TIDS               ((TARGET_10_4_NUM_PEERS) * 2)
+#define TARGET_10_4_AST_SKID_LIMIT             32
+#define TARGET_10_4_TX_CHAIN_MASK              (BIT(0) | BIT(1) | \
+                                                BIT(2) | BIT(3))
+#define TARGET_10_4_RX_CHAIN_MASK              (BIT(0) | BIT(1) | \
+                                                BIT(2) | BIT(3))
+
+/* 100 ms for video, best-effort, and background */
+#define TARGET_10_4_RX_TIMEOUT_LO_PRI          100
+
+/* 40 ms for voice */
+#define TARGET_10_4_RX_TIMEOUT_HI_PRI          40
+
+#define TARGET_10_4_RX_DECAP_MODE              ATH10K_HW_TXRX_NATIVE_WIFI
+#define TARGET_10_4_SCAN_MAX_REQS              4
+#define TARGET_10_4_BMISS_OFFLOAD_MAX_VDEV     3
+#define TARGET_10_4_ROAM_OFFLOAD_MAX_VDEV      3
+#define TARGET_10_4_ROAM_OFFLOAD_MAX_PROFILES   8
+
+/* Note: mcast to ucast is disabled by default */
+#define TARGET_10_4_NUM_MCAST_GROUPS           0
+#define TARGET_10_4_NUM_MCAST_TABLE_ELEMS      0
+#define TARGET_10_4_MCAST2UCAST_MODE           0
+
+#define TARGET_10_4_TX_DBG_LOG_SIZE            1024
+#define TARGET_10_4_NUM_WDS_ENTRIES            32
+#define TARGET_10_4_DMA_BURST_SIZE             1
+#define TARGET_10_4_MAC_AGGR_DELIM             0
+#define TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK 1
+#define TARGET_10_4_VOW_CONFIG                 0
+#define TARGET_10_4_GTK_OFFLOAD_MAX_VDEV       3
+#define TARGET_10_4_NUM_MSDU_DESC              (1024 + 400)
+#define TARGET_10_4_11AC_TX_MAX_FRAGS          2
+#define TARGET_10_4_MAX_PEER_EXT_STATS         16
+#define TARGET_10_4_SMART_ANT_CAP              0
+#define TARGET_10_4_BK_MIN_FREE                        0
+#define TARGET_10_4_BE_MIN_FREE                        0
+#define TARGET_10_4_VI_MIN_FREE                        0
+#define TARGET_10_4_VO_MIN_FREE                        0
+#define TARGET_10_4_RX_BATCH_MODE              1
+#define TARGET_10_4_THERMAL_THROTTLING_CONFIG  0
+#define TARGET_10_4_ATF_CONFIG                 0
+#define TARGET_10_4_IPHDR_PAD_CONFIG           1
+#define TARGET_10_4_QWRAP_CONFIG               0
+
 /* Number of Copy Engines supported */
-#define CE_COUNT 8
+#define CE_COUNT ar->hw_values->ce_count
 
 /*
  * Total number of PCIe MSI interrupts requested for all interrupt sources.
@@ -335,10 +441,10 @@ enum ath10k_hw_rate_cck {
 
 /* MSIs for Copy Engines */
 #define MSI_ASSIGN_CE_INITIAL  1
-#define MSI_ASSIGN_CE_MAX      7
+#define MSI_ASSIGN_CE_MAX      ar->hw_values->msi_assign_ce_max
 
 /* as of IP3.7.1 */
-#define RTC_STATE_V_ON                         3
+#define RTC_STATE_V_ON                         ar->hw_values->rtc_state_val_on
 
 #define RTC_STATE_COLD_RESET_MASK              ar->regs->rtc_state_cold_reset_mask
 #define RTC_STATE_V_LSB                                0
@@ -374,7 +480,7 @@ enum ath10k_hw_rate_cck {
 #define CE7_BASE_ADDRESS                       ar->regs->ce7_base_address
 #define DBI_BASE_ADDRESS                       0x00060000
 #define WLAN_ANALOG_INTF_PCIE_BASE_ADDRESS     0x0006c000
-#define PCIE_LOCAL_BASE_ADDRESS                        0x00080000
+#define PCIE_LOCAL_BASE_ADDRESS                ar->regs->pcie_local_base_address
 
 #define SOC_RESET_CONTROL_ADDRESS              0x00000000
 #define SOC_RESET_CONTROL_OFFSET               0x00000000
@@ -448,7 +554,7 @@ enum ath10k_hw_rate_cck {
 #define CORE_CTRL_ADDRESS                      0x0000
 #define PCIE_INTR_ENABLE_ADDRESS               0x0008
 #define PCIE_INTR_CAUSE_ADDRESS                        0x000c
-#define PCIE_INTR_CLR_ADDRESS                  0x0014
+#define PCIE_INTR_CLR_ADDRESS                  ar->regs->pcie_intr_clr_address
 #define SCRATCH_3_ADDRESS                      ar->regs->scratch_3_address
 #define CPU_INTR_ADDRESS                       0x0010
 
@@ -456,16 +562,18 @@ enum ath10k_hw_rate_cck {
 #define CCNT_TO_MSEC(x) ((x) / 88000)
 
 /* Firmware indications to the Host via SCRATCH_3 register. */
-#define FW_INDICATOR_ADDRESS   (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS)
+#define FW_INDICATOR_ADDRESS                   ar->regs->fw_indicator_address
 #define FW_IND_EVENT_PENDING                   1
 #define FW_IND_INITIALIZED                     2
 
 /* HOST_REG interrupt from firmware */
-#define PCIE_INTR_FIRMWARE_MASK                        0x00000400
-#define PCIE_INTR_CE_MASK_ALL                  0x0007f800
+#define PCIE_INTR_FIRMWARE_MASK                        ar->regs->pcie_intr_fw_mask
+#define PCIE_INTR_CE_MASK_ALL                  ar->regs->pcie_intr_ce_mask_all
 
 #define DRAM_BASE_ADDRESS                      0x00400000
 
+#define PCIE_BAR_REG_ADDRESS                   0x40030
+
 #define MISSING 0
 
 #define SYSTEM_SLEEP_OFFSET                    SOC_SYSTEM_SLEEP_OFFSET
index 218b6af63447458fa81960479afeeecf9a1520e9..c9a7d5b5dffc5d367fe0ad9d84f071430eb8fb24 100644 (file)
@@ -1668,7 +1668,7 @@ static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
        return 0;
 }
 
-static int ath10k_mac_ps_vif_count(struct ath10k *ar)
+static int ath10k_mac_num_vifs_started(struct ath10k *ar)
 {
        struct ath10k_vif *arvif;
        int num = 0;
@@ -1676,7 +1676,7 @@ static int ath10k_mac_ps_vif_count(struct ath10k *ar)
        lockdep_assert_held(&ar->conf_mutex);
 
        list_for_each_entry(arvif, &ar->arvifs, list)
-               if (arvif->ps)
+               if (arvif->is_started)
                        num++;
 
        return num;
@@ -1700,7 +1700,7 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
 
        enable_ps = arvif->ps;
 
-       if (enable_ps && ath10k_mac_ps_vif_count(ar) > 1 &&
+       if (enable_ps && ath10k_mac_num_vifs_started(ar) > 1 &&
            !test_bit(ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT,
                      ar->fw_features)) {
                ath10k_warn(ar, "refusing to enable ps on vdev %i: not supported by fw\n",
@@ -3034,38 +3034,16 @@ static void ath10k_mac_vif_handle_tx_pause(struct ath10k_vif *arvif,
 
        lockdep_assert_held(&ar->htt.tx_lock);
 
-       switch (pause_id) {
-       case WMI_TLV_TX_PAUSE_ID_MCC:
-       case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
-       case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
-       case WMI_TLV_TX_PAUSE_ID_AP_PS:
-       case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
-               switch (action) {
-               case WMI_TLV_TX_PAUSE_ACTION_STOP:
-                       ath10k_mac_vif_tx_lock(arvif, pause_id);
-                       break;
-               case WMI_TLV_TX_PAUSE_ACTION_WAKE:
-                       ath10k_mac_vif_tx_unlock(arvif, pause_id);
-                       break;
-               default:
-                       ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
-                                   action, arvif->vdev_id);
-                       break;
-               }
+       switch (action) {
+       case WMI_TLV_TX_PAUSE_ACTION_STOP:
+               ath10k_mac_vif_tx_lock(arvif, pause_id);
+               break;
+       case WMI_TLV_TX_PAUSE_ACTION_WAKE:
+               ath10k_mac_vif_tx_unlock(arvif, pause_id);
                break;
-       case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
-       case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
-       case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
-       case WMI_TLV_TX_PAUSE_ID_HOST:
        default:
-               /* FIXME: Some pause_ids aren't vdev specific. Instead they
-                * target peer_id and tid. Implementing these could improve
-                * traffic scheduling fairness across multiple connected
-                * stations in AP/IBSS modes.
-                */
-               ath10k_dbg(ar, ATH10K_DBG_MAC,
-                          "mac ignoring unsupported tx pause vdev %i id %d\n",
-                          arvif->vdev_id, pause_id);
+               ath10k_warn(ar, "received unknown tx pause action %d on vdev %i, ignoring\n",
+                           action, arvif->vdev_id);
                break;
        }
 }
@@ -3082,12 +3060,15 @@ static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac,
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
        struct ath10k_mac_tx_pause *arg = data;
 
+       if (arvif->vdev_id != arg->vdev_id)
+               return;
+
        ath10k_mac_vif_handle_tx_pause(arvif, arg->pause_id, arg->action);
 }
 
-void ath10k_mac_handle_tx_pause(struct ath10k *ar, u32 vdev_id,
-                               enum wmi_tlv_tx_pause_id pause_id,
-                               enum wmi_tlv_tx_pause_action action)
+void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
+                                    enum wmi_tlv_tx_pause_id pause_id,
+                                    enum wmi_tlv_tx_pause_action action)
 {
        struct ath10k_mac_tx_pause arg = {
                .vdev_id = vdev_id,
@@ -3449,14 +3430,13 @@ void __ath10k_scan_finish(struct ath10k *ar)
        case ATH10K_SCAN_IDLE:
                break;
        case ATH10K_SCAN_RUNNING:
-               if (ar->scan.is_roc)
-                       ieee80211_remain_on_channel_expired(ar->hw);
-               /* fall through */
        case ATH10K_SCAN_ABORTING:
                if (!ar->scan.is_roc)
                        ieee80211_scan_completed(ar->hw,
                                                 (ar->scan.state ==
                                                  ATH10K_SCAN_ABORTING));
+               else if (ar->scan.roc_notify)
+                       ieee80211_remain_on_channel_expired(ar->hw);
                /* fall through */
        case ATH10K_SCAN_STARTING:
                ar->scan.state = ATH10K_SCAN_IDLE;
@@ -4641,9 +4621,6 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
        arg.vdev_id = arvif->vdev_id;
        arg.scan_id = ATH10K_SCAN_ID;
 
-       if (!req->no_cck)
-               arg.scan_ctrl_flags |= WMI_SCAN_ADD_CCK_RATES;
-
        if (req->ie_len) {
                arg.ie_len = req->ie_len;
                memcpy(arg.ie, req->ie, arg.ie_len);
@@ -5462,6 +5439,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
                ar->scan.is_roc = true;
                ar->scan.vdev_id = arvif->vdev_id;
                ar->scan.roc_freq = chan->center_freq;
+               ar->scan.roc_notify = true;
                ret = 0;
                break;
        case ATH10K_SCAN_STARTING:
@@ -5525,7 +5503,13 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw)
        struct ath10k *ar = hw->priv;
 
        mutex_lock(&ar->conf_mutex);
+
+       spin_lock_bh(&ar->data_lock);
+       ar->scan.roc_notify = false;
+       spin_unlock_bh(&ar->data_lock);
+
        ath10k_scan_abort(ar);
+
        mutex_unlock(&ar->conf_mutex);
 
        cancel_delayed_work_sync(&ar->scan.timeout);
@@ -5566,7 +5550,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 {
        struct ath10k *ar = hw->priv;
        bool skip;
-       int ret;
+       long time_left;
 
        /* mac80211 doesn't care if we really xmit queued frames or not
         * we'll collect those frames either way if we stop/delete vdevs */
@@ -5578,7 +5562,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        if (ar->state == ATH10K_STATE_WEDGED)
                goto skip;
 
-       ret = wait_event_timeout(ar->htt.empty_tx_wq, ({
+       time_left = wait_event_timeout(ar->htt.empty_tx_wq, ({
                        bool empty;
 
                        spin_lock_bh(&ar->htt.tx_lock);
@@ -5592,9 +5576,9 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                        (empty || skip);
                }), ATH10K_FLUSH_TIMEOUT_HZ);
 
-       if (ret <= 0 || skip)
-               ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %i\n",
-                           skip, ar->state, ret);
+       if (time_left == 0 || skip)
+               ath10k_warn(ar, "failed to flush transmit queue (skip %i ar-state %i): %ld\n",
+                           skip, ar->state, time_left);
 
 skip:
        mutex_unlock(&ar->conf_mutex);
@@ -6219,6 +6203,13 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 
        arvif->is_started = true;
 
+       ret = ath10k_mac_vif_setup_ps(arvif);
+       if (ret) {
+               ath10k_warn(ar, "failed to update vdev %i ps: %d\n",
+                           arvif->vdev_id, ret);
+               goto err_stop;
+       }
+
        if (vif->type == NL80211_IFTYPE_MONITOR) {
                ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, 0, vif->addr);
                if (ret) {
@@ -6236,6 +6227,7 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
 err_stop:
        ath10k_vdev_stop(arvif);
        arvif->is_started = false;
+       ath10k_mac_vif_setup_ps(arvif);
 
 err:
        mutex_unlock(&ar->conf_mutex);
@@ -6565,8 +6557,11 @@ static const struct ieee80211_iface_combination ath10k_10x_if_comb[] = {
 static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = {
        {
                .max = 2,
-               .types = BIT(NL80211_IFTYPE_STATION) |
-                        BIT(NL80211_IFTYPE_AP) |
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max = 2,
+               .types = BIT(NL80211_IFTYPE_AP) |
                         BIT(NL80211_IFTYPE_P2P_CLIENT) |
                         BIT(NL80211_IFTYPE_P2P_GO),
        },
@@ -6576,6 +6571,26 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit[] = {
        },
 };
 
+static const struct ieee80211_iface_limit ath10k_tlv_qcs_if_limit[] = {
+       {
+               .max = 2,
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max = 2,
+               .types = BIT(NL80211_IFTYPE_P2P_CLIENT),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_AP) |
+                        BIT(NL80211_IFTYPE_P2P_GO),
+       },
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
+       },
+};
+
 static const struct ieee80211_iface_limit ath10k_tlv_if_limit_ibss[] = {
        {
                .max = 1,
@@ -6594,7 +6609,7 @@ static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = {
        {
                .limits = ath10k_tlv_if_limit,
                .num_different_channels = 1,
-               .max_interfaces = 3,
+               .max_interfaces = 4,
                .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit),
        },
        {
@@ -6608,10 +6623,16 @@ static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = {
 static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = {
        {
                .limits = ath10k_tlv_if_limit,
-               .num_different_channels = 2,
-               .max_interfaces = 3,
+               .num_different_channels = 1,
+               .max_interfaces = 4,
                .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit),
        },
+       {
+               .limits = ath10k_tlv_qcs_if_limit,
+               .num_different_channels = 2,
+               .max_interfaces = 4,
+               .n_limits = ARRAY_SIZE(ath10k_tlv_qcs_if_limit),
+       },
        {
                .limits = ath10k_tlv_if_limit_ibss,
                .num_different_channels = 1,
@@ -6620,6 +6641,33 @@ static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = {
        },
 };
 
+static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = {
+       {
+               .max = 1,
+               .types = BIT(NL80211_IFTYPE_STATION),
+       },
+       {
+               .max    = 16,
+               .types  = BIT(NL80211_IFTYPE_AP)
+       },
+};
+
+static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
+       {
+               .limits = ath10k_10_4_if_limits,
+               .n_limits = ARRAY_SIZE(ath10k_10_4_if_limits),
+               .max_interfaces = 16,
+               .num_different_channels = 1,
+               .beacon_int_infra_match = true,
+#ifdef CONFIG_ATH10K_DFS_CERTIFIED
+               .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                       BIT(NL80211_CHAN_WIDTH_20) |
+                                       BIT(NL80211_CHAN_WIDTH_40) |
+                                       BIT(NL80211_CHAN_WIDTH_80),
+#endif
+       },
+};
+
 static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
 {
        struct ieee80211_sta_vht_cap vht_cap = {0};
@@ -6902,6 +6950,8 @@ int ath10k_mac_register(struct ath10k *ar)
                goto err_free;
        }
 
+       wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
+
        /*
         * on LL hardware queues are managed entirely by the FW
         * so we only advertise to mac we can do the queues thing
@@ -6941,6 +6991,11 @@ int ath10k_mac_register(struct ath10k *ar)
                ar->hw->wiphy->n_iface_combinations =
                        ARRAY_SIZE(ath10k_10x_if_comb);
                break;
+       case ATH10K_FW_WMI_OP_VERSION_10_4:
+               ar->hw->wiphy->iface_combinations = ath10k_10_4_if_comb;
+               ar->hw->wiphy->n_iface_combinations =
+                       ARRAY_SIZE(ath10k_10_4_if_comb);
+               break;
        case ATH10K_FW_WMI_OP_VERSION_UNSET:
        case ATH10K_FW_WMI_OP_VERSION_MAX:
                WARN_ON(1);
index b291f063705c3bb816f811aad450e9549aca5dfb..e3cefe4c7cfd04aa4e8c142282330068209bcb68 100644 (file)
@@ -61,9 +61,9 @@ int ath10k_mac_vif_chan(struct ieee80211_vif *vif,
 
 void ath10k_mac_handle_beacon(struct ath10k *ar, struct sk_buff *skb);
 void ath10k_mac_handle_beacon_miss(struct ath10k *ar, u32 vdev_id);
-void ath10k_mac_handle_tx_pause(struct ath10k *ar, u32 vdev_id,
-                               enum wmi_tlv_tx_pause_id pause_id,
-                               enum wmi_tlv_tx_pause_action action);
+void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
+                                    enum wmi_tlv_tx_pause_id pause_id,
+                                    enum wmi_tlv_tx_pause_action action);
 
 u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
                             u8 hw_rate);
index ea656e011a96e195d4513e41a482a40bab07df42..5778e5277823c53731ab7dd047f60a19816c7515 100644 (file)
@@ -59,6 +59,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
 
 #define QCA988X_2_0_DEVICE_ID  (0x003c)
 #define QCA6174_2_1_DEVICE_ID  (0x003e)
+#define QCA99X0_2_0_DEVICE_ID  (0x0040)
 
 static const struct pci_device_id ath10k_pci_id_table[] = {
        { PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
@@ -81,7 +82,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
 
 static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
 static int ath10k_pci_cold_reset(struct ath10k *ar);
-static int ath10k_pci_warm_reset(struct ath10k *ar);
+static int ath10k_pci_safe_chip_reset(struct ath10k *ar);
 static int ath10k_pci_wait_for_target_init(struct ath10k *ar);
 static int ath10k_pci_init_irq(struct ath10k *ar);
 static int ath10k_pci_deinit_irq(struct ath10k *ar);
@@ -90,6 +91,7 @@ static void ath10k_pci_free_irq(struct ath10k *ar);
 static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
                               struct ath10k_ce_pipe *rx_pipe,
                               struct bmi_xfer *xfer);
+static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar);
 
 static const struct ce_attr host_ce_config_wlan[] = {
        /* CE0: host->target HTC control and raw streams */
@@ -155,6 +157,38 @@ static const struct ce_attr host_ce_config_wlan[] = {
                .src_sz_max = DIAG_TRANSFER_LIMIT,
                .dest_nentries = 2,
        },
+
+       /* CE8: target->host pktlog */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 2048,
+               .dest_nentries = 128,
+       },
+
+       /* CE9 target autonomous qcache memcpy */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 0,
+               .dest_nentries = 0,
+       },
+
+       /* CE10: target autonomous hif memcpy */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 0,
+               .dest_nentries = 0,
+       },
+
+       /* CE11: target autonomous hif memcpy */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 0,
+               .dest_nentries = 0,
+       },
 };
 
 /* Target firmware's Copy Engine configuration. */
@@ -232,6 +266,38 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
        },
 
        /* CE7 used only by Host */
+       {
+               .pipenum = __cpu_to_le32(7),
+               .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+               .nentries = __cpu_to_le32(0),
+               .nbytes_max = __cpu_to_le32(0),
+               .flags = __cpu_to_le32(0),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE8 target->host packtlog */
+       {
+               .pipenum = __cpu_to_le32(8),
+               .pipedir = __cpu_to_le32(PIPEDIR_IN),
+               .nentries = __cpu_to_le32(64),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE9 target autonomous qcache memcpy */
+       {
+               .pipenum = __cpu_to_le32(9),
+               .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* It not necessary to send target wlan configuration for CE10 & CE11
+        * as these CEs are not actively used in target.
+        */
 };
 
 /*
@@ -479,6 +545,12 @@ void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value)
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret;
 
+       if (unlikely(offset + sizeof(value) > ar_pci->mem_len)) {
+               ath10k_warn(ar, "refusing to write mmio out of bounds at 0x%08x - 0x%08zx (max 0x%08zx)\n",
+                           offset, offset + sizeof(value), ar_pci->mem_len);
+               return;
+       }
+
        ret = ath10k_pci_wake(ar);
        if (ret) {
                ath10k_warn(ar, "failed to wake target for write32 of 0x%08x at 0x%08x: %d\n",
@@ -496,6 +568,12 @@ u32 ath10k_pci_read32(struct ath10k *ar, u32 offset)
        u32 val;
        int ret;
 
+       if (unlikely(offset + sizeof(val) > ar_pci->mem_len)) {
+               ath10k_warn(ar, "refusing to read mmio out of bounds at 0x%08x - 0x%08zx (max 0x%08zx)\n",
+                           offset, offset + sizeof(val), ar_pci->mem_len);
+               return 0;
+       }
+
        ret = ath10k_pci_wake(ar);
        if (ret) {
                ath10k_warn(ar, "failed to wake target for read32 at 0x%08x: %d\n",
@@ -678,6 +756,26 @@ static void ath10k_pci_rx_replenish_retry(unsigned long ptr)
        ath10k_pci_rx_post(ar);
 }
 
+static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
+{
+       u32 val = 0;
+
+       switch (ar->hw_rev) {
+       case ATH10K_HW_QCA988X:
+       case ATH10K_HW_QCA6174:
+               val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                         CORE_CTRL_ADDRESS) &
+                      0x7ff) << 21;
+               break;
+       case ATH10K_HW_QCA99X0:
+               val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
+               break;
+       }
+
+       val |= 0x100000 | (addr & 0xfffff);
+       return val;
+}
+
 /*
  * Diagnostic read/write access is provided for startup/config/debug usage.
  * Caller must guarantee proper alignment, when applicable, and single user
@@ -740,8 +838,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
                 * convert it from Target CPU virtual address space
                 * to CE address space
                 */
-               address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
-                                                    address);
+               address = ath10k_pci_targ_cpu_to_ce_addr(ar, address);
 
                ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
                                            0);
@@ -899,7 +996,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
         * to
         *    CE address space
         */
-       address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, address);
+       address = ath10k_pci_targ_cpu_to_ce_addr(ar, address);
 
        remaining_bytes = orig_nbytes;
        ce_data = ce_data_base;
@@ -1331,20 +1428,42 @@ static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
 {
        u32 val;
 
-       val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
-       val &= ~CORE_CTRL_PCIE_REG_31_MASK;
-
-       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
+       switch (ar->hw_rev) {
+       case ATH10K_HW_QCA988X:
+       case ATH10K_HW_QCA6174:
+               val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                       CORE_CTRL_ADDRESS);
+               val &= ~CORE_CTRL_PCIE_REG_31_MASK;
+               ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+                                  CORE_CTRL_ADDRESS, val);
+               break;
+       case ATH10K_HW_QCA99X0:
+               /* TODO: Find appropriate register configuration for QCA99X0
+                *  to mask irq/MSI.
+                */
+                break;
+       }
 }
 
 static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
 {
        u32 val;
 
-       val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
-       val |= CORE_CTRL_PCIE_REG_31_MASK;
-
-       ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
+       switch (ar->hw_rev) {
+       case ATH10K_HW_QCA988X:
+       case ATH10K_HW_QCA6174:
+               val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+                                       CORE_CTRL_ADDRESS);
+               val |= CORE_CTRL_PCIE_REG_31_MASK;
+               ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+                                  CORE_CTRL_ADDRESS, val);
+               break;
+       case ATH10K_HW_QCA99X0:
+               /* TODO: Find appropriate register configuration for QCA99X0
+                *  to unmask irq/MSI.
+                */
+               break;
+       }
 }
 
 static void ath10k_pci_irq_disable(struct ath10k *ar)
@@ -1506,7 +1625,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
         * masked. To prevent the device from asserting the interrupt reset it
         * before proceeding with cleanup.
         */
-       ath10k_pci_warm_reset(ar);
+       ath10k_pci_safe_chip_reset(ar);
 
        ath10k_pci_irq_disable(ar);
        ath10k_pci_irq_sync(ar);
@@ -1687,6 +1806,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
 
        switch (ar_pci->pdev->device) {
        case QCA988X_2_0_DEVICE_ID:
+       case QCA99X0_2_0_DEVICE_ID:
                return 1;
        case QCA6174_2_1_DEVICE_ID:
                switch (MS(ar->chip_id, SOC_CHIP_ID_REV)) {
@@ -1757,7 +1877,8 @@ static int ath10k_pci_init_config(struct ath10k *ar)
 
        ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr,
                                        target_ce_config_wlan,
-                                       sizeof(target_ce_config_wlan));
+                                       sizeof(struct ce_pipe_config) *
+                                       NUM_TARGET_CE_CONFIG_WLAN);
 
        if (ret != 0) {
                ath10k_err(ar, "Failed to write pipe cfg: %d\n", ret);
@@ -1871,7 +1992,7 @@ static int ath10k_pci_alloc_pipes(struct ath10k *ar)
                }
 
                /* Last CE is Diagnostic Window */
-               if (i == CE_COUNT - 1) {
+               if (i == CE_DIAG_PIPE) {
                        ar_pci->ce_diag = pipe->ce_hdl;
                        continue;
                }
@@ -2016,6 +2137,18 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
        return 0;
 }
 
+static int ath10k_pci_safe_chip_reset(struct ath10k *ar)
+{
+       if (QCA_REV_988X(ar) || QCA_REV_6174(ar)) {
+               return ath10k_pci_warm_reset(ar);
+       } else if (QCA_REV_99X0(ar)) {
+               ath10k_pci_irq_disable(ar);
+               return ath10k_pci_qca99x0_chip_reset(ar);
+       } else {
+               return -ENOTSUPP;
+       }
+}
+
 static int ath10k_pci_qca988x_chip_reset(struct ath10k *ar)
 {
        int i, ret;
@@ -2122,12 +2255,38 @@ static int ath10k_pci_qca6174_chip_reset(struct ath10k *ar)
        return 0;
 }
 
+static int ath10k_pci_qca99x0_chip_reset(struct ath10k *ar)
+{
+       int ret;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca99x0 chip reset\n");
+
+       ret = ath10k_pci_cold_reset(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to cold reset: %d\n", ret);
+               return ret;
+       }
+
+       ret = ath10k_pci_wait_for_target_init(ar);
+       if (ret) {
+               ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
+                           ret);
+               return ret;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot qca99x0 chip reset complete (cold)\n");
+
+       return 0;
+}
+
 static int ath10k_pci_chip_reset(struct ath10k *ar)
 {
        if (QCA_REV_988X(ar))
                return ath10k_pci_qca988x_chip_reset(ar);
        else if (QCA_REV_6174(ar))
                return ath10k_pci_qca6174_chip_reset(ar);
+       else if (QCA_REV_99X0(ar))
+               return ath10k_pci_qca99x0_chip_reset(ar);
        else
                return -ENOTSUPP;
 }
@@ -2679,6 +2838,7 @@ static int ath10k_pci_claim(struct ath10k *ar)
        pci_set_master(pdev);
 
        /* Arrange for access to Target SoC registers. */
+       ar_pci->mem_len = pci_resource_len(pdev, BAR_NUM);
        ar_pci->mem = pci_iomap(pdev, BAR_NUM, 0);
        if (!ar_pci->mem) {
                ath10k_err(ar, "failed to iomap BAR%d\n", BAR_NUM);
@@ -2745,6 +2905,9 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        case QCA6174_2_1_DEVICE_ID:
                hw_rev = ATH10K_HW_QCA6174;
                break;
+       case QCA99X0_2_0_DEVICE_ID:
+               hw_rev = ATH10K_HW_QCA99X0;
+               break;
        default:
                WARN_ON(1);
                return -ENOTSUPP;
index d7696ddc03c42b2b2622913f9c42674f22f84039..8d364fb8f743eb6f8ed488c88d83b8adf25b6536 100644 (file)
@@ -162,6 +162,7 @@ struct ath10k_pci {
        struct device *dev;
        struct ath10k *ar;
        void __iomem *mem;
+       size_t mem_len;
 
        /*
         * Number of MSI interrupts granted, 0 --> using legacy PCI line
@@ -236,18 +237,6 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
 #define CDC_WAR_MAGIC_STR   0xceef0000
 #define CDC_WAR_DATA_CE     4
 
-/*
- * TODO: Should be a function call specific to each Target-type.
- * This convoluted macro converts from Target CPU Virtual Address Space to CE
- * Address Space. As part of this process, we conservatively fetch the current
- * PCIE_BAR. MOST of the time, this should match the upper bits of PCI space
- * for this device; but that's not guaranteed.
- */
-#define TARG_CPU_SPACE_TO_CE_SPACE(ar, pci_addr, addr)                 \
-       (((ath10k_pci_read32(ar, (SOC_CORE_BASE_ADDRESS |               \
-         CORE_CTRL_ADDRESS)) & 0x7ff) << 21) |                         \
-        0x100000 | ((addr) & 0xfffff))
-
 /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
 #define DIAG_ACCESS_CE_TIMEOUT_MS 10
 
diff --git a/drivers/net/wireless/ath/ath10k/swap.c b/drivers/net/wireless/ath/ath10k/swap.c
new file mode 100644 (file)
index 0000000..3ca3fae
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2015 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 has implementation for code swap logic. With code swap feature,
+ * target can run the fw binary with even smaller IRAM size by using host
+ * memory to store some of the code segments.
+ */
+
+#include "core.h"
+#include "bmi.h"
+#include "debug.h"
+
+static int ath10k_swap_code_seg_fill(struct ath10k *ar,
+                                    struct ath10k_swap_code_seg_info *seg_info,
+                                    const void *data, size_t data_len)
+{
+       u8 *virt_addr = seg_info->virt_address[0];
+       u8 swap_magic[ATH10K_SWAP_CODE_SEG_MAGIC_BYTES_SZ] = {};
+       const u8 *fw_data = data;
+       union ath10k_swap_code_seg_item *swap_item;
+       u32 length = 0;
+       u32 payload_len;
+       u32 total_payload_len = 0;
+       u32 size_left = data_len;
+
+       /* Parse swap bin and copy the content to host allocated memory.
+        * The format is Address, length and value. The last 4-bytes is
+        * target write address. Currently address field is not used.
+        */
+       seg_info->target_addr = -1;
+       while (size_left >= sizeof(*swap_item)) {
+               swap_item = (union ath10k_swap_code_seg_item *)fw_data;
+               payload_len = __le32_to_cpu(swap_item->tlv.length);
+               if ((payload_len > size_left) ||
+                   (payload_len == 0 &&
+                    size_left != sizeof(struct ath10k_swap_code_seg_tail))) {
+                       ath10k_err(ar, "refusing to parse invalid tlv length %d\n",
+                                  payload_len);
+                       return -EINVAL;
+               }
+
+               if (payload_len == 0) {
+                       if (memcmp(swap_item->tail.magic_signature, swap_magic,
+                                  ATH10K_SWAP_CODE_SEG_MAGIC_BYTES_SZ)) {
+                               ath10k_err(ar, "refusing an invalid swap file\n");
+                               return -EINVAL;
+                       }
+                       seg_info->target_addr =
+                               __le32_to_cpu(swap_item->tail.bmi_write_addr);
+                       break;
+               }
+
+               memcpy(virt_addr, swap_item->tlv.data, payload_len);
+               virt_addr += payload_len;
+               length = payload_len +  sizeof(struct ath10k_swap_code_seg_tlv);
+               size_left -= length;
+               fw_data += length;
+               total_payload_len += payload_len;
+       }
+
+       if (seg_info->target_addr == -1) {
+               ath10k_err(ar, "failed to parse invalid swap file\n");
+               return -EINVAL;
+       }
+       seg_info->seg_hw_info.swap_size = __cpu_to_le32(total_payload_len);
+
+       return 0;
+}
+
+static void
+ath10k_swap_code_seg_free(struct ath10k *ar,
+                         struct ath10k_swap_code_seg_info *seg_info)
+{
+       u32 seg_size;
+
+       if (!seg_info)
+               return;
+
+       if (!seg_info->virt_address[0])
+               return;
+
+       seg_size = __le32_to_cpu(seg_info->seg_hw_info.size);
+       dma_free_coherent(ar->dev, seg_size, seg_info->virt_address[0],
+                         seg_info->paddr[0]);
+}
+
+static struct ath10k_swap_code_seg_info *
+ath10k_swap_code_seg_alloc(struct ath10k *ar, size_t swap_bin_len)
+{
+       struct ath10k_swap_code_seg_info *seg_info;
+       void *virt_addr;
+       dma_addr_t paddr;
+
+       swap_bin_len = roundup(swap_bin_len, 2);
+       if (swap_bin_len > ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX) {
+               ath10k_err(ar, "refusing code swap bin because it is too big %zu > %d\n",
+                          swap_bin_len, ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX);
+               return NULL;
+       }
+
+       seg_info = devm_kzalloc(ar->dev, sizeof(*seg_info), GFP_KERNEL);
+       if (!seg_info)
+               return NULL;
+
+       virt_addr = dma_alloc_coherent(ar->dev, swap_bin_len, &paddr,
+                                      GFP_KERNEL);
+       if (!virt_addr) {
+               ath10k_err(ar, "failed to allocate dma coherent memory\n");
+               return NULL;
+       }
+
+       seg_info->seg_hw_info.bus_addr[0] = __cpu_to_le32(paddr);
+       seg_info->seg_hw_info.size = __cpu_to_le32(swap_bin_len);
+       seg_info->seg_hw_info.swap_size = __cpu_to_le32(swap_bin_len);
+       seg_info->seg_hw_info.num_segs =
+                       __cpu_to_le32(ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED);
+       seg_info->seg_hw_info.size_log2 = __cpu_to_le32(ilog2(swap_bin_len));
+       seg_info->virt_address[0] = virt_addr;
+       seg_info->paddr[0] = paddr;
+
+       return seg_info;
+}
+
+int ath10k_swap_code_seg_configure(struct ath10k *ar,
+                                  enum ath10k_swap_code_seg_bin_type type)
+{
+       int ret;
+       struct ath10k_swap_code_seg_info *seg_info = NULL;
+
+       switch (type) {
+       case ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW:
+               if (!ar->swap.firmware_swap_code_seg_info)
+                       return 0;
+
+               ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot found firmware code swap binary\n");
+               seg_info = ar->swap.firmware_swap_code_seg_info;
+               break;
+       default:
+       case ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP:
+       case ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF:
+               ath10k_warn(ar, "ignoring unknown code swap binary type %d\n",
+                           type);
+               return 0;
+       }
+
+       ret = ath10k_bmi_write_memory(ar, seg_info->target_addr,
+                                     &seg_info->seg_hw_info,
+                                     sizeof(seg_info->seg_hw_info));
+       if (ret) {
+               ath10k_err(ar, "failed to write Code swap segment information (%d)\n",
+                          ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+void ath10k_swap_code_seg_release(struct ath10k *ar)
+{
+       ath10k_swap_code_seg_free(ar, ar->swap.firmware_swap_code_seg_info);
+       ar->swap.firmware_codeswap_data = NULL;
+       ar->swap.firmware_codeswap_len = 0;
+       ar->swap.firmware_swap_code_seg_info = NULL;
+}
+
+int ath10k_swap_code_seg_init(struct ath10k *ar)
+{
+       int ret;
+       struct ath10k_swap_code_seg_info *seg_info;
+
+       if (!ar->swap.firmware_codeswap_len || !ar->swap.firmware_codeswap_data)
+               return 0;
+
+       seg_info = ath10k_swap_code_seg_alloc(ar,
+                                             ar->swap.firmware_codeswap_len);
+       if (!seg_info) {
+               ath10k_err(ar, "failed to allocate fw code swap segment\n");
+               return -ENOMEM;
+       }
+
+       ret = ath10k_swap_code_seg_fill(ar, seg_info,
+                                       ar->swap.firmware_codeswap_data,
+                                       ar->swap.firmware_codeswap_len);
+
+       if (ret) {
+               ath10k_warn(ar, "failed to initialize fw code swap segment: %d\n",
+                           ret);
+               ath10k_swap_code_seg_free(ar, seg_info);
+               return ret;
+       }
+
+       ar->swap.firmware_swap_code_seg_info = seg_info;
+
+       return 0;
+}
diff --git a/drivers/net/wireless/ath/ath10k/swap.h b/drivers/net/wireless/ath/ath10k/swap.h
new file mode 100644 (file)
index 0000000..5c89952
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+#ifndef _SWAP_H_
+#define _SWAP_H_
+
+#define ATH10K_SWAP_CODE_SEG_BIN_LEN_MAX       (512 * 1024)
+#define ATH10K_SWAP_CODE_SEG_MAGIC_BYTES_SZ    12
+#define ATH10K_SWAP_CODE_SEG_NUM_MAX           16
+/* Currently only one swap segment is supported */
+#define ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED     1
+
+struct ath10k_swap_code_seg_tlv {
+       __le32 address;
+       __le32 length;
+       u8 data[0];
+} __packed;
+
+struct ath10k_swap_code_seg_tail {
+       u8 magic_signature[ATH10K_SWAP_CODE_SEG_MAGIC_BYTES_SZ];
+       __le32 bmi_write_addr;
+} __packed;
+
+union ath10k_swap_code_seg_item {
+       struct ath10k_swap_code_seg_tlv tlv;
+       struct ath10k_swap_code_seg_tail tail;
+} __packed;
+
+enum ath10k_swap_code_seg_bin_type {
+        ATH10K_SWAP_CODE_SEG_BIN_TYPE_OTP,
+        ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW,
+        ATH10K_SWAP_CODE_SEG_BIN_TYPE_UTF,
+};
+
+struct ath10k_swap_code_seg_hw_info {
+       /* Swap binary image size */
+       __le32 swap_size;
+       __le32 num_segs;
+
+       /* Swap data size */
+       __le32 size;
+       __le32 size_log2;
+       __le32 bus_addr[ATH10K_SWAP_CODE_SEG_NUM_MAX];
+       __le64 reserved[ATH10K_SWAP_CODE_SEG_NUM_MAX];
+} __packed;
+
+struct ath10k_swap_code_seg_info {
+       struct ath10k_swap_code_seg_hw_info seg_hw_info;
+       void *virt_address[ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED];
+       u32 target_addr;
+       dma_addr_t paddr[ATH10K_SWAP_CODE_SEG_NUM_SUPPORTED];
+};
+
+int ath10k_swap_code_seg_configure(struct ath10k *ar,
+                                  enum ath10k_swap_code_seg_bin_type type);
+void ath10k_swap_code_seg_release(struct ath10k *ar);
+int ath10k_swap_code_seg_init(struct ath10k *ar);
+
+#endif
index a417aae52623de0e86b951029c0991717eaf39dc..768bef6290995b4e2b4c80c6c3e09e7b3f15893a 100644 (file)
@@ -450,4 +450,7 @@ Fw Mode/SubMode Mask
 #define QCA6174_BOARD_DATA_SZ     8192
 #define QCA6174_BOARD_EXT_DATA_SZ 0
 
+#define QCA99X0_BOARD_DATA_SZ    12288
+#define QCA99X0_BOARD_EXT_DATA_SZ 0
+
 #endif /* __TARGADDRS_H__ */
index 826500bb2b1b247233fbf1998733c2d8c16b3fe7..6cf289158840a3ba01da0f82c81a4e07916a4b70 100644 (file)
@@ -147,9 +147,9 @@ struct ath10k_peer *ath10k_peer_find_by_id(struct ath10k *ar, int peer_id)
 static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id,
                                       const u8 *addr, bool expect_mapped)
 {
-       int ret;
+       long time_left;
 
-       ret = wait_event_timeout(ar->peer_mapping_wq, ({
+       time_left = wait_event_timeout(ar->peer_mapping_wq, ({
                        bool mapped;
 
                        spin_lock_bh(&ar->data_lock);
@@ -160,7 +160,7 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id,
                         test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
                }), 3*HZ);
 
-       if (ret <= 0)
+       if (time_left == 0)
                return -ETIMEDOUT;
 
        return 0;
index 8fdba3865c960e699bacf0998fd911d1e3a231b1..4189d4a90ce0a8e6eeca9a9f2a25a1818fce3548 100644 (file)
@@ -377,12 +377,34 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
                   "wmi tlv tx pause pause_id %u action %u vdev_map 0x%08x peer_id %u tid_map 0x%08x\n",
                   pause_id, action, vdev_map, peer_id, tid_map);
 
-       for (vdev_id = 0; vdev_map; vdev_id++) {
-               if (!(vdev_map & BIT(vdev_id)))
-                       continue;
-
-               vdev_map &= ~BIT(vdev_id);
-               ath10k_mac_handle_tx_pause(ar, vdev_id, pause_id, action);
+       switch (pause_id) {
+       case WMI_TLV_TX_PAUSE_ID_MCC:
+       case WMI_TLV_TX_PAUSE_ID_P2P_CLI_NOA:
+       case WMI_TLV_TX_PAUSE_ID_P2P_GO_PS:
+       case WMI_TLV_TX_PAUSE_ID_AP_PS:
+       case WMI_TLV_TX_PAUSE_ID_IBSS_PS:
+               for (vdev_id = 0; vdev_map; vdev_id++) {
+                       if (!(vdev_map & BIT(vdev_id)))
+                               continue;
+
+                       vdev_map &= ~BIT(vdev_id);
+                       ath10k_mac_handle_tx_pause_vdev(ar, vdev_id, pause_id,
+                                                       action);
+               }
+               break;
+       case WMI_TLV_TX_PAUSE_ID_AP_PEER_PS:
+       case WMI_TLV_TX_PAUSE_ID_AP_PEER_UAPSD:
+       case WMI_TLV_TX_PAUSE_ID_STA_ADD_BA:
+       case WMI_TLV_TX_PAUSE_ID_HOST:
+               ath10k_dbg(ar, ATH10K_DBG_MAC,
+                          "mac ignoring unsupported tx pause id %d\n",
+                          pause_id);
+               break;
+       default:
+               ath10k_dbg(ar, ATH10K_DBG_MAC,
+                          "mac ignoring unknown tx pause vdev %d\n",
+                          pause_id);
+               break;
        }
 
        kfree(tb);
@@ -709,6 +731,8 @@ static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
                                         const void *ptr, void *data)
 {
        struct wmi_tlv_swba_parse *swba = data;
+       struct wmi_tim_info_arg *tim_info_arg;
+       const struct wmi_tim_info *tim_info_ev = ptr;
 
        if (tag != WMI_TLV_TAG_STRUCT_TIM_INFO)
                return -EPROTO;
@@ -716,7 +740,21 @@ static int ath10k_wmi_tlv_swba_tim_parse(struct ath10k *ar, u16 tag, u16 len,
        if (swba->n_tim >= ARRAY_SIZE(swba->arg->tim_info))
                return -ENOBUFS;
 
-       swba->arg->tim_info[swba->n_tim++] = ptr;
+       if (__le32_to_cpu(tim_info_ev->tim_len) >
+            sizeof(tim_info_ev->tim_bitmap)) {
+               ath10k_warn(ar, "refusing to parse invalid swba structure\n");
+               return -EPROTO;
+       }
+
+       tim_info_arg = &swba->arg->tim_info[swba->n_tim];
+       tim_info_arg->tim_len = tim_info_ev->tim_len;
+       tim_info_arg->tim_mcast = tim_info_ev->tim_mcast;
+       tim_info_arg->tim_bitmap = tim_info_ev->tim_bitmap;
+       tim_info_arg->tim_changed = tim_info_ev->tim_changed;
+       tim_info_arg->tim_num_ps_pending = tim_info_ev->tim_num_ps_pending;
+
+       swba->n_tim++;
+
        return 0;
 }
 
@@ -3151,6 +3189,38 @@ static struct wmi_cmd_map wmi_tlv_cmd_map = {
        .tdls_set_state_cmdid = WMI_TLV_TDLS_SET_STATE_CMDID,
        .tdls_peer_update_cmdid = WMI_TLV_TDLS_PEER_UPDATE_CMDID,
        .adaptive_qcs_cmdid = WMI_TLV_RESMGR_ADAPTIVE_OCS_CMDID,
+       .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+       .oem_req_cmdid = WMI_CMD_UNSUPPORTED,
+       .nan_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
+       .qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
+       .tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
+       .fwtest_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
 };
 
 static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
@@ -3204,6 +3274,48 @@ static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
        .burst_dur = WMI_TLV_PDEV_PARAM_BURST_DUR,
        .burst_enable = WMI_TLV_PDEV_PARAM_BURST_ENABLE,
        .cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
+       .aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
+       .ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
+       .sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
+       .pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
 };
 
 static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
@@ -3262,6 +3374,22 @@ static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
        .tx_encap_type = WMI_TLV_VDEV_PARAM_TX_ENCAP_TYPE,
        .ap_detect_out_of_sync_sleeping_sta_time_secs =
                                        WMI_TLV_VDEV_PARAM_UNSUPPORTED,
+       .rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
+       .cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
+       .mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
+       .proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
+       .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
+       .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
 };
 
 static const struct wmi_ops wmi_tlv_ops = {
index 6c046c244705fe69f23fa9207113c6cefec9a78e..0791a4336e80f4b4886b62ef89eb892bb73342ce 100644 (file)
@@ -148,6 +148,48 @@ static struct wmi_cmd_map wmi_cmd_map = {
        .gpio_config_cmdid = WMI_GPIO_CONFIG_CMDID,
        .gpio_output_cmdid = WMI_GPIO_OUTPUT_CMDID,
        .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
+       .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+       .oem_req_cmdid = WMI_CMD_UNSUPPORTED,
+       .nan_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
+       .qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
+       .tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
+       .fwtest_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_nfcal_power_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_tpc_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ast_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_set_dscp_tid_map_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_get_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_filter_neighbor_rx_packets_cmdid = WMI_CMD_UNSUPPORTED,
+       .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
+       .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
 };
 
 /* 10.X WMI cmd track */
@@ -271,6 +313,48 @@ static struct wmi_cmd_map wmi_10x_cmd_map = {
        .gpio_config_cmdid = WMI_10X_GPIO_CONFIG_CMDID,
        .gpio_output_cmdid = WMI_10X_GPIO_OUTPUT_CMDID,
        .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
+       .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+       .oem_req_cmdid = WMI_CMD_UNSUPPORTED,
+       .nan_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
+       .qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
+       .tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
+       .fwtest_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_nfcal_power_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_tpc_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ast_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_set_dscp_tid_map_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_get_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_filter_neighbor_rx_packets_cmdid = WMI_CMD_UNSUPPORTED,
+       .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
+       .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
 };
 
 /* 10.2.4 WMI cmd track */
@@ -393,6 +477,231 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = {
        .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
        .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
        .pdev_get_temperature_cmdid = WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
+       .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+       .oem_req_cmdid = WMI_CMD_UNSUPPORTED,
+       .nan_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
+       .qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
+       .tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
+       .fwtest_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_nfcal_power_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_tpc_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ast_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_set_dscp_tid_map_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_get_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_filter_neighbor_rx_packets_cmdid = WMI_CMD_UNSUPPORTED,
+       .mu_cal_start_cmdid = WMI_CMD_UNSUPPORTED,
+       .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED,
+};
+
+/* 10.4 WMI cmd track */
+static struct wmi_cmd_map wmi_10_4_cmd_map = {
+       .init_cmdid = WMI_10_4_INIT_CMDID,
+       .start_scan_cmdid = WMI_10_4_START_SCAN_CMDID,
+       .stop_scan_cmdid = WMI_10_4_STOP_SCAN_CMDID,
+       .scan_chan_list_cmdid = WMI_10_4_SCAN_CHAN_LIST_CMDID,
+       .scan_sch_prio_tbl_cmdid = WMI_10_4_SCAN_SCH_PRIO_TBL_CMDID,
+       .pdev_set_regdomain_cmdid = WMI_10_4_PDEV_SET_REGDOMAIN_CMDID,
+       .pdev_set_channel_cmdid = WMI_10_4_PDEV_SET_CHANNEL_CMDID,
+       .pdev_set_param_cmdid = WMI_10_4_PDEV_SET_PARAM_CMDID,
+       .pdev_pktlog_enable_cmdid = WMI_10_4_PDEV_PKTLOG_ENABLE_CMDID,
+       .pdev_pktlog_disable_cmdid = WMI_10_4_PDEV_PKTLOG_DISABLE_CMDID,
+       .pdev_set_wmm_params_cmdid = WMI_10_4_PDEV_SET_WMM_PARAMS_CMDID,
+       .pdev_set_ht_cap_ie_cmdid = WMI_10_4_PDEV_SET_HT_CAP_IE_CMDID,
+       .pdev_set_vht_cap_ie_cmdid = WMI_10_4_PDEV_SET_VHT_CAP_IE_CMDID,
+       .pdev_set_dscp_tid_map_cmdid = WMI_10_4_PDEV_SET_DSCP_TID_MAP_CMDID,
+       .pdev_set_quiet_mode_cmdid = WMI_10_4_PDEV_SET_QUIET_MODE_CMDID,
+       .pdev_green_ap_ps_enable_cmdid = WMI_10_4_PDEV_GREEN_AP_PS_ENABLE_CMDID,
+       .pdev_get_tpc_config_cmdid = WMI_10_4_PDEV_GET_TPC_CONFIG_CMDID,
+       .pdev_set_base_macaddr_cmdid = WMI_10_4_PDEV_SET_BASE_MACADDR_CMDID,
+       .vdev_create_cmdid = WMI_10_4_VDEV_CREATE_CMDID,
+       .vdev_delete_cmdid = WMI_10_4_VDEV_DELETE_CMDID,
+       .vdev_start_request_cmdid = WMI_10_4_VDEV_START_REQUEST_CMDID,
+       .vdev_restart_request_cmdid = WMI_10_4_VDEV_RESTART_REQUEST_CMDID,
+       .vdev_up_cmdid = WMI_10_4_VDEV_UP_CMDID,
+       .vdev_stop_cmdid = WMI_10_4_VDEV_STOP_CMDID,
+       .vdev_down_cmdid = WMI_10_4_VDEV_DOWN_CMDID,
+       .vdev_set_param_cmdid = WMI_10_4_VDEV_SET_PARAM_CMDID,
+       .vdev_install_key_cmdid = WMI_10_4_VDEV_INSTALL_KEY_CMDID,
+       .peer_create_cmdid = WMI_10_4_PEER_CREATE_CMDID,
+       .peer_delete_cmdid = WMI_10_4_PEER_DELETE_CMDID,
+       .peer_flush_tids_cmdid = WMI_10_4_PEER_FLUSH_TIDS_CMDID,
+       .peer_set_param_cmdid = WMI_10_4_PEER_SET_PARAM_CMDID,
+       .peer_assoc_cmdid = WMI_10_4_PEER_ASSOC_CMDID,
+       .peer_add_wds_entry_cmdid = WMI_10_4_PEER_ADD_WDS_ENTRY_CMDID,
+       .peer_remove_wds_entry_cmdid = WMI_10_4_PEER_REMOVE_WDS_ENTRY_CMDID,
+       .peer_mcast_group_cmdid = WMI_10_4_PEER_MCAST_GROUP_CMDID,
+       .bcn_tx_cmdid = WMI_10_4_BCN_TX_CMDID,
+       .pdev_send_bcn_cmdid = WMI_10_4_PDEV_SEND_BCN_CMDID,
+       .bcn_tmpl_cmdid = WMI_10_4_BCN_PRB_TMPL_CMDID,
+       .bcn_filter_rx_cmdid = WMI_10_4_BCN_FILTER_RX_CMDID,
+       .prb_req_filter_rx_cmdid = WMI_10_4_PRB_REQ_FILTER_RX_CMDID,
+       .mgmt_tx_cmdid = WMI_10_4_MGMT_TX_CMDID,
+       .prb_tmpl_cmdid = WMI_10_4_PRB_TMPL_CMDID,
+       .addba_clear_resp_cmdid = WMI_10_4_ADDBA_CLEAR_RESP_CMDID,
+       .addba_send_cmdid = WMI_10_4_ADDBA_SEND_CMDID,
+       .addba_status_cmdid = WMI_10_4_ADDBA_STATUS_CMDID,
+       .delba_send_cmdid = WMI_10_4_DELBA_SEND_CMDID,
+       .addba_set_resp_cmdid = WMI_10_4_ADDBA_SET_RESP_CMDID,
+       .send_singleamsdu_cmdid = WMI_10_4_SEND_SINGLEAMSDU_CMDID,
+       .sta_powersave_mode_cmdid = WMI_10_4_STA_POWERSAVE_MODE_CMDID,
+       .sta_powersave_param_cmdid = WMI_10_4_STA_POWERSAVE_PARAM_CMDID,
+       .sta_mimo_ps_mode_cmdid = WMI_10_4_STA_MIMO_PS_MODE_CMDID,
+       .pdev_dfs_enable_cmdid = WMI_10_4_PDEV_DFS_ENABLE_CMDID,
+       .pdev_dfs_disable_cmdid = WMI_10_4_PDEV_DFS_DISABLE_CMDID,
+       .roam_scan_mode = WMI_10_4_ROAM_SCAN_MODE,
+       .roam_scan_rssi_threshold = WMI_10_4_ROAM_SCAN_RSSI_THRESHOLD,
+       .roam_scan_period = WMI_10_4_ROAM_SCAN_PERIOD,
+       .roam_scan_rssi_change_threshold =
+                               WMI_10_4_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
+       .roam_ap_profile = WMI_10_4_ROAM_AP_PROFILE,
+       .ofl_scan_add_ap_profile = WMI_10_4_OFL_SCAN_ADD_AP_PROFILE,
+       .ofl_scan_remove_ap_profile = WMI_10_4_OFL_SCAN_REMOVE_AP_PROFILE,
+       .ofl_scan_period = WMI_10_4_OFL_SCAN_PERIOD,
+       .p2p_dev_set_device_info = WMI_10_4_P2P_DEV_SET_DEVICE_INFO,
+       .p2p_dev_set_discoverability = WMI_10_4_P2P_DEV_SET_DISCOVERABILITY,
+       .p2p_go_set_beacon_ie = WMI_10_4_P2P_GO_SET_BEACON_IE,
+       .p2p_go_set_probe_resp_ie = WMI_10_4_P2P_GO_SET_PROBE_RESP_IE,
+       .p2p_set_vendor_ie_data_cmdid = WMI_10_4_P2P_SET_VENDOR_IE_DATA_CMDID,
+       .ap_ps_peer_param_cmdid = WMI_10_4_AP_PS_PEER_PARAM_CMDID,
+       .ap_ps_peer_uapsd_coex_cmdid = WMI_10_4_AP_PS_PEER_UAPSD_COEX_CMDID,
+       .peer_rate_retry_sched_cmdid = WMI_10_4_PEER_RATE_RETRY_SCHED_CMDID,
+       .wlan_profile_trigger_cmdid = WMI_10_4_WLAN_PROFILE_TRIGGER_CMDID,
+       .wlan_profile_set_hist_intvl_cmdid =
+                               WMI_10_4_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
+       .wlan_profile_get_profile_data_cmdid =
+                               WMI_10_4_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
+       .wlan_profile_enable_profile_id_cmdid =
+                               WMI_10_4_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
+       .wlan_profile_list_profile_id_cmdid =
+                               WMI_10_4_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
+       .pdev_suspend_cmdid = WMI_10_4_PDEV_SUSPEND_CMDID,
+       .pdev_resume_cmdid = WMI_10_4_PDEV_RESUME_CMDID,
+       .add_bcn_filter_cmdid = WMI_10_4_ADD_BCN_FILTER_CMDID,
+       .rmv_bcn_filter_cmdid = WMI_10_4_RMV_BCN_FILTER_CMDID,
+       .wow_add_wake_pattern_cmdid = WMI_10_4_WOW_ADD_WAKE_PATTERN_CMDID,
+       .wow_del_wake_pattern_cmdid = WMI_10_4_WOW_DEL_WAKE_PATTERN_CMDID,
+       .wow_enable_disable_wake_event_cmdid =
+                               WMI_10_4_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
+       .wow_enable_cmdid = WMI_10_4_WOW_ENABLE_CMDID,
+       .wow_hostwakeup_from_sleep_cmdid =
+                               WMI_10_4_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
+       .rtt_measreq_cmdid = WMI_10_4_RTT_MEASREQ_CMDID,
+       .rtt_tsf_cmdid = WMI_10_4_RTT_TSF_CMDID,
+       .vdev_spectral_scan_configure_cmdid =
+                               WMI_10_4_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
+       .vdev_spectral_scan_enable_cmdid =
+                               WMI_10_4_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
+       .request_stats_cmdid = WMI_10_4_REQUEST_STATS_CMDID,
+       .set_arp_ns_offload_cmdid = WMI_CMD_UNSUPPORTED,
+       .network_list_offload_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .gtk_offload_cmdid = WMI_10_4_GTK_OFFLOAD_CMDID,
+       .csa_offload_enable_cmdid = WMI_10_4_CSA_OFFLOAD_ENABLE_CMDID,
+       .csa_offload_chanswitch_cmdid = WMI_10_4_CSA_OFFLOAD_CHANSWITCH_CMDID,
+       .chatter_set_mode_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_tid_addba_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_tid_delba_cmdid = WMI_CMD_UNSUPPORTED,
+       .sta_dtim_ps_method_cmdid = WMI_CMD_UNSUPPORTED,
+       .sta_uapsd_auto_trig_cmdid = WMI_CMD_UNSUPPORTED,
+       .sta_keepalive_cmd = WMI_CMD_UNSUPPORTED,
+       .echo_cmdid = WMI_10_4_ECHO_CMDID,
+       .pdev_utf_cmdid = WMI_10_4_PDEV_UTF_CMDID,
+       .dbglog_cfg_cmdid = WMI_10_4_DBGLOG_CFG_CMDID,
+       .pdev_qvit_cmdid = WMI_10_4_PDEV_QVIT_CMDID,
+       .pdev_ftm_intg_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_set_keepalive_cmdid = WMI_10_4_VDEV_SET_KEEPALIVE_CMDID,
+       .vdev_get_keepalive_cmdid = WMI_10_4_VDEV_GET_KEEPALIVE_CMDID,
+       .force_fw_hang_cmdid = WMI_10_4_FORCE_FW_HANG_CMDID,
+       .gpio_config_cmdid = WMI_10_4_GPIO_CONFIG_CMDID,
+       .gpio_output_cmdid = WMI_10_4_GPIO_OUTPUT_CMDID,
+       .pdev_get_temperature_cmdid = WMI_10_4_PDEV_GET_TEMPERATURE_CMDID,
+       .vdev_set_wmm_params_cmdid = WMI_CMD_UNSUPPORTED,
+       .tdls_set_state_cmdid = WMI_CMD_UNSUPPORTED,
+       .tdls_peer_update_cmdid = WMI_CMD_UNSUPPORTED,
+       .adaptive_qcs_cmdid = WMI_CMD_UNSUPPORTED,
+       .scan_update_request_cmdid = WMI_10_4_SCAN_UPDATE_REQUEST_CMDID,
+       .vdev_standby_response_cmdid = WMI_10_4_VDEV_STANDBY_RESPONSE_CMDID,
+       .vdev_resume_response_cmdid = WMI_10_4_VDEV_RESUME_RESPONSE_CMDID,
+       .wlan_peer_caching_add_peer_cmdid =
+                       WMI_10_4_WLAN_PEER_CACHING_ADD_PEER_CMDID,
+       .wlan_peer_caching_evict_peer_cmdid =
+                       WMI_10_4_WLAN_PEER_CACHING_EVICT_PEER_CMDID,
+       .wlan_peer_caching_restore_peer_cmdid =
+                       WMI_10_4_WLAN_PEER_CACHING_RESTORE_PEER_CMDID,
+       .wlan_peer_caching_print_all_peers_info_cmdid =
+                       WMI_10_4_WLAN_PEER_CACHING_PRINT_ALL_PEERS_INFO_CMDID,
+       .peer_update_wds_entry_cmdid = WMI_10_4_PEER_UPDATE_WDS_ENTRY_CMDID,
+       .peer_add_proxy_sta_entry_cmdid =
+                       WMI_10_4_PEER_ADD_PROXY_STA_ENTRY_CMDID,
+       .rtt_keepalive_cmdid = WMI_10_4_RTT_KEEPALIVE_CMDID,
+       .oem_req_cmdid = WMI_10_4_OEM_REQ_CMDID,
+       .nan_cmdid = WMI_10_4_NAN_CMDID,
+       .vdev_ratemask_cmdid = WMI_10_4_VDEV_RATEMASK_CMDID,
+       .qboost_cfg_cmdid = WMI_10_4_QBOOST_CFG_CMDID,
+       .pdev_smart_ant_enable_cmdid = WMI_10_4_PDEV_SMART_ANT_ENABLE_CMDID,
+       .pdev_smart_ant_set_rx_antenna_cmdid =
+                       WMI_10_4_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID,
+       .peer_smart_ant_set_tx_antenna_cmdid =
+                       WMI_10_4_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID,
+       .peer_smart_ant_set_train_info_cmdid =
+                       WMI_10_4_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID,
+       .peer_smart_ant_set_node_config_ops_cmdid =
+                       WMI_10_4_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID,
+       .pdev_set_antenna_switch_table_cmdid =
+                       WMI_10_4_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID,
+       .pdev_set_ctl_table_cmdid = WMI_10_4_PDEV_SET_CTL_TABLE_CMDID,
+       .pdev_set_mimogain_table_cmdid = WMI_10_4_PDEV_SET_MIMOGAIN_TABLE_CMDID,
+       .pdev_ratepwr_table_cmdid = WMI_10_4_PDEV_RATEPWR_TABLE_CMDID,
+       .pdev_ratepwr_chainmsk_table_cmdid =
+                       WMI_10_4_PDEV_RATEPWR_CHAINMSK_TABLE_CMDID,
+       .pdev_fips_cmdid = WMI_10_4_PDEV_FIPS_CMDID,
+       .tt_set_conf_cmdid = WMI_10_4_TT_SET_CONF_CMDID,
+       .fwtest_cmdid = WMI_10_4_FWTEST_CMDID,
+       .vdev_atf_request_cmdid = WMI_10_4_VDEV_ATF_REQUEST_CMDID,
+       .peer_atf_request_cmdid = WMI_10_4_PEER_ATF_REQUEST_CMDID,
+       .pdev_get_ani_cck_config_cmdid = WMI_10_4_PDEV_GET_ANI_CCK_CONFIG_CMDID,
+       .pdev_get_ani_ofdm_config_cmdid =
+                       WMI_10_4_PDEV_GET_ANI_OFDM_CONFIG_CMDID,
+       .pdev_reserve_ast_entry_cmdid = WMI_10_4_PDEV_RESERVE_AST_ENTRY_CMDID,
+       .pdev_get_nfcal_power_cmdid = WMI_10_4_PDEV_GET_NFCAL_POWER_CMDID,
+       .pdev_get_tpc_cmdid = WMI_10_4_PDEV_GET_TPC_CMDID,
+       .pdev_get_ast_info_cmdid = WMI_10_4_PDEV_GET_AST_INFO_CMDID,
+       .vdev_set_dscp_tid_map_cmdid = WMI_10_4_VDEV_SET_DSCP_TID_MAP_CMDID,
+       .pdev_get_info_cmdid = WMI_10_4_PDEV_GET_INFO_CMDID,
+       .vdev_get_info_cmdid = WMI_10_4_VDEV_GET_INFO_CMDID,
+       .vdev_filter_neighbor_rx_packets_cmdid =
+                       WMI_10_4_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID,
+       .mu_cal_start_cmdid = WMI_10_4_MU_CAL_START_CMDID,
+       .set_cca_params_cmdid = WMI_10_4_SET_CCA_PARAMS_CMDID,
+       .pdev_bss_chan_info_request_cmdid =
+                       WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
 };
 
 /* MAIN WMI VDEV param map */
@@ -452,6 +761,22 @@ static struct wmi_vdev_param_map wmi_vdev_param_map = {
        .tx_encap_type = WMI_VDEV_PARAM_TX_ENCAP_TYPE,
        .ap_detect_out_of_sync_sleeping_sta_time_secs =
                                        WMI_VDEV_PARAM_UNSUPPORTED,
+       .rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
+       .cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
+       .mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
+       .proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
+       .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
+       .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
 };
 
 /* 10.X WMI VDEV param map */
@@ -511,6 +836,22 @@ static struct wmi_vdev_param_map wmi_10x_vdev_param_map = {
        .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED,
        .ap_detect_out_of_sync_sleeping_sta_time_secs =
                WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
+       .rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
+       .cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
+       .mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
+       .proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
+       .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
+       .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
 };
 
 static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
@@ -569,6 +910,97 @@ static struct wmi_vdev_param_map wmi_10_2_4_vdev_param_map = {
        .tx_encap_type = WMI_VDEV_PARAM_UNSUPPORTED,
        .ap_detect_out_of_sync_sleeping_sta_time_secs =
                WMI_10X_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
+       .rc_num_retries = WMI_VDEV_PARAM_UNSUPPORTED,
+       .cabq_maxdur = WMI_VDEV_PARAM_UNSUPPORTED,
+       .mfptest_set = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht_sgimask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .vht80_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_enable = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_tgt_bmiss_num = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_bmiss_sample_cycle = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_slop_step = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_init_slop = WMI_VDEV_PARAM_UNSUPPORTED,
+       .early_rx_adjust_pause = WMI_VDEV_PARAM_UNSUPPORTED,
+       .proxy_sta = WMI_VDEV_PARAM_UNSUPPORTED,
+       .meru_vc = WMI_VDEV_PARAM_UNSUPPORTED,
+       .rx_decap_type = WMI_VDEV_PARAM_UNSUPPORTED,
+       .bw_nss_ratemask = WMI_VDEV_PARAM_UNSUPPORTED,
+};
+
+static struct wmi_vdev_param_map wmi_10_4_vdev_param_map = {
+       .rts_threshold = WMI_10_4_VDEV_PARAM_RTS_THRESHOLD,
+       .fragmentation_threshold = WMI_10_4_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
+       .beacon_interval = WMI_10_4_VDEV_PARAM_BEACON_INTERVAL,
+       .listen_interval = WMI_10_4_VDEV_PARAM_LISTEN_INTERVAL,
+       .multicast_rate = WMI_10_4_VDEV_PARAM_MULTICAST_RATE,
+       .mgmt_tx_rate = WMI_10_4_VDEV_PARAM_MGMT_TX_RATE,
+       .slot_time = WMI_10_4_VDEV_PARAM_SLOT_TIME,
+       .preamble = WMI_10_4_VDEV_PARAM_PREAMBLE,
+       .swba_time = WMI_10_4_VDEV_PARAM_SWBA_TIME,
+       .wmi_vdev_stats_update_period = WMI_10_4_VDEV_STATS_UPDATE_PERIOD,
+       .wmi_vdev_pwrsave_ageout_time = WMI_10_4_VDEV_PWRSAVE_AGEOUT_TIME,
+       .wmi_vdev_host_swba_interval = WMI_10_4_VDEV_HOST_SWBA_INTERVAL,
+       .dtim_period = WMI_10_4_VDEV_PARAM_DTIM_PERIOD,
+       .wmi_vdev_oc_scheduler_air_time_limit =
+              WMI_10_4_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
+       .wds = WMI_10_4_VDEV_PARAM_WDS,
+       .atim_window = WMI_10_4_VDEV_PARAM_ATIM_WINDOW,
+       .bmiss_count_max = WMI_10_4_VDEV_PARAM_BMISS_COUNT_MAX,
+       .bmiss_first_bcnt = WMI_10_4_VDEV_PARAM_BMISS_FIRST_BCNT,
+       .bmiss_final_bcnt = WMI_10_4_VDEV_PARAM_BMISS_FINAL_BCNT,
+       .feature_wmm = WMI_10_4_VDEV_PARAM_FEATURE_WMM,
+       .chwidth = WMI_10_4_VDEV_PARAM_CHWIDTH,
+       .chextoffset = WMI_10_4_VDEV_PARAM_CHEXTOFFSET,
+       .disable_htprotection = WMI_10_4_VDEV_PARAM_DISABLE_HTPROTECTION,
+       .sta_quickkickout = WMI_10_4_VDEV_PARAM_STA_QUICKKICKOUT,
+       .mgmt_rate = WMI_10_4_VDEV_PARAM_MGMT_RATE,
+       .protection_mode = WMI_10_4_VDEV_PARAM_PROTECTION_MODE,
+       .fixed_rate = WMI_10_4_VDEV_PARAM_FIXED_RATE,
+       .sgi = WMI_10_4_VDEV_PARAM_SGI,
+       .ldpc = WMI_10_4_VDEV_PARAM_LDPC,
+       .tx_stbc = WMI_10_4_VDEV_PARAM_TX_STBC,
+       .rx_stbc = WMI_10_4_VDEV_PARAM_RX_STBC,
+       .intra_bss_fwd = WMI_10_4_VDEV_PARAM_INTRA_BSS_FWD,
+       .def_keyid = WMI_10_4_VDEV_PARAM_DEF_KEYID,
+       .nss = WMI_10_4_VDEV_PARAM_NSS,
+       .bcast_data_rate = WMI_10_4_VDEV_PARAM_BCAST_DATA_RATE,
+       .mcast_data_rate = WMI_10_4_VDEV_PARAM_MCAST_DATA_RATE,
+       .mcast_indicate = WMI_10_4_VDEV_PARAM_MCAST_INDICATE,
+       .dhcp_indicate = WMI_10_4_VDEV_PARAM_DHCP_INDICATE,
+       .unknown_dest_indicate = WMI_10_4_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
+       .ap_keepalive_min_idle_inactive_time_secs =
+              WMI_10_4_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
+       .ap_keepalive_max_idle_inactive_time_secs =
+              WMI_10_4_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
+       .ap_keepalive_max_unresponsive_time_secs =
+              WMI_10_4_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
+       .ap_enable_nawds = WMI_10_4_VDEV_PARAM_AP_ENABLE_NAWDS,
+       .mcast2ucast_set = WMI_10_4_VDEV_PARAM_MCAST2UCAST_SET,
+       .enable_rtscts = WMI_10_4_VDEV_PARAM_ENABLE_RTSCTS,
+       .txbf = WMI_10_4_VDEV_PARAM_TXBF,
+       .packet_powersave = WMI_10_4_VDEV_PARAM_PACKET_POWERSAVE,
+       .drop_unencry = WMI_10_4_VDEV_PARAM_DROP_UNENCRY,
+       .tx_encap_type = WMI_10_4_VDEV_PARAM_TX_ENCAP_TYPE,
+       .ap_detect_out_of_sync_sleeping_sta_time_secs =
+              WMI_10_4_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
+       .rc_num_retries = WMI_10_4_VDEV_PARAM_RC_NUM_RETRIES,
+       .cabq_maxdur = WMI_10_4_VDEV_PARAM_CABQ_MAXDUR,
+       .mfptest_set = WMI_10_4_VDEV_PARAM_MFPTEST_SET,
+       .rts_fixed_rate = WMI_10_4_VDEV_PARAM_RTS_FIXED_RATE,
+       .vht_sgimask = WMI_10_4_VDEV_PARAM_VHT_SGIMASK,
+       .vht80_ratemask = WMI_10_4_VDEV_PARAM_VHT80_RATEMASK,
+       .early_rx_adjust_enable = WMI_10_4_VDEV_PARAM_EARLY_RX_ADJUST_ENABLE,
+       .early_rx_tgt_bmiss_num = WMI_10_4_VDEV_PARAM_EARLY_RX_TGT_BMISS_NUM,
+       .early_rx_bmiss_sample_cycle =
+              WMI_10_4_VDEV_PARAM_EARLY_RX_BMISS_SAMPLE_CYCLE,
+       .early_rx_slop_step = WMI_10_4_VDEV_PARAM_EARLY_RX_SLOP_STEP,
+       .early_rx_init_slop = WMI_10_4_VDEV_PARAM_EARLY_RX_INIT_SLOP,
+       .early_rx_adjust_pause = WMI_10_4_VDEV_PARAM_EARLY_RX_ADJUST_PAUSE,
+       .proxy_sta = WMI_10_4_VDEV_PARAM_PROXY_STA,
+       .meru_vc = WMI_10_4_VDEV_PARAM_MERU_VC,
+       .rx_decap_type = WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE,
+       .bw_nss_ratemask = WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK,
 };
 
 static struct wmi_pdev_param_map wmi_pdev_param_map = {
@@ -621,6 +1053,48 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
        .burst_dur = WMI_PDEV_PARAM_UNSUPPORTED,
        .burst_enable = WMI_PDEV_PARAM_UNSUPPORTED,
        .cal_period = WMI_PDEV_PARAM_UNSUPPORTED,
+       .aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
+       .ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
+       .sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
+       .pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
 };
 
 static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
@@ -674,6 +1148,48 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
        .burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR,
        .burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
        .cal_period = WMI_10X_PDEV_PARAM_CAL_PERIOD,
+       .aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
+       .ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
+       .sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
+       .pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
 };
 
 static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
@@ -727,6 +1243,48 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
        .burst_dur = WMI_10X_PDEV_PARAM_BURST_DUR,
        .burst_enable = WMI_10X_PDEV_PARAM_BURST_ENABLE,
        .cal_period = WMI_10X_PDEV_PARAM_CAL_PERIOD,
+       .aggr_burst = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_decap_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .smart_antenna_default_antenna = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .antenna_gain = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rx_filter = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_to_ucast_tid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .proxy_sta_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_mode = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .remove_mcast2ucast_buffer = WMI_PDEV_PARAM_UNSUPPORTED,
+       .peer_sta_ps_statechg_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .igmpmld_ac_override = WMI_PDEV_PARAM_UNSUPPORTED,
+       .block_interbss = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_disable_reset_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_msdu_ttl_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_ppdu_duration_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .txbf_sound_period_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_promisc_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_burst_mode_cmdid = WMI_PDEV_PARAM_UNSUPPORTED,
+       .en_stats = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mu_group_policy = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_detection = WMI_PDEV_PARAM_UNSUPPORTED,
+       .noise_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .dpd_enable = WMI_PDEV_PARAM_UNSUPPORTED,
+       .set_mcast_bcast_echo = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_strict_sch = WMI_PDEV_PARAM_UNSUPPORTED,
+       .atf_sched_duration = WMI_PDEV_PARAM_UNSUPPORTED,
+       .ant_plzn = WMI_PDEV_PARAM_UNSUPPORTED,
+       .mgmt_retry_limit = WMI_PDEV_PARAM_UNSUPPORTED,
+       .sensitivity_level = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_2g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .signed_txpower_5g = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_amsdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .enable_per_tid_ampdu = WMI_PDEV_PARAM_UNSUPPORTED,
+       .cca_threshold = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rts_fixed_rate = WMI_PDEV_PARAM_UNSUPPORTED,
+       .pdev_reset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+       .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
 };
 
 /* firmware 10.2 specific mappings */
@@ -849,6 +1407,139 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
        .gpio_config_cmdid = WMI_10_2_GPIO_CONFIG_CMDID,
        .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
        .pdev_get_temperature_cmdid = WMI_CMD_UNSUPPORTED,
+       .scan_update_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_standby_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_resume_response_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_add_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_evict_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_restore_peer_cmdid = WMI_CMD_UNSUPPORTED,
+       .wlan_peer_caching_print_all_peers_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_update_wds_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_add_proxy_sta_entry_cmdid = WMI_CMD_UNSUPPORTED,
+       .rtt_keepalive_cmdid = WMI_CMD_UNSUPPORTED,
+       .oem_req_cmdid = WMI_CMD_UNSUPPORTED,
+       .nan_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_ratemask_cmdid = WMI_CMD_UNSUPPORTED,
+       .qboost_cfg_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_enable_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_smart_ant_set_rx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_tx_antenna_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_train_info_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_smart_ant_set_node_config_ops_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_antenna_switch_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_ctl_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_set_mimogain_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_ratepwr_chainmsk_table_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_fips_cmdid = WMI_CMD_UNSUPPORTED,
+       .tt_set_conf_cmdid = WMI_CMD_UNSUPPORTED,
+       .fwtest_cmdid = WMI_CMD_UNSUPPORTED,
+       .vdev_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .peer_atf_request_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_cck_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED,
+       .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED,
+};
+
+static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+       .tx_chain_mask = WMI_10_4_PDEV_PARAM_TX_CHAIN_MASK,
+       .rx_chain_mask = WMI_10_4_PDEV_PARAM_RX_CHAIN_MASK,
+       .txpower_limit2g = WMI_10_4_PDEV_PARAM_TXPOWER_LIMIT2G,
+       .txpower_limit5g = WMI_10_4_PDEV_PARAM_TXPOWER_LIMIT5G,
+       .txpower_scale = WMI_10_4_PDEV_PARAM_TXPOWER_SCALE,
+       .beacon_gen_mode = WMI_10_4_PDEV_PARAM_BEACON_GEN_MODE,
+       .beacon_tx_mode = WMI_10_4_PDEV_PARAM_BEACON_TX_MODE,
+       .resmgr_offchan_mode = WMI_10_4_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
+       .protection_mode = WMI_10_4_PDEV_PARAM_PROTECTION_MODE,
+       .dynamic_bw = WMI_10_4_PDEV_PARAM_DYNAMIC_BW,
+       .non_agg_sw_retry_th = WMI_10_4_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
+       .agg_sw_retry_th = WMI_10_4_PDEV_PARAM_AGG_SW_RETRY_TH,
+       .sta_kickout_th = WMI_10_4_PDEV_PARAM_STA_KICKOUT_TH,
+       .ac_aggrsize_scaling = WMI_10_4_PDEV_PARAM_AC_AGGRSIZE_SCALING,
+       .ltr_enable = WMI_10_4_PDEV_PARAM_LTR_ENABLE,
+       .ltr_ac_latency_be = WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_BE,
+       .ltr_ac_latency_bk = WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_BK,
+       .ltr_ac_latency_vi = WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_VI,
+       .ltr_ac_latency_vo = WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_VO,
+       .ltr_ac_latency_timeout = WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
+       .ltr_sleep_override = WMI_10_4_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
+       .ltr_rx_override = WMI_10_4_PDEV_PARAM_LTR_RX_OVERRIDE,
+       .ltr_tx_activity_timeout = WMI_10_4_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
+       .l1ss_enable = WMI_10_4_PDEV_PARAM_L1SS_ENABLE,
+       .dsleep_enable = WMI_10_4_PDEV_PARAM_DSLEEP_ENABLE,
+       .pcielp_txbuf_flush = WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
+       .pcielp_txbuf_watermark = WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_WATERMARK,
+       .pcielp_txbuf_tmo_en = WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
+       .pcielp_txbuf_tmo_value = WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
+       .pdev_stats_update_period =
+                       WMI_10_4_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
+       .vdev_stats_update_period =
+                       WMI_10_4_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
+       .peer_stats_update_period =
+                       WMI_10_4_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
+       .bcnflt_stats_update_period =
+                       WMI_10_4_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
+       .pmf_qos = WMI_10_4_PDEV_PARAM_PMF_QOS,
+       .arp_ac_override = WMI_10_4_PDEV_PARAM_ARP_AC_OVERRIDE,
+       .dcs = WMI_10_4_PDEV_PARAM_DCS,
+       .ani_enable = WMI_10_4_PDEV_PARAM_ANI_ENABLE,
+       .ani_poll_period = WMI_10_4_PDEV_PARAM_ANI_POLL_PERIOD,
+       .ani_listen_period = WMI_10_4_PDEV_PARAM_ANI_LISTEN_PERIOD,
+       .ani_ofdm_level = WMI_10_4_PDEV_PARAM_ANI_OFDM_LEVEL,
+       .ani_cck_level = WMI_10_4_PDEV_PARAM_ANI_CCK_LEVEL,
+       .dyntxchain = WMI_10_4_PDEV_PARAM_DYNTXCHAIN,
+       .proxy_sta = WMI_10_4_PDEV_PARAM_PROXY_STA,
+       .idle_ps_config = WMI_10_4_PDEV_PARAM_IDLE_PS_CONFIG,
+       .power_gating_sleep = WMI_10_4_PDEV_PARAM_POWER_GATING_SLEEP,
+       .fast_channel_reset = WMI_10_4_PDEV_PARAM_FAST_CHANNEL_RESET,
+       .burst_dur = WMI_10_4_PDEV_PARAM_BURST_DUR,
+       .burst_enable = WMI_10_4_PDEV_PARAM_BURST_ENABLE,
+       .cal_period = WMI_10_4_PDEV_PARAM_CAL_PERIOD,
+       .aggr_burst = WMI_10_4_PDEV_PARAM_AGGR_BURST,
+       .rx_decap_mode = WMI_10_4_PDEV_PARAM_RX_DECAP_MODE,
+       .smart_antenna_default_antenna =
+                       WMI_10_4_PDEV_PARAM_SMART_ANTENNA_DEFAULT_ANTENNA,
+       .igmpmld_override = WMI_10_4_PDEV_PARAM_IGMPMLD_OVERRIDE,
+       .igmpmld_tid = WMI_10_4_PDEV_PARAM_IGMPMLD_TID,
+       .antenna_gain = WMI_10_4_PDEV_PARAM_ANTENNA_GAIN,
+       .rx_filter = WMI_10_4_PDEV_PARAM_RX_FILTER,
+       .set_mcast_to_ucast_tid = WMI_10_4_PDEV_SET_MCAST_TO_UCAST_TID,
+       .proxy_sta_mode = WMI_10_4_PDEV_PARAM_PROXY_STA_MODE,
+       .set_mcast2ucast_mode = WMI_10_4_PDEV_PARAM_SET_MCAST2UCAST_MODE,
+       .set_mcast2ucast_buffer = WMI_10_4_PDEV_PARAM_SET_MCAST2UCAST_BUFFER,
+       .remove_mcast2ucast_buffer =
+                       WMI_10_4_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
+       .peer_sta_ps_statechg_enable =
+                       WMI_10_4_PDEV_PEER_STA_PS_STATECHG_ENABLE,
+       .igmpmld_ac_override = WMI_10_4_PDEV_PARAM_IGMPMLD_AC_OVERRIDE,
+       .block_interbss = WMI_10_4_PDEV_PARAM_BLOCK_INTERBSS,
+       .set_disable_reset_cmdid = WMI_10_4_PDEV_PARAM_SET_DISABLE_RESET_CMDID,
+       .set_msdu_ttl_cmdid = WMI_10_4_PDEV_PARAM_SET_MSDU_TTL_CMDID,
+       .set_ppdu_duration_cmdid = WMI_10_4_PDEV_PARAM_SET_PPDU_DURATION_CMDID,
+       .txbf_sound_period_cmdid = WMI_10_4_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
+       .set_promisc_mode_cmdid = WMI_10_4_PDEV_PARAM_SET_PROMISC_MODE_CMDID,
+       .set_burst_mode_cmdid = WMI_10_4_PDEV_PARAM_SET_BURST_MODE_CMDID,
+       .en_stats = WMI_10_4_PDEV_PARAM_EN_STATS,
+       .mu_group_policy = WMI_10_4_PDEV_PARAM_MU_GROUP_POLICY,
+       .noise_detection = WMI_10_4_PDEV_PARAM_NOISE_DETECTION,
+       .noise_threshold = WMI_10_4_PDEV_PARAM_NOISE_THRESHOLD,
+       .dpd_enable = WMI_10_4_PDEV_PARAM_DPD_ENABLE,
+       .set_mcast_bcast_echo = WMI_10_4_PDEV_PARAM_SET_MCAST_BCAST_ECHO,
+       .atf_strict_sch = WMI_10_4_PDEV_PARAM_ATF_STRICT_SCH,
+       .atf_sched_duration = WMI_10_4_PDEV_PARAM_ATF_SCHED_DURATION,
+       .ant_plzn = WMI_10_4_PDEV_PARAM_ANT_PLZN,
+       .mgmt_retry_limit = WMI_10_4_PDEV_PARAM_MGMT_RETRY_LIMIT,
+       .sensitivity_level = WMI_10_4_PDEV_PARAM_SENSITIVITY_LEVEL,
+       .signed_txpower_2g = WMI_10_4_PDEV_PARAM_SIGNED_TXPOWER_2G,
+       .signed_txpower_5g = WMI_10_4_PDEV_PARAM_SIGNED_TXPOWER_5G,
+       .enable_per_tid_amsdu = WMI_10_4_PDEV_PARAM_ENABLE_PER_TID_AMSDU,
+       .enable_per_tid_ampdu = WMI_10_4_PDEV_PARAM_ENABLE_PER_TID_AMPDU,
+       .cca_threshold = WMI_10_4_PDEV_PARAM_CCA_THRESHOLD,
+       .rts_fixed_rate = WMI_10_4_PDEV_PARAM_RTS_FIXED_RATE,
+       .pdev_reset = WMI_10_4_PDEV_PARAM_PDEV_RESET,
+       .wapi_mbssid_offset = WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
+       .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+       .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
 };
 
 void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
@@ -1232,6 +1923,8 @@ ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type,
                        return "completed [preempted]";
                case WMI_SCAN_REASON_TIMEDOUT:
                        return "completed [timedout]";
+               case WMI_SCAN_REASON_INTERNAL_FAILURE:
+                       return "completed [internal err]";
                case WMI_SCAN_REASON_MAX:
                        break;
                }
@@ -1246,6 +1939,10 @@ ath10k_wmi_event_scan_type_str(enum wmi_scan_event_type type,
                return "preempted";
        case WMI_SCAN_EVENT_START_FAILED:
                return "start failed";
+       case WMI_SCAN_EVENT_RESTARTED:
+               return "restarted";
+       case WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT:
+               return "foreign channel exit";
        default:
                return "unknown";
        }
@@ -1321,6 +2018,8 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
                break;
        case WMI_SCAN_EVENT_DEQUEUED:
        case WMI_SCAN_EVENT_PREEMPTED:
+       case WMI_SCAN_EVENT_RESTARTED:
+       case WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT:
        default:
                break;
        }
@@ -1433,6 +2132,40 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
        return 0;
 }
 
+static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
+                                             struct sk_buff *skb,
+                                             struct wmi_mgmt_rx_ev_arg *arg)
+{
+       struct wmi_10_4_mgmt_rx_event *ev;
+       struct wmi_10_4_mgmt_rx_hdr *ev_hdr;
+       size_t pull_len;
+       u32 msdu_len;
+
+       ev = (struct wmi_10_4_mgmt_rx_event *)skb->data;
+       ev_hdr = &ev->hdr;
+       pull_len = sizeof(*ev);
+
+       if (skb->len < pull_len)
+               return -EPROTO;
+
+       skb_pull(skb, pull_len);
+       arg->channel = ev_hdr->channel;
+       arg->buf_len = ev_hdr->buf_len;
+       arg->status = ev_hdr->status;
+       arg->snr = ev_hdr->snr;
+       arg->phy_mode = ev_hdr->phy_mode;
+       arg->rate = ev_hdr->rate;
+
+       msdu_len = __le32_to_cpu(arg->buf_len);
+       if (skb->len < msdu_len)
+               return -EPROTO;
+
+       /* Make sure bytes added for padding are removed. */
+       skb_trim(skb, msdu_len);
+
+       return 0;
+}
+
 int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
 {
        struct wmi_mgmt_rx_ev_arg arg = {};
@@ -1593,6 +2326,29 @@ static int ath10k_wmi_op_pull_ch_info_ev(struct ath10k *ar, struct sk_buff *skb,
        return 0;
 }
 
+static int ath10k_wmi_10_4_op_pull_ch_info_ev(struct ath10k *ar,
+                                             struct sk_buff *skb,
+                                             struct wmi_ch_info_ev_arg *arg)
+{
+       struct wmi_10_4_chan_info_event *ev = (void *)skb->data;
+
+       if (skb->len < sizeof(*ev))
+               return -EPROTO;
+
+       skb_pull(skb, sizeof(*ev));
+       arg->err_code = ev->err_code;
+       arg->freq = ev->freq;
+       arg->cmd_flags = ev->cmd_flags;
+       arg->noise_floor = ev->noise_floor;
+       arg->rx_clear_count = ev->rx_clear_count;
+       arg->cycle_count = ev->cycle_count;
+       arg->chan_tx_pwr_range = ev->chan_tx_pwr_range;
+       arg->chan_tx_pwr_tp = ev->chan_tx_pwr_tp;
+       arg->rx_frame_count = ev->rx_frame_count;
+
+       return 0;
+}
+
 void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
 {
        struct wmi_ch_info_ev_arg arg = {};
@@ -2149,33 +2905,42 @@ exit:
 static void ath10k_wmi_update_tim(struct ath10k *ar,
                                  struct ath10k_vif *arvif,
                                  struct sk_buff *bcn,
-                                 const struct wmi_tim_info *tim_info)
+                                 const struct wmi_tim_info_arg *tim_info)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)bcn->data;
        struct ieee80211_tim_ie *tim;
        u8 *ies, *ie;
        u8 ie_len, pvm_len;
        __le32 t;
-       u32 v;
+       u32 v, tim_len;
+
+       /* When FW reports 0 in tim_len, ensure atleast first byte
+        * in tim_bitmap is considered for pvm calculation.
+        */
+       tim_len = tim_info->tim_len ? __le32_to_cpu(tim_info->tim_len) : 1;
 
        /* if next SWBA has no tim_changed the tim_bitmap is garbage.
         * we must copy the bitmap upon change and reuse it later */
        if (__le32_to_cpu(tim_info->tim_changed)) {
                int i;
 
-               BUILD_BUG_ON(sizeof(arvif->u.ap.tim_bitmap) !=
-                            sizeof(tim_info->tim_bitmap));
+               if (sizeof(arvif->u.ap.tim_bitmap) < tim_len) {
+                       ath10k_warn(ar, "SWBA TIM field is too big (%u), truncated it to %zu",
+                                   tim_len, sizeof(arvif->u.ap.tim_bitmap));
+                       tim_len = sizeof(arvif->u.ap.tim_bitmap);
+               }
 
-               for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
+               for (i = 0; i < tim_len; i++) {
                        t = tim_info->tim_bitmap[i / 4];
                        v = __le32_to_cpu(t);
                        arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
                }
 
-               /* FW reports either length 0 or 16
-                * so we calculate this on our own */
+               /* FW reports either length 0 or length based on max supported
+                * station. so we calculate this on our own
+                */
                arvif->u.ap.tim_len = 0;
-               for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++)
+               for (i = 0; i < tim_len; i++)
                        if (arvif->u.ap.tim_bitmap[i])
                                arvif->u.ap.tim_len = i;
 
@@ -2199,7 +2964,7 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
        pvm_len = ie_len - 3; /* exclude dtim count, dtim period, bmap ctl */
 
        if (pvm_len < arvif->u.ap.tim_len) {
-               int expand_size = sizeof(arvif->u.ap.tim_bitmap) - pvm_len;
+               int expand_size = tim_len - pvm_len;
                int move_size = skb_tail_pointer(bcn) - (ie + 2 + ie_len);
                void *next_ie = ie + 2 + ie_len;
 
@@ -2214,7 +2979,7 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
                }
        }
 
-       if (pvm_len > sizeof(arvif->u.ap.tim_bitmap)) {
+       if (pvm_len > tim_len) {
                ath10k_warn(ar, "tim pvm length is too great (%d)\n", pvm_len);
                return;
        }
@@ -2278,7 +3043,21 @@ static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
                if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info)))
                        break;
 
-               arg->tim_info[i] = &ev->bcn_info[i].tim_info;
+               if (__le32_to_cpu(ev->bcn_info[i].tim_info.tim_len) >
+                    sizeof(ev->bcn_info[i].tim_info.tim_bitmap)) {
+                       ath10k_warn(ar, "refusing to parse invalid swba structure\n");
+                       return -EPROTO;
+               }
+
+               arg->tim_info[i].tim_len = ev->bcn_info[i].tim_info.tim_len;
+               arg->tim_info[i].tim_mcast = ev->bcn_info[i].tim_info.tim_mcast;
+               arg->tim_info[i].tim_bitmap =
+                               ev->bcn_info[i].tim_info.tim_bitmap;
+               arg->tim_info[i].tim_changed =
+                               ev->bcn_info[i].tim_info.tim_changed;
+               arg->tim_info[i].tim_num_ps_pending =
+                               ev->bcn_info[i].tim_info.tim_num_ps_pending;
+
                arg->noa_info[i] = &ev->bcn_info[i].p2p_noa_info;
                i++;
        }
@@ -2286,12 +3065,69 @@ static int ath10k_wmi_op_pull_swba_ev(struct ath10k *ar, struct sk_buff *skb,
        return 0;
 }
 
+static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar,
+                                          struct sk_buff *skb,
+                                          struct wmi_swba_ev_arg *arg)
+{
+       struct wmi_10_4_host_swba_event *ev = (void *)skb->data;
+       u32 map, tim_len;
+       size_t i;
+
+       if (skb->len < sizeof(*ev))
+               return -EPROTO;
+
+       skb_pull(skb, sizeof(*ev));
+       arg->vdev_map = ev->vdev_map;
+
+       for (i = 0, map = __le32_to_cpu(ev->vdev_map); map; map >>= 1) {
+               if (!(map & BIT(0)))
+                       continue;
+
+               /* If this happens there were some changes in firmware and
+                * ath10k should update the max size of tim_info array.
+                */
+               if (WARN_ON_ONCE(i == ARRAY_SIZE(arg->tim_info)))
+                       break;
+
+               if (__le32_to_cpu(ev->bcn_info[i].tim_info.tim_len) >
+                     sizeof(ev->bcn_info[i].tim_info.tim_bitmap)) {
+                       ath10k_warn(ar, "refusing to parse invalid swba structure\n");
+                       return -EPROTO;
+               }
+
+               tim_len = __le32_to_cpu(ev->bcn_info[i].tim_info.tim_len);
+               if (tim_len) {
+                       /* Exclude 4 byte guard length */
+                       tim_len -= 4;
+                       arg->tim_info[i].tim_len = __cpu_to_le32(tim_len);
+               } else {
+                       arg->tim_info[i].tim_len = 0;
+               }
+
+               arg->tim_info[i].tim_mcast = ev->bcn_info[i].tim_info.tim_mcast;
+               arg->tim_info[i].tim_bitmap =
+                               ev->bcn_info[i].tim_info.tim_bitmap;
+               arg->tim_info[i].tim_changed =
+                               ev->bcn_info[i].tim_info.tim_changed;
+               arg->tim_info[i].tim_num_ps_pending =
+                               ev->bcn_info[i].tim_info.tim_num_ps_pending;
+
+               /* 10.4 firmware doesn't have p2p support. notice of absence
+                * info can be ignored for now.
+                */
+
+               i++;
+       }
+
+       return 0;
+}
+
 void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
 {
        struct wmi_swba_ev_arg arg = {};
        u32 map;
        int i = -1;
-       const struct wmi_tim_info *tim_info;
+       const struct wmi_tim_info_arg *tim_info;
        const struct wmi_p2p_noa_info *noa_info;
        struct ath10k_vif *arvif;
        struct sk_buff *bcn;
@@ -2320,7 +3156,7 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
                        break;
                }
 
-               tim_info = arg.tim_info[i];
+               tim_info = &arg.tim_info[i];
                noa_info = arg.noa_info[i];
 
                ath10k_dbg(ar, ATH10K_DBG_MGMT,
@@ -2335,6 +3171,10 @@ void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
                           __le32_to_cpu(tim_info->tim_bitmap[1]),
                           __le32_to_cpu(tim_info->tim_bitmap[0]));
 
+               /* TODO: Only first 4 word from tim_bitmap is dumped.
+                * Extend debug code to dump full tim_bitmap.
+                */
+
                arvif = ath10k_get_arvif(ar, vdev_id);
                if (arvif == NULL) {
                        ath10k_warn(ar, "no vif for vdev_id %d found\n",
@@ -3075,10 +3915,10 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
        if (ar->fw_api == 1 && ar->fw_version_build > 636)
                set_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features);
 
-       if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
+       if (ar->num_rf_chains > ar->max_spatial_stream) {
                ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
-                           ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
-               ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
+                           ar->num_rf_chains, ar->max_spatial_stream);
+               ar->num_rf_chains = ar->max_spatial_stream;
        }
 
        ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
@@ -3101,20 +3941,39 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
                return;
        }
 
+       if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) {
+               ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX +
+                                   TARGET_10_4_NUM_VDEVS;
+               ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS +
+                                      TARGET_10_4_NUM_VDEVS;
+               ar->num_tids = ar->num_active_peers * 2;
+               ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX;
+       }
+
+       /* TODO: Adjust max peer count for cases like WMI_SERVICE_RATECTRL_CACHE
+        * and WMI_SERVICE_IRAM_TIDS, etc.
+        */
+
        for (i = 0; i < num_mem_reqs; ++i) {
                req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
                num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
                unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
                num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
 
-               if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
+               if (num_unit_info & NUM_UNITS_IS_NUM_ACTIVE_PEERS) {
+                       if (ar->num_active_peers)
+                               num_units = ar->num_active_peers + 1;
+                       else
+                               num_units = ar->max_num_peers + 1;
+               } else if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) {
                        /* number of units to allocate is number of
                         * peers, 1 extra for self peer on target */
                        /* this needs to be tied, host and target
                         * can get out of sync */
-                       num_units = TARGET_10X_NUM_PEERS + 1;
-               else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS)
-                       num_units = TARGET_10X_NUM_VDEVS + 1;
+                       num_units = ar->max_num_peers + 1;
+               } else if (num_unit_info & NUM_UNITS_IS_NUM_VDEVS) {
+                       num_units = ar->max_num_vdevs + 1;
+               }
 
                ath10k_dbg(ar, ATH10K_DBG_WMI,
                           "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
@@ -3576,6 +4435,73 @@ out:
        dev_kfree_skb(skb);
 }
 
+static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
+{
+       struct wmi_cmd_hdr *cmd_hdr;
+       enum wmi_10_4_event_id id;
+
+       cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
+       id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
+
+       if (!skb_pull(skb, sizeof(struct wmi_cmd_hdr)))
+               goto out;
+
+       trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
+
+       switch (id) {
+       case WMI_10_4_MGMT_RX_EVENTID:
+               ath10k_wmi_event_mgmt_rx(ar, skb);
+               /* mgmt_rx() owns the skb now! */
+               return;
+       case WMI_10_4_ECHO_EVENTID:
+               ath10k_wmi_event_echo(ar, skb);
+               break;
+       case WMI_10_4_DEBUG_MESG_EVENTID:
+               ath10k_wmi_event_debug_mesg(ar, skb);
+               break;
+       case WMI_10_4_SERVICE_READY_EVENTID:
+               ath10k_wmi_event_service_ready(ar, skb);
+               break;
+       case WMI_10_4_SCAN_EVENTID:
+               ath10k_wmi_event_scan(ar, skb);
+               break;
+       case WMI_10_4_CHAN_INFO_EVENTID:
+               ath10k_wmi_event_chan_info(ar, skb);
+               break;
+       case WMI_10_4_READY_EVENTID:
+               ath10k_wmi_event_ready(ar, skb);
+               break;
+       case WMI_10_4_PEER_STA_KICKOUT_EVENTID:
+               ath10k_wmi_event_peer_sta_kickout(ar, skb);
+               break;
+       case WMI_10_4_HOST_SWBA_EVENTID:
+               ath10k_wmi_event_host_swba(ar, skb);
+               break;
+       case WMI_10_4_TBTTOFFSET_UPDATE_EVENTID:
+               ath10k_wmi_event_tbttoffset_update(ar, skb);
+               break;
+       case WMI_10_4_DEBUG_PRINT_EVENTID:
+               ath10k_wmi_event_debug_print(ar, skb);
+               break;
+       case WMI_10_4_VDEV_START_RESP_EVENTID:
+               ath10k_wmi_event_vdev_start_resp(ar, skb);
+               break;
+       case WMI_10_4_VDEV_STOPPED_EVENTID:
+               ath10k_wmi_event_vdev_stopped(ar, skb);
+               break;
+       case WMI_10_4_WOW_WAKEUP_HOST_EVENTID:
+               ath10k_dbg(ar, ATH10K_DBG_WMI,
+                          "received event id %d not implemented\n", id);
+               break;
+       default:
+               ath10k_warn(ar, "Unknown eventid: %d\n", id);
+               break;
+       }
+
+out:
+       dev_kfree_skb(skb);
+}
+
 static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb)
 {
        int ret;
@@ -3950,6 +4876,88 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
        return buf;
 }
 
+static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
+{
+       struct wmi_init_cmd_10_4 *cmd;
+       struct sk_buff *buf;
+       struct wmi_resource_config_10_4 config = {};
+       u32 len;
+
+       config.num_vdevs = __cpu_to_le32(ar->max_num_vdevs);
+       config.num_peers = __cpu_to_le32(ar->max_num_peers);
+       config.num_active_peers = __cpu_to_le32(ar->num_active_peers);
+       config.num_tids = __cpu_to_le32(ar->num_tids);
+
+       config.num_offload_peers = __cpu_to_le32(TARGET_10_4_NUM_OFFLOAD_PEERS);
+       config.num_offload_reorder_buffs =
+                       __cpu_to_le32(TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS);
+       config.num_peer_keys  = __cpu_to_le32(TARGET_10_4_NUM_PEER_KEYS);
+       config.ast_skid_limit = __cpu_to_le32(TARGET_10_4_AST_SKID_LIMIT);
+       config.tx_chain_mask  = __cpu_to_le32(TARGET_10_4_TX_CHAIN_MASK);
+       config.rx_chain_mask  = __cpu_to_le32(TARGET_10_4_RX_CHAIN_MASK);
+
+       config.rx_timeout_pri[0] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI);
+       config.rx_timeout_pri[1] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI);
+       config.rx_timeout_pri[2] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_LO_PRI);
+       config.rx_timeout_pri[3] = __cpu_to_le32(TARGET_10_4_RX_TIMEOUT_HI_PRI);
+
+       config.rx_decap_mode        = __cpu_to_le32(TARGET_10_4_RX_DECAP_MODE);
+       config.scan_max_pending_req = __cpu_to_le32(TARGET_10_4_SCAN_MAX_REQS);
+       config.bmiss_offload_max_vdev =
+                       __cpu_to_le32(TARGET_10_4_BMISS_OFFLOAD_MAX_VDEV);
+       config.roam_offload_max_vdev  =
+                       __cpu_to_le32(TARGET_10_4_ROAM_OFFLOAD_MAX_VDEV);
+       config.roam_offload_max_ap_profiles =
+                       __cpu_to_le32(TARGET_10_4_ROAM_OFFLOAD_MAX_PROFILES);
+       config.num_mcast_groups = __cpu_to_le32(TARGET_10_4_NUM_MCAST_GROUPS);
+       config.num_mcast_table_elems =
+                       __cpu_to_le32(TARGET_10_4_NUM_MCAST_TABLE_ELEMS);
+
+       config.mcast2ucast_mode = __cpu_to_le32(TARGET_10_4_MCAST2UCAST_MODE);
+       config.tx_dbg_log_size  = __cpu_to_le32(TARGET_10_4_TX_DBG_LOG_SIZE);
+       config.num_wds_entries  = __cpu_to_le32(TARGET_10_4_NUM_WDS_ENTRIES);
+       config.dma_burst_size   = __cpu_to_le32(TARGET_10_4_DMA_BURST_SIZE);
+       config.mac_aggr_delim   = __cpu_to_le32(TARGET_10_4_MAC_AGGR_DELIM);
+
+       config.rx_skip_defrag_timeout_dup_detection_check =
+         __cpu_to_le32(TARGET_10_4_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK);
+
+       config.vow_config = __cpu_to_le32(TARGET_10_4_VOW_CONFIG);
+       config.gtk_offload_max_vdev =
+                       __cpu_to_le32(TARGET_10_4_GTK_OFFLOAD_MAX_VDEV);
+       config.num_msdu_desc = __cpu_to_le32(TARGET_10_4_NUM_MSDU_DESC);
+       config.max_frag_entries = __cpu_to_le32(TARGET_10_4_11AC_TX_MAX_FRAGS);
+       config.max_peer_ext_stats =
+                       __cpu_to_le32(TARGET_10_4_MAX_PEER_EXT_STATS);
+       config.smart_ant_cap = __cpu_to_le32(TARGET_10_4_SMART_ANT_CAP);
+
+       config.bk_minfree = __cpu_to_le32(TARGET_10_4_BK_MIN_FREE);
+       config.be_minfree = __cpu_to_le32(TARGET_10_4_BE_MIN_FREE);
+       config.vi_minfree = __cpu_to_le32(TARGET_10_4_VI_MIN_FREE);
+       config.vo_minfree = __cpu_to_le32(TARGET_10_4_VO_MIN_FREE);
+
+       config.rx_batchmode = __cpu_to_le32(TARGET_10_4_RX_BATCH_MODE);
+       config.tt_support =
+                       __cpu_to_le32(TARGET_10_4_THERMAL_THROTTLING_CONFIG);
+       config.atf_config = __cpu_to_le32(TARGET_10_4_ATF_CONFIG);
+       config.iphdr_pad_config = __cpu_to_le32(TARGET_10_4_IPHDR_PAD_CONFIG);
+       config.qwrap_config = __cpu_to_le32(TARGET_10_4_QWRAP_CONFIG);
+
+       len = sizeof(*cmd) +
+             (sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
+
+       buf = ath10k_wmi_alloc_skb(ar, len);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       cmd = (struct wmi_init_cmd_10_4 *)buf->data;
+       memcpy(&cmd->resource_config, &config, sizeof(config));
+       ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
+
+       ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.4\n");
+       return buf;
+}
+
 int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
 {
        if (arg->ie_len && !arg->ie)
@@ -4172,7 +5180,6 @@ void ath10k_wmi_start_scan_init(struct ath10k *ar,
                | WMI_SCAN_EVENT_BSS_CHANNEL
                | WMI_SCAN_EVENT_FOREIGN_CHANNEL
                | WMI_SCAN_EVENT_DEQUEUED;
-       arg->scan_ctrl_flags |= WMI_SCAN_ADD_OFDM_RATES;
        arg->scan_ctrl_flags |= WMI_SCAN_CHAN_STAT_EVENT;
        arg->n_bssids = 1;
        arg->bssids[0].bssid = "\xFF\xFF\xFF\xFF\xFF\xFF";
@@ -5412,9 +6419,64 @@ static const struct wmi_ops wmi_10_2_4_ops = {
        /* .gen_adaptive_qcs not implemented */
 };
 
+static const struct wmi_ops wmi_10_4_ops = {
+       .rx = ath10k_wmi_10_4_op_rx,
+       .map_svc = wmi_10_4_svc_map,
+
+       .pull_scan = ath10k_wmi_op_pull_scan_ev,
+       .pull_mgmt_rx = ath10k_wmi_10_4_op_pull_mgmt_rx_ev,
+       .pull_ch_info = ath10k_wmi_10_4_op_pull_ch_info_ev,
+       .pull_vdev_start = ath10k_wmi_op_pull_vdev_start_ev,
+       .pull_peer_kick = ath10k_wmi_op_pull_peer_kick_ev,
+       .pull_swba = ath10k_wmi_10_4_op_pull_swba_ev,
+       .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
+       .pull_rdy = ath10k_wmi_op_pull_rdy_ev,
+
+       .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
+       .gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
+       .gen_pdev_set_rd = ath10k_wmi_10x_op_gen_pdev_set_rd,
+       .gen_pdev_set_param = ath10k_wmi_op_gen_pdev_set_param,
+       .gen_init = ath10k_wmi_10_4_op_gen_init,
+       .gen_start_scan = ath10k_wmi_op_gen_start_scan,
+       .gen_stop_scan = ath10k_wmi_op_gen_stop_scan,
+       .gen_vdev_create = ath10k_wmi_op_gen_vdev_create,
+       .gen_vdev_delete = ath10k_wmi_op_gen_vdev_delete,
+       .gen_vdev_start = ath10k_wmi_op_gen_vdev_start,
+       .gen_vdev_stop = ath10k_wmi_op_gen_vdev_stop,
+       .gen_vdev_up = ath10k_wmi_op_gen_vdev_up,
+       .gen_vdev_down = ath10k_wmi_op_gen_vdev_down,
+       .gen_vdev_set_param = ath10k_wmi_op_gen_vdev_set_param,
+       .gen_vdev_install_key = ath10k_wmi_op_gen_vdev_install_key,
+       .gen_peer_create = ath10k_wmi_op_gen_peer_create,
+       .gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
+       .gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
+       .gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
+       .gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
+       .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
+       .gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
+       .gen_scan_chan_list = ath10k_wmi_op_gen_scan_chan_list,
+       .gen_beacon_dma = ath10k_wmi_op_gen_beacon_dma,
+       .gen_pdev_set_wmm = ath10k_wmi_op_gen_pdev_set_wmm,
+       .gen_force_fw_hang = ath10k_wmi_op_gen_force_fw_hang,
+       .gen_mgmt_tx = ath10k_wmi_op_gen_mgmt_tx,
+       .gen_dbglog_cfg = ath10k_wmi_op_gen_dbglog_cfg,
+       .gen_pktlog_enable = ath10k_wmi_op_gen_pktlog_enable,
+       .gen_pktlog_disable = ath10k_wmi_op_gen_pktlog_disable,
+       .gen_pdev_set_quiet_mode = ath10k_wmi_op_gen_pdev_set_quiet_mode,
+
+       /* shared with 10.2 */
+       .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
+};
+
 int ath10k_wmi_attach(struct ath10k *ar)
 {
        switch (ar->wmi.op_version) {
+       case ATH10K_FW_WMI_OP_VERSION_10_4:
+               ar->wmi.ops = &wmi_10_4_ops;
+               ar->wmi.cmd = &wmi_10_4_cmd_map;
+               ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
+               ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
+               break;
        case ATH10K_FW_WMI_OP_VERSION_10_2_4:
                ar->wmi.cmd = &wmi_10_2_4_cmd_map;
                ar->wmi.ops = &wmi_10_2_4_ops;
index cf44a3d080a38c7a58b454d7e82419e98f1733a4..0d4efc9c5796432cec96bacf70c83a4f94d8e7dc 100644 (file)
@@ -150,6 +150,12 @@ enum wmi_service {
        WMI_SERVICE_SAP_AUTH_OFFLOAD,
        WMI_SERVICE_ATF,
        WMI_SERVICE_COEX_GPIO,
+       WMI_SERVICE_ENHANCED_PROXY_STA,
+       WMI_SERVICE_TT,
+       WMI_SERVICE_PEER_CACHING,
+       WMI_SERVICE_AUX_SPECTRAL_INTF,
+       WMI_SERVICE_AUX_CHAN_LOAD_INTF,
+       WMI_SERVICE_BSS_CHANNEL_INFO_64,
 
        /* keep last */
        WMI_SERVICE_MAX,
@@ -218,6 +224,51 @@ enum wmi_main_service {
        WMI_MAIN_SERVICE_TX_ENCAP,
 };
 
+enum wmi_10_4_service {
+       WMI_10_4_SERVICE_BEACON_OFFLOAD = 0,
+       WMI_10_4_SERVICE_SCAN_OFFLOAD,
+       WMI_10_4_SERVICE_ROAM_OFFLOAD,
+       WMI_10_4_SERVICE_BCN_MISS_OFFLOAD,
+       WMI_10_4_SERVICE_STA_PWRSAVE,
+       WMI_10_4_SERVICE_STA_ADVANCED_PWRSAVE,
+       WMI_10_4_SERVICE_AP_UAPSD,
+       WMI_10_4_SERVICE_AP_DFS,
+       WMI_10_4_SERVICE_11AC,
+       WMI_10_4_SERVICE_BLOCKACK,
+       WMI_10_4_SERVICE_PHYERR,
+       WMI_10_4_SERVICE_BCN_FILTER,
+       WMI_10_4_SERVICE_RTT,
+       WMI_10_4_SERVICE_RATECTRL,
+       WMI_10_4_SERVICE_WOW,
+       WMI_10_4_SERVICE_RATECTRL_CACHE,
+       WMI_10_4_SERVICE_IRAM_TIDS,
+       WMI_10_4_SERVICE_BURST,
+       WMI_10_4_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+       WMI_10_4_SERVICE_GTK_OFFLOAD,
+       WMI_10_4_SERVICE_SCAN_SCH,
+       WMI_10_4_SERVICE_CSA_OFFLOAD,
+       WMI_10_4_SERVICE_CHATTER,
+       WMI_10_4_SERVICE_COEX_FREQAVOID,
+       WMI_10_4_SERVICE_PACKET_POWER_SAVE,
+       WMI_10_4_SERVICE_FORCE_FW_HANG,
+       WMI_10_4_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+       WMI_10_4_SERVICE_GPIO,
+       WMI_10_4_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+       WMI_10_4_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+       WMI_10_4_SERVICE_STA_KEEP_ALIVE,
+       WMI_10_4_SERVICE_TX_ENCAP,
+       WMI_10_4_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
+       WMI_10_4_SERVICE_EARLY_RX,
+       WMI_10_4_SERVICE_ENHANCED_PROXY_STA,
+       WMI_10_4_SERVICE_TT,
+       WMI_10_4_SERVICE_ATF,
+       WMI_10_4_SERVICE_PEER_CACHING,
+       WMI_10_4_SERVICE_COEX_GPIO,
+       WMI_10_4_SERVICE_AUX_SPECTRAL_INTF,
+       WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
+       WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
+};
+
 static inline char *wmi_service_name(int service_id)
 {
 #define SVCSTR(x) case x: return #x
@@ -299,6 +350,12 @@ static inline char *wmi_service_name(int service_id)
        SVCSTR(WMI_SERVICE_SAP_AUTH_OFFLOAD);
        SVCSTR(WMI_SERVICE_ATF);
        SVCSTR(WMI_SERVICE_COEX_GPIO);
+       SVCSTR(WMI_SERVICE_ENHANCED_PROXY_STA);
+       SVCSTR(WMI_SERVICE_TT);
+       SVCSTR(WMI_SERVICE_PEER_CACHING);
+       SVCSTR(WMI_SERVICE_AUX_SPECTRAL_INTF);
+       SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF);
+       SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64);
        default:
                return NULL;
        }
@@ -437,6 +494,95 @@ static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
               WMI_SERVICE_TX_ENCAP, len);
 }
 
+static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
+                                   size_t len)
+{
+       SVCMAP(WMI_10_4_SERVICE_BEACON_OFFLOAD,
+              WMI_SERVICE_BEACON_OFFLOAD, len);
+       SVCMAP(WMI_10_4_SERVICE_SCAN_OFFLOAD,
+              WMI_SERVICE_SCAN_OFFLOAD, len);
+       SVCMAP(WMI_10_4_SERVICE_ROAM_OFFLOAD,
+              WMI_SERVICE_ROAM_OFFLOAD, len);
+       SVCMAP(WMI_10_4_SERVICE_BCN_MISS_OFFLOAD,
+              WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+       SVCMAP(WMI_10_4_SERVICE_STA_PWRSAVE,
+              WMI_SERVICE_STA_PWRSAVE, len);
+       SVCMAP(WMI_10_4_SERVICE_STA_ADVANCED_PWRSAVE,
+              WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+       SVCMAP(WMI_10_4_SERVICE_AP_UAPSD,
+              WMI_SERVICE_AP_UAPSD, len);
+       SVCMAP(WMI_10_4_SERVICE_AP_DFS,
+              WMI_SERVICE_AP_DFS, len);
+       SVCMAP(WMI_10_4_SERVICE_11AC,
+              WMI_SERVICE_11AC, len);
+       SVCMAP(WMI_10_4_SERVICE_BLOCKACK,
+              WMI_SERVICE_BLOCKACK, len);
+       SVCMAP(WMI_10_4_SERVICE_PHYERR,
+              WMI_SERVICE_PHYERR, len);
+       SVCMAP(WMI_10_4_SERVICE_BCN_FILTER,
+              WMI_SERVICE_BCN_FILTER, len);
+       SVCMAP(WMI_10_4_SERVICE_RTT,
+              WMI_SERVICE_RTT, len);
+       SVCMAP(WMI_10_4_SERVICE_RATECTRL,
+              WMI_SERVICE_RATECTRL, len);
+       SVCMAP(WMI_10_4_SERVICE_WOW,
+              WMI_SERVICE_WOW, len);
+       SVCMAP(WMI_10_4_SERVICE_RATECTRL_CACHE,
+              WMI_SERVICE_RATECTRL_CACHE, len);
+       SVCMAP(WMI_10_4_SERVICE_IRAM_TIDS,
+              WMI_SERVICE_IRAM_TIDS, len);
+       SVCMAP(WMI_10_4_SERVICE_BURST,
+              WMI_SERVICE_BURST, len);
+       SVCMAP(WMI_10_4_SERVICE_SMART_ANTENNA_SW_SUPPORT,
+              WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT, len);
+       SVCMAP(WMI_10_4_SERVICE_GTK_OFFLOAD,
+              WMI_SERVICE_GTK_OFFLOAD, len);
+       SVCMAP(WMI_10_4_SERVICE_SCAN_SCH,
+              WMI_SERVICE_SCAN_SCH, len);
+       SVCMAP(WMI_10_4_SERVICE_CSA_OFFLOAD,
+              WMI_SERVICE_CSA_OFFLOAD, len);
+       SVCMAP(WMI_10_4_SERVICE_CHATTER,
+              WMI_SERVICE_CHATTER, len);
+       SVCMAP(WMI_10_4_SERVICE_COEX_FREQAVOID,
+              WMI_SERVICE_COEX_FREQAVOID, len);
+       SVCMAP(WMI_10_4_SERVICE_PACKET_POWER_SAVE,
+              WMI_SERVICE_PACKET_POWER_SAVE, len);
+       SVCMAP(WMI_10_4_SERVICE_FORCE_FW_HANG,
+              WMI_SERVICE_FORCE_FW_HANG, len);
+       SVCMAP(WMI_10_4_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+              WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT, len);
+       SVCMAP(WMI_10_4_SERVICE_GPIO,
+              WMI_SERVICE_GPIO, len);
+       SVCMAP(WMI_10_4_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
+              WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, len);
+       SVCMAP(WMI_10_4_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
+              WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, len);
+       SVCMAP(WMI_10_4_SERVICE_STA_KEEP_ALIVE,
+              WMI_SERVICE_STA_KEEP_ALIVE, len);
+       SVCMAP(WMI_10_4_SERVICE_TX_ENCAP,
+              WMI_SERVICE_TX_ENCAP, len);
+       SVCMAP(WMI_10_4_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
+              WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC, len);
+       SVCMAP(WMI_10_4_SERVICE_EARLY_RX,
+              WMI_SERVICE_EARLY_RX, len);
+       SVCMAP(WMI_10_4_SERVICE_ENHANCED_PROXY_STA,
+              WMI_SERVICE_ENHANCED_PROXY_STA, len);
+       SVCMAP(WMI_10_4_SERVICE_TT,
+              WMI_SERVICE_TT, len);
+       SVCMAP(WMI_10_4_SERVICE_ATF,
+              WMI_SERVICE_ATF, len);
+       SVCMAP(WMI_10_4_SERVICE_PEER_CACHING,
+              WMI_SERVICE_PEER_CACHING, len);
+       SVCMAP(WMI_10_4_SERVICE_COEX_GPIO,
+              WMI_SERVICE_COEX_GPIO, len);
+       SVCMAP(WMI_10_4_SERVICE_AUX_SPECTRAL_INTF,
+              WMI_SERVICE_AUX_SPECTRAL_INTF, len);
+       SVCMAP(WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
+              WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
+       SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
+              WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
+}
+
 #undef SVCMAP
 
 /* 2 word representation of MAC addr */
@@ -565,6 +711,48 @@ struct wmi_cmd_map {
        u32 tdls_set_state_cmdid;
        u32 tdls_peer_update_cmdid;
        u32 adaptive_qcs_cmdid;
+       u32 scan_update_request_cmdid;
+       u32 vdev_standby_response_cmdid;
+       u32 vdev_resume_response_cmdid;
+       u32 wlan_peer_caching_add_peer_cmdid;
+       u32 wlan_peer_caching_evict_peer_cmdid;
+       u32 wlan_peer_caching_restore_peer_cmdid;
+       u32 wlan_peer_caching_print_all_peers_info_cmdid;
+       u32 peer_update_wds_entry_cmdid;
+       u32 peer_add_proxy_sta_entry_cmdid;
+       u32 rtt_keepalive_cmdid;
+       u32 oem_req_cmdid;
+       u32 nan_cmdid;
+       u32 vdev_ratemask_cmdid;
+       u32 qboost_cfg_cmdid;
+       u32 pdev_smart_ant_enable_cmdid;
+       u32 pdev_smart_ant_set_rx_antenna_cmdid;
+       u32 peer_smart_ant_set_tx_antenna_cmdid;
+       u32 peer_smart_ant_set_train_info_cmdid;
+       u32 peer_smart_ant_set_node_config_ops_cmdid;
+       u32 pdev_set_antenna_switch_table_cmdid;
+       u32 pdev_set_ctl_table_cmdid;
+       u32 pdev_set_mimogain_table_cmdid;
+       u32 pdev_ratepwr_table_cmdid;
+       u32 pdev_ratepwr_chainmsk_table_cmdid;
+       u32 pdev_fips_cmdid;
+       u32 tt_set_conf_cmdid;
+       u32 fwtest_cmdid;
+       u32 vdev_atf_request_cmdid;
+       u32 peer_atf_request_cmdid;
+       u32 pdev_get_ani_cck_config_cmdid;
+       u32 pdev_get_ani_ofdm_config_cmdid;
+       u32 pdev_reserve_ast_entry_cmdid;
+       u32 pdev_get_nfcal_power_cmdid;
+       u32 pdev_get_tpc_cmdid;
+       u32 pdev_get_ast_info_cmdid;
+       u32 vdev_set_dscp_tid_map_cmdid;
+       u32 pdev_get_info_cmdid;
+       u32 vdev_get_info_cmdid;
+       u32 vdev_filter_neighbor_rx_packets_cmdid;
+       u32 mu_cal_start_cmdid;
+       u32 set_cca_params_cmdid;
+       u32 pdev_bss_chan_info_request_cmdid;
 };
 
 /*
@@ -1220,6 +1408,216 @@ enum wmi_10_2_event_id {
        WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
 };
 
+enum wmi_10_4_cmd_id {
+       WMI_10_4_START_CMDID = 0x9000,
+       WMI_10_4_END_CMDID = 0x9FFF,
+       WMI_10_4_INIT_CMDID,
+       WMI_10_4_START_SCAN_CMDID = WMI_10_4_START_CMDID,
+       WMI_10_4_STOP_SCAN_CMDID,
+       WMI_10_4_SCAN_CHAN_LIST_CMDID,
+       WMI_10_4_SCAN_SCH_PRIO_TBL_CMDID,
+       WMI_10_4_SCAN_UPDATE_REQUEST_CMDID,
+       WMI_10_4_ECHO_CMDID,
+       WMI_10_4_PDEV_SET_REGDOMAIN_CMDID,
+       WMI_10_4_PDEV_SET_CHANNEL_CMDID,
+       WMI_10_4_PDEV_SET_PARAM_CMDID,
+       WMI_10_4_PDEV_PKTLOG_ENABLE_CMDID,
+       WMI_10_4_PDEV_PKTLOG_DISABLE_CMDID,
+       WMI_10_4_PDEV_SET_WMM_PARAMS_CMDID,
+       WMI_10_4_PDEV_SET_HT_CAP_IE_CMDID,
+       WMI_10_4_PDEV_SET_VHT_CAP_IE_CMDID,
+       WMI_10_4_PDEV_SET_BASE_MACADDR_CMDID,
+       WMI_10_4_PDEV_SET_DSCP_TID_MAP_CMDID,
+       WMI_10_4_PDEV_SET_QUIET_MODE_CMDID,
+       WMI_10_4_PDEV_GREEN_AP_PS_ENABLE_CMDID,
+       WMI_10_4_PDEV_GET_TPC_CONFIG_CMDID,
+       WMI_10_4_VDEV_CREATE_CMDID,
+       WMI_10_4_VDEV_DELETE_CMDID,
+       WMI_10_4_VDEV_START_REQUEST_CMDID,
+       WMI_10_4_VDEV_RESTART_REQUEST_CMDID,
+       WMI_10_4_VDEV_UP_CMDID,
+       WMI_10_4_VDEV_STOP_CMDID,
+       WMI_10_4_VDEV_DOWN_CMDID,
+       WMI_10_4_VDEV_STANDBY_RESPONSE_CMDID,
+       WMI_10_4_VDEV_RESUME_RESPONSE_CMDID,
+       WMI_10_4_VDEV_SET_PARAM_CMDID,
+       WMI_10_4_VDEV_INSTALL_KEY_CMDID,
+       WMI_10_4_WLAN_PEER_CACHING_ADD_PEER_CMDID,
+       WMI_10_4_WLAN_PEER_CACHING_EVICT_PEER_CMDID,
+       WMI_10_4_WLAN_PEER_CACHING_RESTORE_PEER_CMDID,
+       WMI_10_4_WLAN_PEER_CACHING_PRINT_ALL_PEERS_INFO_CMDID,
+       WMI_10_4_PEER_CREATE_CMDID,
+       WMI_10_4_PEER_DELETE_CMDID,
+       WMI_10_4_PEER_FLUSH_TIDS_CMDID,
+       WMI_10_4_PEER_SET_PARAM_CMDID,
+       WMI_10_4_PEER_ASSOC_CMDID,
+       WMI_10_4_PEER_ADD_WDS_ENTRY_CMDID,
+       WMI_10_4_PEER_UPDATE_WDS_ENTRY_CMDID,
+       WMI_10_4_PEER_REMOVE_WDS_ENTRY_CMDID,
+       WMI_10_4_PEER_ADD_PROXY_STA_ENTRY_CMDID,
+       WMI_10_4_PEER_MCAST_GROUP_CMDID,
+       WMI_10_4_BCN_TX_CMDID,
+       WMI_10_4_PDEV_SEND_BCN_CMDID,
+       WMI_10_4_BCN_PRB_TMPL_CMDID,
+       WMI_10_4_BCN_FILTER_RX_CMDID,
+       WMI_10_4_PRB_REQ_FILTER_RX_CMDID,
+       WMI_10_4_MGMT_TX_CMDID,
+       WMI_10_4_PRB_TMPL_CMDID,
+       WMI_10_4_ADDBA_CLEAR_RESP_CMDID,
+       WMI_10_4_ADDBA_SEND_CMDID,
+       WMI_10_4_ADDBA_STATUS_CMDID,
+       WMI_10_4_DELBA_SEND_CMDID,
+       WMI_10_4_ADDBA_SET_RESP_CMDID,
+       WMI_10_4_SEND_SINGLEAMSDU_CMDID,
+       WMI_10_4_STA_POWERSAVE_MODE_CMDID,
+       WMI_10_4_STA_POWERSAVE_PARAM_CMDID,
+       WMI_10_4_STA_MIMO_PS_MODE_CMDID,
+       WMI_10_4_DBGLOG_CFG_CMDID,
+       WMI_10_4_PDEV_DFS_ENABLE_CMDID,
+       WMI_10_4_PDEV_DFS_DISABLE_CMDID,
+       WMI_10_4_PDEV_QVIT_CMDID,
+       WMI_10_4_ROAM_SCAN_MODE,
+       WMI_10_4_ROAM_SCAN_RSSI_THRESHOLD,
+       WMI_10_4_ROAM_SCAN_PERIOD,
+       WMI_10_4_ROAM_SCAN_RSSI_CHANGE_THRESHOLD,
+       WMI_10_4_ROAM_AP_PROFILE,
+       WMI_10_4_OFL_SCAN_ADD_AP_PROFILE,
+       WMI_10_4_OFL_SCAN_REMOVE_AP_PROFILE,
+       WMI_10_4_OFL_SCAN_PERIOD,
+       WMI_10_4_P2P_DEV_SET_DEVICE_INFO,
+       WMI_10_4_P2P_DEV_SET_DISCOVERABILITY,
+       WMI_10_4_P2P_GO_SET_BEACON_IE,
+       WMI_10_4_P2P_GO_SET_PROBE_RESP_IE,
+       WMI_10_4_P2P_SET_VENDOR_IE_DATA_CMDID,
+       WMI_10_4_AP_PS_PEER_PARAM_CMDID,
+       WMI_10_4_AP_PS_PEER_UAPSD_COEX_CMDID,
+       WMI_10_4_PEER_RATE_RETRY_SCHED_CMDID,
+       WMI_10_4_WLAN_PROFILE_TRIGGER_CMDID,
+       WMI_10_4_WLAN_PROFILE_SET_HIST_INTVL_CMDID,
+       WMI_10_4_WLAN_PROFILE_GET_PROFILE_DATA_CMDID,
+       WMI_10_4_WLAN_PROFILE_ENABLE_PROFILE_ID_CMDID,
+       WMI_10_4_WLAN_PROFILE_LIST_PROFILE_ID_CMDID,
+       WMI_10_4_PDEV_SUSPEND_CMDID,
+       WMI_10_4_PDEV_RESUME_CMDID,
+       WMI_10_4_ADD_BCN_FILTER_CMDID,
+       WMI_10_4_RMV_BCN_FILTER_CMDID,
+       WMI_10_4_WOW_ADD_WAKE_PATTERN_CMDID,
+       WMI_10_4_WOW_DEL_WAKE_PATTERN_CMDID,
+       WMI_10_4_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID,
+       WMI_10_4_WOW_ENABLE_CMDID,
+       WMI_10_4_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID,
+       WMI_10_4_RTT_MEASREQ_CMDID,
+       WMI_10_4_RTT_TSF_CMDID,
+       WMI_10_4_RTT_KEEPALIVE_CMDID,
+       WMI_10_4_OEM_REQ_CMDID,
+       WMI_10_4_NAN_CMDID,
+       WMI_10_4_VDEV_SPECTRAL_SCAN_CONFIGURE_CMDID,
+       WMI_10_4_VDEV_SPECTRAL_SCAN_ENABLE_CMDID,
+       WMI_10_4_REQUEST_STATS_CMDID,
+       WMI_10_4_GPIO_CONFIG_CMDID,
+       WMI_10_4_GPIO_OUTPUT_CMDID,
+       WMI_10_4_VDEV_RATEMASK_CMDID,
+       WMI_10_4_CSA_OFFLOAD_ENABLE_CMDID,
+       WMI_10_4_GTK_OFFLOAD_CMDID,
+       WMI_10_4_QBOOST_CFG_CMDID,
+       WMI_10_4_CSA_OFFLOAD_CHANSWITCH_CMDID,
+       WMI_10_4_PDEV_SMART_ANT_ENABLE_CMDID,
+       WMI_10_4_PDEV_SMART_ANT_SET_RX_ANTENNA_CMDID,
+       WMI_10_4_PEER_SMART_ANT_SET_TX_ANTENNA_CMDID,
+       WMI_10_4_PEER_SMART_ANT_SET_TRAIN_INFO_CMDID,
+       WMI_10_4_PEER_SMART_ANT_SET_NODE_CONFIG_OPS_CMDID,
+       WMI_10_4_VDEV_SET_KEEPALIVE_CMDID,
+       WMI_10_4_VDEV_GET_KEEPALIVE_CMDID,
+       WMI_10_4_FORCE_FW_HANG_CMDID,
+       WMI_10_4_PDEV_SET_ANTENNA_SWITCH_TABLE_CMDID,
+       WMI_10_4_PDEV_SET_CTL_TABLE_CMDID,
+       WMI_10_4_PDEV_SET_MIMOGAIN_TABLE_CMDID,
+       WMI_10_4_PDEV_RATEPWR_TABLE_CMDID,
+       WMI_10_4_PDEV_RATEPWR_CHAINMSK_TABLE_CMDID,
+       WMI_10_4_PDEV_FIPS_CMDID,
+       WMI_10_4_TT_SET_CONF_CMDID,
+       WMI_10_4_FWTEST_CMDID,
+       WMI_10_4_VDEV_ATF_REQUEST_CMDID,
+       WMI_10_4_PEER_ATF_REQUEST_CMDID,
+       WMI_10_4_PDEV_GET_ANI_CCK_CONFIG_CMDID,
+       WMI_10_4_PDEV_GET_ANI_OFDM_CONFIG_CMDID,
+       WMI_10_4_PDEV_RESERVE_AST_ENTRY_CMDID,
+       WMI_10_4_PDEV_GET_NFCAL_POWER_CMDID,
+       WMI_10_4_PDEV_GET_TPC_CMDID,
+       WMI_10_4_PDEV_GET_AST_INFO_CMDID,
+       WMI_10_4_VDEV_SET_DSCP_TID_MAP_CMDID,
+       WMI_10_4_PDEV_GET_TEMPERATURE_CMDID,
+       WMI_10_4_PDEV_GET_INFO_CMDID,
+       WMI_10_4_VDEV_GET_INFO_CMDID,
+       WMI_10_4_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID,
+       WMI_10_4_MU_CAL_START_CMDID,
+       WMI_10_4_SET_CCA_PARAMS_CMDID,
+       WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
+       WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
+};
+
+enum wmi_10_4_event_id {
+       WMI_10_4_SERVICE_READY_EVENTID = 0x8000,
+       WMI_10_4_READY_EVENTID,
+       WMI_10_4_DEBUG_MESG_EVENTID,
+       WMI_10_4_START_EVENTID = 0x9000,
+       WMI_10_4_END_EVENTID = 0x9FFF,
+       WMI_10_4_SCAN_EVENTID = WMI_10_4_START_EVENTID,
+       WMI_10_4_ECHO_EVENTID,
+       WMI_10_4_UPDATE_STATS_EVENTID,
+       WMI_10_4_INST_RSSI_STATS_EVENTID,
+       WMI_10_4_VDEV_START_RESP_EVENTID,
+       WMI_10_4_VDEV_STANDBY_REQ_EVENTID,
+       WMI_10_4_VDEV_RESUME_REQ_EVENTID,
+       WMI_10_4_VDEV_STOPPED_EVENTID,
+       WMI_10_4_PEER_STA_KICKOUT_EVENTID,
+       WMI_10_4_HOST_SWBA_EVENTID,
+       WMI_10_4_TBTTOFFSET_UPDATE_EVENTID,
+       WMI_10_4_MGMT_RX_EVENTID,
+       WMI_10_4_CHAN_INFO_EVENTID,
+       WMI_10_4_PHYERR_EVENTID,
+       WMI_10_4_ROAM_EVENTID,
+       WMI_10_4_PROFILE_MATCH,
+       WMI_10_4_DEBUG_PRINT_EVENTID,
+       WMI_10_4_PDEV_QVIT_EVENTID,
+       WMI_10_4_WLAN_PROFILE_DATA_EVENTID,
+       WMI_10_4_RTT_MEASUREMENT_REPORT_EVENTID,
+       WMI_10_4_TSF_MEASUREMENT_REPORT_EVENTID,
+       WMI_10_4_RTT_ERROR_REPORT_EVENTID,
+       WMI_10_4_RTT_KEEPALIVE_EVENTID,
+       WMI_10_4_OEM_CAPABILITY_EVENTID,
+       WMI_10_4_OEM_MEASUREMENT_REPORT_EVENTID,
+       WMI_10_4_OEM_ERROR_REPORT_EVENTID,
+       WMI_10_4_NAN_EVENTID,
+       WMI_10_4_WOW_WAKEUP_HOST_EVENTID,
+       WMI_10_4_GTK_OFFLOAD_STATUS_EVENTID,
+       WMI_10_4_GTK_REKEY_FAIL_EVENTID,
+       WMI_10_4_DCS_INTERFERENCE_EVENTID,
+       WMI_10_4_PDEV_TPC_CONFIG_EVENTID,
+       WMI_10_4_CSA_HANDLING_EVENTID,
+       WMI_10_4_GPIO_INPUT_EVENTID,
+       WMI_10_4_PEER_RATECODE_LIST_EVENTID,
+       WMI_10_4_GENERIC_BUFFER_EVENTID,
+       WMI_10_4_MCAST_BUF_RELEASE_EVENTID,
+       WMI_10_4_MCAST_LIST_AGEOUT_EVENTID,
+       WMI_10_4_VDEV_GET_KEEPALIVE_EVENTID,
+       WMI_10_4_WDS_PEER_EVENTID,
+       WMI_10_4_PEER_STA_PS_STATECHG_EVENTID,
+       WMI_10_4_PDEV_FIPS_EVENTID,
+       WMI_10_4_TT_STATS_EVENTID,
+       WMI_10_4_PDEV_CHANNEL_HOPPING_EVENTID,
+       WMI_10_4_PDEV_ANI_CCK_LEVEL_EVENTID,
+       WMI_10_4_PDEV_ANI_OFDM_LEVEL_EVENTID,
+       WMI_10_4_PDEV_RESERVE_AST_ENTRY_EVENTID,
+       WMI_10_4_PDEV_NFCAL_POWER_EVENTID,
+       WMI_10_4_PDEV_TPC_EVENTID,
+       WMI_10_4_PDEV_GET_AST_INFO_EVENTID,
+       WMI_10_4_PDEV_TEMPERATURE_EVENTID,
+       WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID,
+       WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID,
+       WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
+};
+
 enum wmi_phy_mode {
        MODE_11A        = 0,   /* 11a Mode */
        MODE_11G        = 1,   /* 11b/g Mode */
@@ -1349,7 +1747,8 @@ enum wmi_channel_change_cause {
 /* Indicate reason for channel switch */
 #define WMI_CHANNEL_CHANGE_CAUSE_CSA (1 << 13)
 
-#define WMI_MAX_SPATIAL_STREAM   3
+#define WMI_MAX_SPATIAL_STREAM        3 /* default max ss */
+#define WMI_10_4_MAX_SPATIAL_STREAM   4
 
 /* HT Capabilities*/
 #define WMI_HT_CAP_ENABLED                0x0001   /* HT Enabled/ disabled */
@@ -1979,8 +2378,224 @@ struct wmi_resource_config_10_2 {
        __le32 feature_mask;
 } __packed;
 
-#define NUM_UNITS_IS_NUM_VDEVS   0x1
-#define NUM_UNITS_IS_NUM_PEERS   0x2
+#define NUM_UNITS_IS_NUM_VDEVS         BIT(0)
+#define NUM_UNITS_IS_NUM_PEERS         BIT(1)
+#define NUM_UNITS_IS_NUM_ACTIVE_PEERS  BIT(2)
+
+struct wmi_resource_config_10_4 {
+       /* Number of virtual devices (VAPs) to support */
+       __le32 num_vdevs;
+
+       /* Number of peer nodes to support */
+       __le32 num_peers;
+
+       /* Number of active peer nodes to support */
+       __le32 num_active_peers;
+
+       /* In offload mode, target supports features like WOW, chatter and other
+        * protocol offloads. In order to support them some functionalities like
+        * reorder buffering, PN checking need to be done in target.
+        * This determines maximum number of peers supported by target in
+        * offload mode.
+        */
+       __le32 num_offload_peers;
+
+       /* Number of reorder buffers available for doing target based reorder
+        * Rx reorder buffering
+        */
+       __le32 num_offload_reorder_buffs;
+
+       /* Number of keys per peer */
+       __le32 num_peer_keys;
+
+       /* Total number of TX/RX data TIDs */
+       __le32 num_tids;
+
+       /* Max skid for resolving hash collisions.
+        * The address search table is sparse, so that if two MAC addresses
+        * result in the same hash value, the second of these conflicting
+        * entries can slide to the next index in the address search table,
+        * and use it, if it is unoccupied.  This ast_skid_limit parameter
+        * specifies the upper bound on how many subsequent indices to search
+        * over to find an unoccupied space.
+        */
+       __le32 ast_skid_limit;
+
+       /* The nominal chain mask for transmit.
+        * The chain mask may be modified dynamically, e.g. to operate AP tx
+        * with a reduced number of chains if no clients are associated.
+        * This configuration parameter specifies the nominal chain-mask that
+        * should be used when not operating with a reduced set of tx chains.
+        */
+       __le32 tx_chain_mask;
+
+       /* The nominal chain mask for receive.
+        * The chain mask may be modified dynamically, e.g. for a client to use
+        * a reduced number of chains for receive if the traffic to the client
+        * is low enough that it doesn't require downlink MIMO or antenna
+        * diversity. This configuration parameter specifies the nominal
+        * chain-mask that should be used when not operating with a reduced
+        * set of rx chains.
+        */
+       __le32 rx_chain_mask;
+
+       /* What rx reorder timeout (ms) to use for the AC.
+        * Each WMM access class (voice, video, best-effort, background) will
+        * have its own timeout value to dictate how long to wait for missing
+        * rx MPDUs to arrive before flushing subsequent MPDUs that have already
+        * been received. This parameter specifies the timeout in milliseconds
+        * for each class.
+        */
+       __le32 rx_timeout_pri[4];
+
+       /* What mode the rx should decap packets to.
+        * MAC can decap to RAW (no decap), native wifi or Ethernet types.
+        * This setting also determines the default TX behavior, however TX
+        * behavior can be modified on a per VAP basis during VAP init
+        */
+       __le32 rx_decap_mode;
+
+       __le32 scan_max_pending_req;
+
+       __le32 bmiss_offload_max_vdev;
+
+       __le32 roam_offload_max_vdev;
+
+       __le32 roam_offload_max_ap_profiles;
+
+       /* How many groups to use for mcast->ucast conversion.
+        * The target's WAL maintains a table to hold information regarding
+        * which peers belong to a given multicast group, so that if
+        * multicast->unicast conversion is enabled, the target can convert
+        * multicast tx frames to a series of unicast tx frames, to each peer
+        * within the multicast group. This num_mcast_groups configuration
+        * parameter tells the target how many multicast groups to provide
+        * storage for within its multicast group membership table.
+        */
+       __le32 num_mcast_groups;
+
+       /* Size to alloc for the mcast membership table.
+        * This num_mcast_table_elems configuration parameter tells the target
+        * how many peer elements it needs to provide storage for in its
+        * multicast group membership table. These multicast group membership
+        * table elements are shared by the multicast groups stored within
+        * the table.
+        */
+       __le32 num_mcast_table_elems;
+
+       /* Whether/how to do multicast->unicast conversion.
+        * This configuration parameter specifies whether the target should
+        * perform multicast --> unicast conversion on transmit, and if so,
+        * what to do if it finds no entries in its multicast group membership
+        * table for the multicast IP address in the tx frame.
+        * Configuration value:
+        * 0 -> Do not perform multicast to unicast conversion.
+        * 1 -> Convert multicast frames to unicast, if the IP multicast address
+        *      from the tx frame is found in the multicast group membership
+        *      table.  If the IP multicast address is not found, drop the frame
+        * 2 -> Convert multicast frames to unicast, if the IP multicast address
+        *      from the tx frame is found in the multicast group membership
+        *      table.  If the IP multicast address is not found, transmit the
+        *      frame as multicast.
+        */
+       __le32 mcast2ucast_mode;
+
+       /* How much memory to allocate for a tx PPDU dbg log.
+        * This parameter controls how much memory the target will allocate to
+        * store a log of tx PPDU meta-information (how large the PPDU was,
+        * when it was sent, whether it was successful, etc.)
+        */
+       __le32 tx_dbg_log_size;
+
+       /* How many AST entries to be allocated for WDS */
+       __le32 num_wds_entries;
+
+       /* MAC DMA burst size. 0 -default, 1 -256B */
+       __le32 dma_burst_size;
+
+       /* Fixed delimiters to be inserted after every MPDU to account for
+        * interface latency to avoid underrun.
+        */
+       __le32 mac_aggr_delim;
+
+       /* Determine whether target is responsible for detecting duplicate
+        * non-aggregate MPDU and timing out stale fragments. A-MPDU reordering
+        * is always performed on the target.
+        *
+        * 0: target responsible for frag timeout and dup checking
+        * 1: host responsible for frag timeout and dup checking
+        */
+       __le32 rx_skip_defrag_timeout_dup_detection_check;
+
+       /* Configuration for VoW : No of Video nodes to be supported and max
+        * no of descriptors for each video link (node).
+        */
+       __le32 vow_config;
+
+       /* Maximum vdev that could use gtk offload */
+       __le32 gtk_offload_max_vdev;
+
+       /* Number of msdu descriptors target should use */
+       __le32 num_msdu_desc;
+
+       /* Max number of tx fragments per MSDU.
+        * This parameter controls the max number of tx fragments per MSDU.
+        * This will passed by target as part of the WMI_SERVICE_READY event
+        * and is overridden by the OS shim as required.
+        */
+       __le32 max_frag_entries;
+
+       /* Max number of extended peer stats.
+        * This parameter controls the max number of peers for which extended
+        * statistics are supported by target
+        */
+       __le32 max_peer_ext_stats;
+
+       /* Smart antenna capabilities information.
+        * 1 - Smart antenna is enabled
+        * 0 - Smart antenna is disabled
+        * In future this can contain smart antenna specific capabilities.
+        */
+       __le32 smart_ant_cap;
+
+       /* User can configure the buffers allocated for each AC (BE, BK, VI, VO)
+        * during init.
+        */
+       __le32 bk_minfree;
+       __le32 be_minfree;
+       __le32 vi_minfree;
+       __le32 vo_minfree;
+
+       /* Rx batch mode capability.
+        * 1 - Rx batch mode enabled
+        * 0 - Rx batch mode disabled
+        */
+       __le32 rx_batchmode;
+
+       /* Thermal throttling capability.
+        * 1 - Capable of thermal throttling
+        * 0 - Not capable of thermal throttling
+        */
+       __le32 tt_support;
+
+       /* ATF configuration.
+        * 1  - Enable ATF
+        * 0  - Disable ATF
+        */
+       __le32 atf_config;
+
+       /* Configure padding to manage IP header un-alignment
+        * 1  - Enable padding
+        * 0  - Disable padding
+        */
+       __le32 iphdr_pad_config;
+
+       /* qwrap configuration
+        * 1  - This is qwrap configuration
+        * 0  - This is not qwrap
+        */
+       __le32 qwrap_config;
+} __packed;
 
 /* strucutre describing host memory chunk. */
 struct host_memory_chunk {
@@ -2014,6 +2629,11 @@ struct wmi_init_cmd_10_2 {
        struct wmi_host_mem_chunks mem_chunks;
 } __packed;
 
+struct wmi_init_cmd_10_4 {
+       struct wmi_resource_config_10_4 resource_config;
+       struct wmi_host_mem_chunks mem_chunks;
+} __packed;
+
 struct wmi_chan_list_entry {
        __le16 freq;
        u8 phy_mode; /* valid for 10.2 only */
@@ -2260,15 +2880,17 @@ enum wmi_bss_filter {
 };
 
 enum wmi_scan_event_type {
-       WMI_SCAN_EVENT_STARTED         = 0x1,
-       WMI_SCAN_EVENT_COMPLETED       = 0x2,
-       WMI_SCAN_EVENT_BSS_CHANNEL     = 0x4,
-       WMI_SCAN_EVENT_FOREIGN_CHANNEL = 0x8,
-       WMI_SCAN_EVENT_DEQUEUED        = 0x10,
-       WMI_SCAN_EVENT_PREEMPTED       = 0x20, /* possibly by high-prio scan */
-       WMI_SCAN_EVENT_START_FAILED    = 0x40,
-       WMI_SCAN_EVENT_RESTARTED       = 0x80,
-       WMI_SCAN_EVENT_MAX             = 0x8000
+       WMI_SCAN_EVENT_STARTED              = BIT(0),
+       WMI_SCAN_EVENT_COMPLETED            = BIT(1),
+       WMI_SCAN_EVENT_BSS_CHANNEL          = BIT(2),
+       WMI_SCAN_EVENT_FOREIGN_CHANNEL      = BIT(3),
+       WMI_SCAN_EVENT_DEQUEUED             = BIT(4),
+       /* possibly by high-prio scan */
+       WMI_SCAN_EVENT_PREEMPTED            = BIT(5),
+       WMI_SCAN_EVENT_START_FAILED         = BIT(6),
+       WMI_SCAN_EVENT_RESTARTED            = BIT(7),
+       WMI_SCAN_EVENT_FOREIGN_CHANNEL_EXIT = BIT(8),
+       WMI_SCAN_EVENT_MAX                  = BIT(15),
 };
 
 enum wmi_scan_completion_reason {
@@ -2276,6 +2898,7 @@ enum wmi_scan_completion_reason {
        WMI_SCAN_REASON_CANCELLED,
        WMI_SCAN_REASON_PREEMPTED,
        WMI_SCAN_REASON_TIMEDOUT,
+       WMI_SCAN_REASON_INTERNAL_FAILURE,
        WMI_SCAN_REASON_MAX,
 };
 
@@ -2329,6 +2952,21 @@ struct wmi_mgmt_rx_event_v2 {
        u8 buf[0];
 } __packed;
 
+struct wmi_10_4_mgmt_rx_hdr {
+       __le32 channel;
+       __le32 snr;
+           u8 rssi_ctl[4];
+       __le32 rate;
+       __le32 phy_mode;
+       __le32 buf_len;
+       __le32 status;
+} __packed;
+
+struct wmi_10_4_mgmt_rx_event {
+       struct wmi_10_4_mgmt_rx_hdr hdr;
+       u8 buf[0];
+} __packed;
+
 #define WMI_RX_STATUS_OK                       0x00
 #define WMI_RX_STATUS_ERR_CRC                  0x01
 #define WMI_RX_STATUS_ERR_DECRYPT              0x08
@@ -2613,6 +3251,48 @@ struct wmi_pdev_param_map {
        u32 burst_dur;
        u32 burst_enable;
        u32 cal_period;
+       u32 aggr_burst;
+       u32 rx_decap_mode;
+       u32 smart_antenna_default_antenna;
+       u32 igmpmld_override;
+       u32 igmpmld_tid;
+       u32 antenna_gain;
+       u32 rx_filter;
+       u32 set_mcast_to_ucast_tid;
+       u32 proxy_sta_mode;
+       u32 set_mcast2ucast_mode;
+       u32 set_mcast2ucast_buffer;
+       u32 remove_mcast2ucast_buffer;
+       u32 peer_sta_ps_statechg_enable;
+       u32 igmpmld_ac_override;
+       u32 block_interbss;
+       u32 set_disable_reset_cmdid;
+       u32 set_msdu_ttl_cmdid;
+       u32 set_ppdu_duration_cmdid;
+       u32 txbf_sound_period_cmdid;
+       u32 set_promisc_mode_cmdid;
+       u32 set_burst_mode_cmdid;
+       u32 en_stats;
+       u32 mu_group_policy;
+       u32 noise_detection;
+       u32 noise_threshold;
+       u32 dpd_enable;
+       u32 set_mcast_bcast_echo;
+       u32 atf_strict_sch;
+       u32 atf_sched_duration;
+       u32 ant_plzn;
+       u32 mgmt_retry_limit;
+       u32 sensitivity_level;
+       u32 signed_txpower_2g;
+       u32 signed_txpower_5g;
+       u32 enable_per_tid_amsdu;
+       u32 enable_per_tid_ampdu;
+       u32 cca_threshold;
+       u32 rts_fixed_rate;
+       u32 pdev_reset;
+       u32 wapi_mbssid_offset;
+       u32 arp_srcaddr;
+       u32 arp_dstaddr;
 };
 
 #define WMI_PDEV_PARAM_UNSUPPORTED 0
@@ -2828,6 +3508,100 @@ enum wmi_10x_pdev_param {
        WMI_10X_PDEV_PARAM_CAL_PERIOD
 };
 
+enum wmi_10_4_pdev_param {
+       WMI_10_4_PDEV_PARAM_TX_CHAIN_MASK = 0x1,
+       WMI_10_4_PDEV_PARAM_RX_CHAIN_MASK,
+       WMI_10_4_PDEV_PARAM_TXPOWER_LIMIT2G,
+       WMI_10_4_PDEV_PARAM_TXPOWER_LIMIT5G,
+       WMI_10_4_PDEV_PARAM_TXPOWER_SCALE,
+       WMI_10_4_PDEV_PARAM_BEACON_GEN_MODE,
+       WMI_10_4_PDEV_PARAM_BEACON_TX_MODE,
+       WMI_10_4_PDEV_PARAM_RESMGR_OFFCHAN_MODE,
+       WMI_10_4_PDEV_PARAM_PROTECTION_MODE,
+       WMI_10_4_PDEV_PARAM_DYNAMIC_BW,
+       WMI_10_4_PDEV_PARAM_NON_AGG_SW_RETRY_TH,
+       WMI_10_4_PDEV_PARAM_AGG_SW_RETRY_TH,
+       WMI_10_4_PDEV_PARAM_STA_KICKOUT_TH,
+       WMI_10_4_PDEV_PARAM_AC_AGGRSIZE_SCALING,
+       WMI_10_4_PDEV_PARAM_LTR_ENABLE,
+       WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_BE,
+       WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_BK,
+       WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_VI,
+       WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_VO,
+       WMI_10_4_PDEV_PARAM_LTR_AC_LATENCY_TIMEOUT,
+       WMI_10_4_PDEV_PARAM_LTR_SLEEP_OVERRIDE,
+       WMI_10_4_PDEV_PARAM_LTR_RX_OVERRIDE,
+       WMI_10_4_PDEV_PARAM_LTR_TX_ACTIVITY_TIMEOUT,
+       WMI_10_4_PDEV_PARAM_L1SS_ENABLE,
+       WMI_10_4_PDEV_PARAM_DSLEEP_ENABLE,
+       WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_FLUSH,
+       WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_WATERMARK,
+       WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_TMO_EN,
+       WMI_10_4_PDEV_PARAM_PCIELP_TXBUF_TMO_VALUE,
+       WMI_10_4_PDEV_PARAM_PDEV_STATS_UPDATE_PERIOD,
+       WMI_10_4_PDEV_PARAM_VDEV_STATS_UPDATE_PERIOD,
+       WMI_10_4_PDEV_PARAM_PEER_STATS_UPDATE_PERIOD,
+       WMI_10_4_PDEV_PARAM_BCNFLT_STATS_UPDATE_PERIOD,
+       WMI_10_4_PDEV_PARAM_PMF_QOS,
+       WMI_10_4_PDEV_PARAM_ARP_AC_OVERRIDE,
+       WMI_10_4_PDEV_PARAM_DCS,
+       WMI_10_4_PDEV_PARAM_ANI_ENABLE,
+       WMI_10_4_PDEV_PARAM_ANI_POLL_PERIOD,
+       WMI_10_4_PDEV_PARAM_ANI_LISTEN_PERIOD,
+       WMI_10_4_PDEV_PARAM_ANI_OFDM_LEVEL,
+       WMI_10_4_PDEV_PARAM_ANI_CCK_LEVEL,
+       WMI_10_4_PDEV_PARAM_DYNTXCHAIN,
+       WMI_10_4_PDEV_PARAM_PROXY_STA,
+       WMI_10_4_PDEV_PARAM_IDLE_PS_CONFIG,
+       WMI_10_4_PDEV_PARAM_POWER_GATING_SLEEP,
+       WMI_10_4_PDEV_PARAM_AGGR_BURST,
+       WMI_10_4_PDEV_PARAM_RX_DECAP_MODE,
+       WMI_10_4_PDEV_PARAM_FAST_CHANNEL_RESET,
+       WMI_10_4_PDEV_PARAM_BURST_DUR,
+       WMI_10_4_PDEV_PARAM_BURST_ENABLE,
+       WMI_10_4_PDEV_PARAM_SMART_ANTENNA_DEFAULT_ANTENNA,
+       WMI_10_4_PDEV_PARAM_IGMPMLD_OVERRIDE,
+       WMI_10_4_PDEV_PARAM_IGMPMLD_TID,
+       WMI_10_4_PDEV_PARAM_ANTENNA_GAIN,
+       WMI_10_4_PDEV_PARAM_RX_FILTER,
+       WMI_10_4_PDEV_SET_MCAST_TO_UCAST_TID,
+       WMI_10_4_PDEV_PARAM_PROXY_STA_MODE,
+       WMI_10_4_PDEV_PARAM_SET_MCAST2UCAST_MODE,
+       WMI_10_4_PDEV_PARAM_SET_MCAST2UCAST_BUFFER,
+       WMI_10_4_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
+       WMI_10_4_PDEV_PEER_STA_PS_STATECHG_ENABLE,
+       WMI_10_4_PDEV_PARAM_IGMPMLD_AC_OVERRIDE,
+       WMI_10_4_PDEV_PARAM_BLOCK_INTERBSS,
+       WMI_10_4_PDEV_PARAM_SET_DISABLE_RESET_CMDID,
+       WMI_10_4_PDEV_PARAM_SET_MSDU_TTL_CMDID,
+       WMI_10_4_PDEV_PARAM_SET_PPDU_DURATION_CMDID,
+       WMI_10_4_PDEV_PARAM_TXBF_SOUND_PERIOD_CMDID,
+       WMI_10_4_PDEV_PARAM_SET_PROMISC_MODE_CMDID,
+       WMI_10_4_PDEV_PARAM_SET_BURST_MODE_CMDID,
+       WMI_10_4_PDEV_PARAM_EN_STATS,
+       WMI_10_4_PDEV_PARAM_MU_GROUP_POLICY,
+       WMI_10_4_PDEV_PARAM_NOISE_DETECTION,
+       WMI_10_4_PDEV_PARAM_NOISE_THRESHOLD,
+       WMI_10_4_PDEV_PARAM_DPD_ENABLE,
+       WMI_10_4_PDEV_PARAM_SET_MCAST_BCAST_ECHO,
+       WMI_10_4_PDEV_PARAM_ATF_STRICT_SCH,
+       WMI_10_4_PDEV_PARAM_ATF_SCHED_DURATION,
+       WMI_10_4_PDEV_PARAM_ANT_PLZN,
+       WMI_10_4_PDEV_PARAM_MGMT_RETRY_LIMIT,
+       WMI_10_4_PDEV_PARAM_SENSITIVITY_LEVEL,
+       WMI_10_4_PDEV_PARAM_SIGNED_TXPOWER_2G,
+       WMI_10_4_PDEV_PARAM_SIGNED_TXPOWER_5G,
+       WMI_10_4_PDEV_PARAM_ENABLE_PER_TID_AMSDU,
+       WMI_10_4_PDEV_PARAM_ENABLE_PER_TID_AMPDU,
+       WMI_10_4_PDEV_PARAM_CCA_THRESHOLD,
+       WMI_10_4_PDEV_PARAM_RTS_FIXED_RATE,
+       WMI_10_4_PDEV_PARAM_CAL_PERIOD,
+       WMI_10_4_PDEV_PARAM_PDEV_RESET,
+       WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
+       WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+       WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+};
+
 struct wmi_pdev_set_param_cmd {
        __le32 param_id;
        __le32 param_value;
@@ -3506,6 +4280,22 @@ struct wmi_vdev_param_map {
        u32 drop_unencry;
        u32 tx_encap_type;
        u32 ap_detect_out_of_sync_sleeping_sta_time_secs;
+       u32 rc_num_retries;
+       u32 cabq_maxdur;
+       u32 mfptest_set;
+       u32 rts_fixed_rate;
+       u32 vht_sgimask;
+       u32 vht80_ratemask;
+       u32 early_rx_adjust_enable;
+       u32 early_rx_tgt_bmiss_num;
+       u32 early_rx_bmiss_sample_cycle;
+       u32 early_rx_slop_step;
+       u32 early_rx_init_slop;
+       u32 early_rx_adjust_pause;
+       u32 proxy_sta;
+       u32 meru_vc;
+       u32 rx_decap_type;
+       u32 bw_nss_ratemask;
 };
 
 #define WMI_VDEV_PARAM_UNSUPPORTED 0
@@ -3764,6 +4554,75 @@ enum wmi_10x_vdev_param {
        WMI_10X_VDEV_PARAM_VHT80_RATEMASK,
 };
 
+enum wmi_10_4_vdev_param {
+       WMI_10_4_VDEV_PARAM_RTS_THRESHOLD = 0x1,
+       WMI_10_4_VDEV_PARAM_FRAGMENTATION_THRESHOLD,
+       WMI_10_4_VDEV_PARAM_BEACON_INTERVAL,
+       WMI_10_4_VDEV_PARAM_LISTEN_INTERVAL,
+       WMI_10_4_VDEV_PARAM_MULTICAST_RATE,
+       WMI_10_4_VDEV_PARAM_MGMT_TX_RATE,
+       WMI_10_4_VDEV_PARAM_SLOT_TIME,
+       WMI_10_4_VDEV_PARAM_PREAMBLE,
+       WMI_10_4_VDEV_PARAM_SWBA_TIME,
+       WMI_10_4_VDEV_STATS_UPDATE_PERIOD,
+       WMI_10_4_VDEV_PWRSAVE_AGEOUT_TIME,
+       WMI_10_4_VDEV_HOST_SWBA_INTERVAL,
+       WMI_10_4_VDEV_PARAM_DTIM_PERIOD,
+       WMI_10_4_VDEV_OC_SCHEDULER_AIR_TIME_LIMIT,
+       WMI_10_4_VDEV_PARAM_WDS,
+       WMI_10_4_VDEV_PARAM_ATIM_WINDOW,
+       WMI_10_4_VDEV_PARAM_BMISS_COUNT_MAX,
+       WMI_10_4_VDEV_PARAM_BMISS_FIRST_BCNT,
+       WMI_10_4_VDEV_PARAM_BMISS_FINAL_BCNT,
+       WMI_10_4_VDEV_PARAM_FEATURE_WMM,
+       WMI_10_4_VDEV_PARAM_CHWIDTH,
+       WMI_10_4_VDEV_PARAM_CHEXTOFFSET,
+       WMI_10_4_VDEV_PARAM_DISABLE_HTPROTECTION,
+       WMI_10_4_VDEV_PARAM_STA_QUICKKICKOUT,
+       WMI_10_4_VDEV_PARAM_MGMT_RATE,
+       WMI_10_4_VDEV_PARAM_PROTECTION_MODE,
+       WMI_10_4_VDEV_PARAM_FIXED_RATE,
+       WMI_10_4_VDEV_PARAM_SGI,
+       WMI_10_4_VDEV_PARAM_LDPC,
+       WMI_10_4_VDEV_PARAM_TX_STBC,
+       WMI_10_4_VDEV_PARAM_RX_STBC,
+       WMI_10_4_VDEV_PARAM_INTRA_BSS_FWD,
+       WMI_10_4_VDEV_PARAM_DEF_KEYID,
+       WMI_10_4_VDEV_PARAM_NSS,
+       WMI_10_4_VDEV_PARAM_BCAST_DATA_RATE,
+       WMI_10_4_VDEV_PARAM_MCAST_DATA_RATE,
+       WMI_10_4_VDEV_PARAM_MCAST_INDICATE,
+       WMI_10_4_VDEV_PARAM_DHCP_INDICATE,
+       WMI_10_4_VDEV_PARAM_UNKNOWN_DEST_INDICATE,
+       WMI_10_4_VDEV_PARAM_AP_KEEPALIVE_MIN_IDLE_INACTIVE_TIME_SECS,
+       WMI_10_4_VDEV_PARAM_AP_KEEPALIVE_MAX_IDLE_INACTIVE_TIME_SECS,
+       WMI_10_4_VDEV_PARAM_AP_KEEPALIVE_MAX_UNRESPONSIVE_TIME_SECS,
+       WMI_10_4_VDEV_PARAM_AP_ENABLE_NAWDS,
+       WMI_10_4_VDEV_PARAM_MCAST2UCAST_SET,
+       WMI_10_4_VDEV_PARAM_ENABLE_RTSCTS,
+       WMI_10_4_VDEV_PARAM_RC_NUM_RETRIES,
+       WMI_10_4_VDEV_PARAM_TXBF,
+       WMI_10_4_VDEV_PARAM_PACKET_POWERSAVE,
+       WMI_10_4_VDEV_PARAM_DROP_UNENCRY,
+       WMI_10_4_VDEV_PARAM_TX_ENCAP_TYPE,
+       WMI_10_4_VDEV_PARAM_AP_DETECT_OUT_OF_SYNC_SLEEPING_STA_TIME_SECS,
+       WMI_10_4_VDEV_PARAM_CABQ_MAXDUR,
+       WMI_10_4_VDEV_PARAM_MFPTEST_SET,
+       WMI_10_4_VDEV_PARAM_RTS_FIXED_RATE,
+       WMI_10_4_VDEV_PARAM_VHT_SGIMASK,
+       WMI_10_4_VDEV_PARAM_VHT80_RATEMASK,
+       WMI_10_4_VDEV_PARAM_EARLY_RX_ADJUST_ENABLE,
+       WMI_10_4_VDEV_PARAM_EARLY_RX_TGT_BMISS_NUM,
+       WMI_10_4_VDEV_PARAM_EARLY_RX_BMISS_SAMPLE_CYCLE,
+       WMI_10_4_VDEV_PARAM_EARLY_RX_SLOP_STEP,
+       WMI_10_4_VDEV_PARAM_EARLY_RX_INIT_SLOP,
+       WMI_10_4_VDEV_PARAM_EARLY_RX_ADJUST_PAUSE,
+       WMI_10_4_VDEV_PARAM_PROXY_STA,
+       WMI_10_4_VDEV_PARAM_MERU_VC,
+       WMI_10_4_VDEV_PARAM_RX_DECAP_TYPE,
+       WMI_10_4_VDEV_PARAM_BW_NSS_RATEMASK,
+};
+
 #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0)
 #define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1)
 #define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
@@ -4305,6 +5164,14 @@ struct wmi_tim_info {
        __le32 tim_num_ps_pending;
 } __packed;
 
+struct wmi_tim_info_arg {
+       __le32 tim_len;
+       __le32 tim_mcast;
+       const __le32 *tim_bitmap;
+       __le32 tim_changed;
+       __le32 tim_num_ps_pending;
+} __packed;
+
 /* Maximum number of NOA Descriptors supported */
 #define WMI_P2P_MAX_NOA_DESCRIPTORS 4
 #define WMI_P2P_OPPPS_ENABLE_BIT       BIT(0)
@@ -4336,6 +5203,47 @@ struct wmi_host_swba_event {
        struct wmi_bcn_info bcn_info[0];
 } __packed;
 
+/* 16 words = 512 client + 1 word = for guard */
+#define WMI_10_4_TIM_BITMAP_ARRAY_SIZE 17
+
+struct wmi_10_4_tim_info {
+       __le32 tim_len;
+       __le32 tim_mcast;
+       __le32 tim_bitmap[WMI_10_4_TIM_BITMAP_ARRAY_SIZE];
+       __le32 tim_changed;
+       __le32 tim_num_ps_pending;
+} __packed;
+
+#define WMI_10_4_P2P_MAX_NOA_DESCRIPTORS 1
+
+struct wmi_10_4_p2p_noa_info {
+       /* Bit 0 - Flag to indicate an update in NOA schedule
+        * Bits 7-1 - Reserved
+        */
+       u8 changed;
+       /* NOA index */
+       u8 index;
+       /* Bit 0 - Opp PS state of the AP
+        * Bits 1-7 - Ctwindow in TUs
+        */
+       u8 ctwindow_oppps;
+       /* Number of NOA descriptors */
+       u8 num_descriptors;
+
+       struct wmi_p2p_noa_descriptor
+               noa_descriptors[WMI_10_4_P2P_MAX_NOA_DESCRIPTORS];
+} __packed;
+
+struct wmi_10_4_bcn_info {
+       struct wmi_10_4_tim_info tim_info;
+       struct wmi_10_4_p2p_noa_info p2p_noa_info;
+} __packed;
+
+struct wmi_10_4_host_swba_event {
+       __le32 vdev_map;
+       struct wmi_10_4_bcn_info bcn_info[0];
+} __packed;
+
 #define WMI_MAX_AP_VDEV 16
 
 struct wmi_tbtt_offset_event {
@@ -4660,6 +5568,18 @@ struct wmi_chan_info_event {
        __le32 cycle_count;
 } __packed;
 
+struct wmi_10_4_chan_info_event {
+       __le32 err_code;
+       __le32 freq;
+       __le32 cmd_flags;
+       __le32 noise_floor;
+       __le32 rx_clear_count;
+       __le32 cycle_count;
+       __le32 chan_tx_pwr_range;
+       __le32 chan_tx_pwr_tp;
+       __le32 rx_frame_count;
+} __packed;
+
 struct wmi_peer_sta_kickout_event {
        struct wmi_mac_addr peer_macaddr;
 } __packed;
@@ -4840,6 +5760,9 @@ struct wmi_ch_info_ev_arg {
        __le32 noise_floor;
        __le32 rx_clear_count;
        __le32 cycle_count;
+       __le32 chan_tx_pwr_range;
+       __le32 chan_tx_pwr_tp;
+       __le32 rx_frame_count;
 };
 
 struct wmi_vdev_start_ev_arg {
@@ -4855,7 +5778,7 @@ struct wmi_peer_kick_ev_arg {
 
 struct wmi_swba_ev_arg {
        __le32 vdev_map;
-       const struct wmi_tim_info *tim_info[WMI_MAX_AP_VDEV];
+       struct wmi_tim_info_arg tim_info[WMI_MAX_AP_VDEV];
        const struct wmi_p2p_noa_info *noa_info[WMI_MAX_AP_VDEV];
 };
 
index fc595b92ac56007a024bc9cb5d871e19cef4ba9c..c5f8bc4b5595ecda04fcb7b130f68180c6d74791 100644 (file)
 #define AR_PHY_MODE              (AR_SM_BASE + 0x8)
 #define AR_PHY_ACTIVE            (AR_SM_BASE + 0xc)
 #define AR_PHY_SPUR_MASK_A       (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x18 : 0x20))
-#define AR_PHY_SPUR_MASK_B       (AR_SM_BASE + 0x24)
+#define AR_PHY_SPUR_MASK_B       (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x1c : 0x24))
 #define AR_PHY_SPECTRAL_SCAN     (AR_SM_BASE + 0x28)
 #define AR_PHY_RADAR_BW_FILTER   (AR_SM_BASE + 0x2c)
 #define AR_PHY_SEARCH_START_DELAY (AR_SM_BASE + 0x30)
 #define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A                       0x3FF
 #define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A_S                     0
 
-#define AR_PHY_TEST              (AR_SM_BASE + 0x160)
+#define AR_PHY_TEST              (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x15c : 0x160))
 
 #define AR_PHY_TEST_BBB_OBS_SEL       0x780000
 #define AR_PHY_TEST_BBB_OBS_SEL_S     19
 #define AR_PHY_TEST_CTL_DEBUGPORT_SEL_S          29
 
 
-#define AR_PHY_TSTDAC            (AR_SM_BASE + 0x168)
+#define AR_PHY_TSTDAC            (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x164 : 0x168))
 
-#define AR_PHY_CHAN_STATUS       (AR_SM_BASE + 0x16c)
+#define AR_PHY_CHAN_STATUS       (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x168 : 0x16c))
 
 #define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x16c : 0x170))
 #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ    0x00000008
 #define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S  3
 
-#define AR_PHY_CHNINFO_NOISEPWR  (AR_SM_BASE + 0x174)
-#define AR_PHY_CHNINFO_GAINDIFF  (AR_SM_BASE + 0x178)
-#define AR_PHY_CHNINFO_FINETIM   (AR_SM_BASE + 0x17c)
-#define AR_PHY_CHAN_INFO_GAIN_0  (AR_SM_BASE + 0x180)
-#define AR_PHY_SCRAMBLER_SEED    (AR_SM_BASE + 0x190)
-#define AR_PHY_CCK_TX_CTRL       (AR_SM_BASE + 0x194)
+#define AR_PHY_CHNINFO_NOISEPWR  (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x170 : 0x174))
+#define AR_PHY_CHNINFO_GAINDIFF  (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x174 : 0x178))
+#define AR_PHY_CHNINFO_FINETIM   (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x178 : 0x17c))
+#define AR_PHY_CHAN_INFO_GAIN_0  (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x17c : 0x180))
+#define AR_PHY_SCRAMBLER_SEED    (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x184 : 0x190))
+#define AR_PHY_CCK_TX_CTRL       (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x188 : 0x194))
 
 #define AR_PHY_HEAVYCLIP_CTL     (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x198 : 0x1a4))
 #define AR_PHY_HEAVYCLIP_20      (AR_SM_BASE + 0x1a8)
 #define AR_PHY_HEAVYCLIP_40      (AR_SM_BASE + 0x1ac)
+#define AR_PHY_HEAVYCLIP_1      (AR_SM_BASE + 0x19c)
+#define AR_PHY_HEAVYCLIP_2      (AR_SM_BASE + 0x1a0)
+#define AR_PHY_HEAVYCLIP_3      (AR_SM_BASE + 0x1a4)
+#define AR_PHY_HEAVYCLIP_4      (AR_SM_BASE + 0x1a8)
+#define AR_PHY_HEAVYCLIP_5      (AR_SM_BASE + 0x1ac)
 #define AR_PHY_ILLEGAL_TXRATE    (AR_SM_BASE + 0x1b0)
 
 #define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2))
index dbf8f495964217e1b5799fb165155ff3c88b4894..da32c8faad94f1b58f2157c046e5db1bdb04f6f3 100644 (file)
@@ -765,6 +765,8 @@ static int read_file_reset(struct seq_file *file, void *data)
                [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
                [RESET_TYPE_MCI] = "MCI Reset",
                [RESET_TYPE_CALIBRATION] = "Calibration error",
+               [RESET_TX_DMA_ERROR] = "Tx DMA stop error",
+               [RESET_RX_DMA_ERROR] = "Rx DMA stop error",
        };
        int i;
 
index a8e9319958e6eca7a645610c24c6b46adc142f3b..cd68c5f0e751a57ed6341e56d710234f92b0f5db 100644 (file)
@@ -50,6 +50,8 @@ enum ath_reset_type {
        RESET_TYPE_BEACON_STUCK,
        RESET_TYPE_MCI,
        RESET_TYPE_CALIBRATION,
+       RESET_TX_DMA_ERROR,
+       RESET_RX_DMA_ERROR,
        __RESET_TYPE_MAX
 };
 
index e98a9eaba7ff3f1b84a85945e63e901c8a216207..1ece42c2443d79e3d73e999b0ff5a6edb8b08fc7 100644 (file)
@@ -30,6 +30,157 @@ struct ath_radar_data {
        u8 pulse_length_pri;
 };
 
+/**** begin: CHIRP ************************************************************/
+
+/* min and max gradients for defined FCC chirping pulses, given by
+ * - 20MHz chirp width over a pulse width of  50us
+ * -  5MHz chirp width over a pulse width of 100us
+ */
+static const int BIN_DELTA_MIN         = 1;
+static const int BIN_DELTA_MAX         = 10;
+
+/* we need at least 3 deltas / 4 samples for a reliable chirp detection */
+#define NUM_DIFFS 3
+static const int FFT_NUM_SAMPLES       = (NUM_DIFFS + 1);
+
+/* Threshold for difference of delta peaks */
+static const int MAX_DIFF              = 2;
+
+/* width range to be checked for chirping */
+static const int MIN_CHIRP_PULSE_WIDTH = 20;
+static const int MAX_CHIRP_PULSE_WIDTH = 110;
+
+struct ath9k_dfs_fft_20 {
+       u8 bin[28];
+       u8 lower_bins[3];
+} __packed;
+struct ath9k_dfs_fft_40 {
+       u8 bin[64];
+       u8 lower_bins[3];
+       u8 upper_bins[3];
+} __packed;
+
+static inline int fft_max_index(u8 *bins)
+{
+       return (bins[2] & 0xfc) >> 2;
+}
+static inline int fft_max_magnitude(u8 *bins)
+{
+       return (bins[0] & 0xc0) >> 6 | bins[1] << 2 | (bins[2] & 0x03) << 10;
+}
+static inline u8 fft_bitmap_weight(u8 *bins)
+{
+       return bins[0] & 0x3f;
+}
+
+static int ath9k_get_max_index_ht40(struct ath9k_dfs_fft_40 *fft,
+                                   bool is_ctl, bool is_ext)
+{
+       const int DFS_UPPER_BIN_OFFSET = 64;
+       /* if detected radar on both channels, select the significant one */
+       if (is_ctl && is_ext) {
+               /* first check wether channels have 'strong' bins */
+               is_ctl = fft_bitmap_weight(fft->lower_bins) != 0;
+               is_ext = fft_bitmap_weight(fft->upper_bins) != 0;
+
+               /* if still unclear, take higher magnitude */
+               if (is_ctl && is_ext) {
+                       int mag_lower = fft_max_magnitude(fft->lower_bins);
+                       int mag_upper = fft_max_magnitude(fft->upper_bins);
+                       if (mag_upper > mag_lower)
+                               is_ctl = false;
+                       else
+                               is_ext = false;
+               }
+       }
+       if (is_ctl)
+               return fft_max_index(fft->lower_bins);
+       return fft_max_index(fft->upper_bins) + DFS_UPPER_BIN_OFFSET;
+}
+static bool ath9k_check_chirping(struct ath_softc *sc, u8 *data,
+                                int datalen, bool is_ctl, bool is_ext)
+{
+       int i;
+       int max_bin[FFT_NUM_SAMPLES];
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       int prev_delta;
+
+       if (IS_CHAN_HT40(ah->curchan)) {
+               struct ath9k_dfs_fft_40 *fft = (struct ath9k_dfs_fft_40 *) data;
+               int num_fft_packets = datalen / sizeof(*fft);
+               if (num_fft_packets == 0)
+                       return false;
+
+               ath_dbg(common, DFS, "HT40: datalen=%d, num_fft_packets=%d\n",
+                       datalen, num_fft_packets);
+               if (num_fft_packets < (FFT_NUM_SAMPLES)) {
+                       ath_dbg(common, DFS, "not enough packets for chirp\n");
+                       return false;
+               }
+               /* HW sometimes adds 2 garbage bytes in front of FFT samples */
+               if ((datalen % sizeof(*fft)) == 2) {
+                       fft = (struct ath9k_dfs_fft_40 *) (data + 2);
+                       ath_dbg(common, DFS, "fixing datalen by 2\n");
+               }
+               if (IS_CHAN_HT40MINUS(ah->curchan)) {
+                       int temp = is_ctl;
+                       is_ctl = is_ext;
+                       is_ext = temp;
+               }
+               for (i = 0; i < FFT_NUM_SAMPLES; i++)
+                       max_bin[i] = ath9k_get_max_index_ht40(fft + i, is_ctl,
+                                                             is_ext);
+       } else {
+               struct ath9k_dfs_fft_20 *fft = (struct ath9k_dfs_fft_20 *) data;
+               int num_fft_packets = datalen / sizeof(*fft);
+               if (num_fft_packets == 0)
+                       return false;
+               ath_dbg(common, DFS, "HT20: datalen=%d, num_fft_packets=%d\n",
+                       datalen, num_fft_packets);
+               if (num_fft_packets < (FFT_NUM_SAMPLES)) {
+                       ath_dbg(common, DFS, "not enough packets for chirp\n");
+                       return false;
+               }
+               /* in ht20, this is a 6-bit signed number => shift it to 0 */
+               for (i = 0; i < FFT_NUM_SAMPLES; i++)
+                       max_bin[i] = fft_max_index(fft[i].lower_bins) ^ 0x20;
+       }
+       ath_dbg(common, DFS, "bin_max = [%d, %d, %d, %d]\n",
+               max_bin[0], max_bin[1], max_bin[2], max_bin[3]);
+
+       /* Check for chirp attributes within specs
+        * a) delta of adjacent max_bins is within range
+        * b) delta of adjacent deltas are within tolerance
+        */
+       prev_delta = 0;
+       for (i = 0; i < NUM_DIFFS; i++) {
+               int ddelta = -1;
+               int delta = max_bin[i + 1] - max_bin[i];
+
+               /* ensure gradient is within valid range */
+               if (abs(delta) < BIN_DELTA_MIN || abs(delta) > BIN_DELTA_MAX) {
+                       ath_dbg(common, DFS, "CHIRP: invalid delta %d "
+                               "in sample %d\n", delta, i);
+                       return false;
+               }
+               if (i == 0)
+                       goto done;
+               ddelta = delta - prev_delta;
+               if (abs(ddelta) > MAX_DIFF) {
+                       ath_dbg(common, DFS, "CHIRP: ddelta %d too high\n",
+                               ddelta);
+                       return false;
+               }
+done:
+               ath_dbg(common, DFS, "CHIRP - %d: delta=%d, ddelta=%d\n",
+                       i, delta, ddelta);
+               prev_delta = delta;
+       }
+       return true;
+}
+/**** end: CHIRP **************************************************************/
+
 /* convert pulse duration to usecs, considering clock mode */
 static u32 dur_to_usecs(struct ath_hw *ah, u32 dur)
 {
@@ -113,12 +264,6 @@ ath9k_postprocess_radar_event(struct ath_softc *sc,
                return false;
        }
 
-       /*
-        * TODO: check chirping pulses
-        *       checks for chirping are dependent on the DFS regulatory domain
-        *       used, which is yet TBD
-        */
-
        /* convert duration to usecs */
        pe->width = dur_to_usecs(sc->sc_ah, dur);
        pe->rssi = rssi;
@@ -190,6 +335,16 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
        if (!ath9k_postprocess_radar_event(sc, &ard, &pe))
                return;
 
+       if (pe.width > MIN_CHIRP_PULSE_WIDTH &&
+           pe.width < MAX_CHIRP_PULSE_WIDTH) {
+               bool is_ctl = !!(ard.pulse_bw_info & PRI_CH_RADAR_FOUND);
+               bool is_ext = !!(ard.pulse_bw_info & EXT_CH_RADAR_FOUND);
+               int clen = datalen - 3;
+               pe.chirp = ath9k_check_chirping(sc, data, clen, is_ctl, is_ext);
+       } else {
+               pe.chirp = false;
+       }
+
        ath_dbg(common, DFS,
                "ath9k_dfs_process_phyerr: type=%d, freq=%d, ts=%llu, "
                "width=%d, rssi=%d, delta_ts=%llu\n",
@@ -198,7 +353,8 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
        sc->dfs_prev_pulse_ts = pe.ts;
        if (ard.pulse_bw_info & PRI_CH_RADAR_FOUND)
                ath9k_dfs_process_radar_pulse(sc, &pe);
-       if (ard.pulse_bw_info & EXT_CH_RADAR_FOUND) {
+       if (IS_CHAN_HT40(ah->curchan) &&
+           ard.pulse_bw_info & EXT_CH_RADAR_FOUND) {
                pe.freq += IS_CHAN_HT40PLUS(ah->curchan) ? 20 : -20;
                ath9k_dfs_process_radar_pulse(sc, &pe);
        }
index 6c75fb1ab77d45ba8b6dab67a7fe6bb3b1f3dc98..d3189daf99965e6059d1ce407c99600a822ed69f 100644 (file)
@@ -491,10 +491,9 @@ bool ath_stoprecv(struct ath_softc *sc)
 
        if (!(ah->ah_flags & AH_UNPLUGGED) &&
            unlikely(!stopped)) {
-               ath_err(ath9k_hw_common(sc->sc_ah),
-                       "Could not stop RX, we could be "
-                       "confusing the DMA engine when we start RX up\n");
-               ATH_DBG_WARN_ON_ONCE(!stopped);
+               ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
+                       "Failed to stop Rx DMA\n");
+               RESET_STAT_INC(sc, RESET_RX_DMA_ERROR);
        }
        return stopped && !reset;
 }
index 3ad79bb4f2c21c94b6c41c526a7e033e0937ed77..b766a7fc60aaa051a519ed18830444322e98d4b3 100644 (file)
@@ -1883,8 +1883,11 @@ bool ath_drain_all_txq(struct ath_softc *sc)
                        npend |= BIT(i);
        }
 
-       if (npend)
-               ath_err(common, "Failed to stop TX DMA, queues=0x%03x!\n", npend);
+       if (npend) {
+               RESET_STAT_INC(sc, RESET_TX_DMA_ERROR);
+               ath_dbg(common, RESET,
+                       "Failed to stop TX DMA, queues=0x%03x!\n", npend);
+       }
 
        for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
                if (!ATH_TXQ_SETUP(sc, i))
@@ -2470,8 +2473,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        bf = list_first_entry(&bf_q, struct ath_buf, list);
        hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data;
 
-       if (hdr->frame_control & IEEE80211_FCTL_MOREDATA) {
-               hdr->frame_control &= ~IEEE80211_FCTL_MOREDATA;
+       if (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_MOREDATA)) {
+               hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
                dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
                        sizeof(*hdr), DMA_TO_DEVICE);
        }
index 1b5ad1965607cd287ca211d2232da1cdcc8d73fc..cc5c592fc4c007cb7fd0fc8c6c8d05427b274123 100644 (file)
@@ -273,7 +273,7 @@ static bool pseq_handler_create_sequences(struct pri_detector *pde,
                                tmp_false_count++;
                        }
                }
-               if (ps.count < min_count)
+               if (ps.count <= min_count)
                        /* did not reach minimum count, drop sequence */
                        continue;
 
index c79cfe02ec80a62ded454689cee393261484d5ec..e4be2d9bbac40415c8ffc660e674b5a1aba2920c 100644 (file)
@@ -736,6 +736,92 @@ static int wil_fix_bcon(struct wil6210_priv *wil,
        return rc;
 }
 
+/* internal functions for device reset and starting AP */
+static int _wil_cfg80211_set_ies(struct wiphy *wiphy,
+                                size_t probe_ies_len, const u8 *probe_ies,
+                                size_t assoc_ies_len, const u8 *assoc_ies)
+
+{
+       int rc;
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       /* FW do not form regular beacon, so bcon IE's are not set
+        * For the DMG bcon, when it will be supported, bcon IE's will
+        * be reused; add something like:
+        * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
+        * bcon->beacon_ies);
+        */
+       rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, probe_ies_len, probe_ies);
+       if (rc) {
+               wil_err(wil, "set_ie(PROBE_RESP) failed\n");
+               return rc;
+       }
+
+       rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, assoc_ies_len, assoc_ies);
+       if (rc) {
+               wil_err(wil, "set_ie(ASSOC_RESP) failed\n");
+               return rc;
+       }
+
+       return 0;
+}
+
+static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
+                                 struct net_device *ndev,
+                                 const u8 *ssid, size_t ssid_len, u32 privacy,
+                                 int bi, u8 chan,
+                                 size_t probe_ies_len, const u8 *probe_ies,
+                                 size_t assoc_ies_len, const u8 *assoc_ies,
+                                 u8 hidden_ssid)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       int rc;
+       struct wireless_dev *wdev = ndev->ieee80211_ptr;
+       u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+       wil_set_recovery_state(wil, fw_recovery_idle);
+
+       mutex_lock(&wil->mutex);
+
+       __wil_down(wil);
+       rc = __wil_up(wil);
+       if (rc)
+               goto out;
+
+       rc = wmi_set_ssid(wil, ssid_len, ssid);
+       if (rc)
+               goto out;
+
+       rc = _wil_cfg80211_set_ies(wiphy, probe_ies_len, probe_ies,
+                                  assoc_ies_len, assoc_ies);
+       if (rc)
+               goto out;
+
+       wil->privacy = privacy;
+       wil->channel = chan;
+       wil->hidden_ssid = hidden_ssid;
+
+       netif_carrier_on(ndev);
+
+       rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid);
+       if (rc)
+               goto err_pcp_start;
+
+       rc = wil_bcast_init(wil);
+       if (rc)
+               goto err_bcast;
+
+       goto out; /* success */
+
+err_bcast:
+       wmi_pcp_stop(wil);
+err_pcp_start:
+       netif_carrier_off(ndev);
+out:
+       mutex_unlock(&wil->mutex);
+       return rc;
+}
+
 static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
                                      struct net_device *ndev,
                                      struct cfg80211_beacon_data *bcon)
@@ -746,6 +832,7 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
        const u8 *pr_ies = NULL;
        size_t pr_ies_len = 0;
        int rc;
+       u32 privacy = 0;
 
        wil_dbg_misc(wil, "%s()\n", __func__);
        wil_print_bcon_data(bcon);
@@ -760,40 +847,41 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
                wil_print_bcon_data(bcon);
        }
 
-       /* FW do not form regular beacon, so bcon IE's are not set
-        * For the DMG bcon, when it will be supported, bcon IE's will
-        * be reused; add something like:
-        * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
-        * bcon->beacon_ies);
-        */
-       rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, pr_ies_len, pr_ies);
-       if (rc) {
-               wil_err(wil, "set_ie(PROBE_RESP) failed\n");
-               return rc;
-       }
+       if (pr_ies && cfg80211_find_ie(WLAN_EID_RSN, pr_ies, pr_ies_len))
+               privacy = 1;
 
-       rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP,
-                       bcon->assocresp_ies_len,
-                       bcon->assocresp_ies);
-       if (rc) {
-               wil_err(wil, "set_ie(ASSOC_RESP) failed\n");
-               return rc;
+       /* in case privacy has changed, need to restart the AP */
+       if (wil->privacy != privacy) {
+               struct wireless_dev *wdev = ndev->ieee80211_ptr;
+
+               wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n",
+                            wil->privacy, privacy);
+
+               rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
+                                           wdev->ssid_len, privacy,
+                                           wdev->beacon_interval,
+                                           wil->channel, pr_ies_len, pr_ies,
+                                           bcon->assocresp_ies_len,
+                                           bcon->assocresp_ies,
+                                           wil->hidden_ssid);
+       } else {
+               rc = _wil_cfg80211_set_ies(wiphy, pr_ies_len, pr_ies,
+                                          bcon->assocresp_ies_len,
+                                          bcon->assocresp_ies);
        }
 
-       return 0;
+       return rc;
 }
 
 static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                                 struct net_device *ndev,
                                 struct cfg80211_ap_settings *info)
 {
-       int rc = 0;
+       int rc;
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-       struct wireless_dev *wdev = ndev->ieee80211_ptr;
        struct ieee80211_channel *channel = info->chandef.chan;
        struct cfg80211_beacon_data *bcon = &info->beacon;
        struct cfg80211_crypto_settings *crypto = &info->crypto;
-       u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
        struct ieee80211_mgmt *f = (struct ieee80211_mgmt *)bcon->probe_resp;
        size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
        const u8 *pr_ies = NULL;
@@ -807,6 +895,23 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                return -EINVAL;
        }
 
+       switch (info->hidden_ssid) {
+       case NL80211_HIDDEN_SSID_NOT_IN_USE:
+               hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
+               break;
+
+       case NL80211_HIDDEN_SSID_ZERO_LEN:
+               hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
+               break;
+
+       case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
+               hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
+               break;
+
+       default:
+               wil_err(wil, "AP: Invalid hidden SSID %d\n", info->hidden_ssid);
+               return -EOPNOTSUPP;
+       }
        wil_dbg_misc(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
                     channel->center_freq, info->privacy ? "secure" : "open");
        wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
@@ -830,70 +935,14 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                wil_print_bcon_data(bcon);
        }
 
-       wil_set_recovery_state(wil, fw_recovery_idle);
-
-       mutex_lock(&wil->mutex);
-
-       __wil_down(wil);
-       rc = __wil_up(wil);
-       if (rc)
-               goto out;
-
-       rc = wmi_set_ssid(wil, info->ssid_len, info->ssid);
-       if (rc)
-               goto out;
-
-       /* IE's */
-       /* bcon 'head IE's are not relevant for 60g band */
-       /*
-        * FW do not form regular beacon, so bcon IE's are not set
-        * For the DMG bcon, when it will be supported, bcon IE's will
-        * be reused; add something like:
-        * wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
-        * bcon->beacon_ies);
-        */
-       wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, pr_ies_len, pr_ies);
-       wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len,
-                  bcon->assocresp_ies);
-
-       wil->privacy = info->privacy;
-
-       switch (info->hidden_ssid) {
-       case NL80211_HIDDEN_SSID_NOT_IN_USE:
-               hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
-               break;
-
-       case NL80211_HIDDEN_SSID_ZERO_LEN:
-               hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
-               break;
-
-       case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
-               hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
-               break;
-
-       default:
-               rc = -EOPNOTSUPP;
-               goto out;
-       }
-
-       netif_carrier_on(ndev);
-
-       rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype,
-                          channel->hw_value, hidden_ssid);
-       if (rc)
-               goto err_pcp_start;
+       rc = _wil_cfg80211_start_ap(wiphy, ndev,
+                                   info->ssid, info->ssid_len, info->privacy,
+                                   info->beacon_interval, channel->hw_value,
+                                   pr_ies_len, pr_ies,
+                                   bcon->assocresp_ies_len,
+                                   bcon->assocresp_ies,
+                                   hidden_ssid);
 
-       rc = wil_bcast_init(wil);
-       if (rc)
-               goto err_bcast;
-
-       goto out; /* success */
-err_bcast:
-       wmi_pcp_stop(wil);
-err_pcp_start:
-       netif_carrier_off(ndev);
-out:
-       mutex_unlock(&wil->mutex);
        return rc;
 }
 
index 275355d46a36fc8c2ae85585fc7188c0a7e64473..c63e4a35eaa0fc95cc0cf9d68847c8a11b0b6749 100644 (file)
@@ -559,6 +559,8 @@ struct wil6210_priv {
        /* profile */
        u32 monitor_flags;
        u32 privacy; /* secure connection? */
+       u8 hidden_ssid; /* relevant in AP mode */
+       u16 channel; /* relevant in AP mode */
        int sinfo_gen;
        u32 ap_isolate; /* no intra-BSS communication */
        /* interrupt moderation */
index 916123a3d74e71053a908491f64eec4a0d978a76..a335f94c72ff7019c3017afadc7946ec26283cc3 100644 (file)
@@ -929,8 +929,8 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev,
        b43_lo_write(dev, &cal->ctl);
 }
 
-/* Periodic LO maintanance work */
-void b43_lo_g_maintanance_work(struct b43_wldev *dev)
+/* Periodic LO maintenance work */
+void b43_lo_g_maintenance_work(struct b43_wldev *dev)
 {
        struct b43_phy *phy = &dev->phy;
        struct b43_phy_g *gphy = phy->g;
index 3b27e20eff80ff1d295d50e879888ed938eda913..7b4df3883bc24ed4f98ef7e8ca755c2304d3a1ad 100644 (file)
@@ -80,7 +80,7 @@ void b43_lo_g_adjust_to(struct b43_wldev *dev,
 
 void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all);
 
-void b43_lo_g_maintanance_work(struct b43_wldev *dev);
+void b43_lo_g_maintenance_work(struct b43_wldev *dev);
 void b43_lo_g_cleanup(struct b43_wldev *dev);
 void b43_lo_g_init(struct b43_wldev *dev);
 
index 727ce6edb4b3831faf6d254ad789b4a9a1a7c336..462310e6e88fbe85716fef77410f2302f3de64b9 100644 (file)
@@ -3004,7 +3004,7 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
                   phy->rev == 1) {
                //TODO: implement rev1 workaround
        }
-       b43_lo_g_maintanance_work(dev);
+       b43_lo_g_maintenance_work(dev);
        b43_mac_enable(dev);
 }
 
index d86d1f1f1c91d70ea803cfd07737ecaab6699400..ffe526070d6f19a99de1a777129a51692e508147 100644 (file)
@@ -5785,6 +5785,7 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy)
 
 static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
 {
+       struct brcmf_pub *drvr = ifp->drvr;
        struct ieee80211_supported_band *band;
        __le32 bandlist[3];
        u32 n_bands;
@@ -5798,6 +5799,19 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
        if (err)
                return err;
 
+       for (i = 0; i < wiphy->iface_combinations->max_interfaces &&
+            i < ARRAY_SIZE(drvr->addresses); i++) {
+               u8 *addr = drvr->addresses[i].addr;
+
+               memcpy(addr, drvr->mac, ETH_ALEN);
+               if (i) {
+                       addr[0] |= BIT(1);
+                       addr[ETH_ALEN - 1] ^= i;
+               }
+       }
+       wiphy->addresses = drvr->addresses;
+       wiphy->n_addresses = i;
+
        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
        wiphy->cipher_suites = __wl_cipher_suites;
        wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
index fd74a9c6e9ac62ac310c688f5fade1acbf7c7d73..746304121cdbf99bf02845462689737c21272c02 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef BRCMFMAC_CORE_H
 #define BRCMFMAC_CORE_H
 
+#include <net/cfg80211.h>
 #include "fweh.h"
 
 #define TOE_TX_CSUM_OL         0x00000001
@@ -118,6 +119,8 @@ struct brcmf_pub {
        /* Multicast data packets sent to dongle */
        unsigned long tx_multicast;
 
+       struct mac_address addresses[BRCMF_MAX_IFS];
+
        struct brcmf_if *iflist[BRCMF_MAX_IFS];
 
        struct mutex proto_block;
index ab775a5d5b331f975c6b4dadb300a0744556d9b1..d2c5747e3ac9233731d70d8ff391fc8791beaebb 100644 (file)
@@ -1472,9 +1472,7 @@ struct brcms_timer *brcms_init_timer(struct brcms_info *wl,
        wl->timers = t;
 
 #ifdef DEBUG
-       t->name = kmalloc(strlen(name) + 1, GFP_ATOMIC);
-       if (t->name)
-               strcpy(t->name, name);
+       t->name = kstrdup(name, GFP_ATOMIC);
 #endif
 
        return t;
index 7603546d2de322cf8fb5dd5bf0d5ff3e48d8a6be..29185aeccba8b721d3d9c18177f5f86b10d145a2 100644 (file)
@@ -467,7 +467,6 @@ static struct spi_driver spi_driver = {
        .remove         = cw1200_spi_disconnect,
        .driver = {
                .name           = "cw1200_wlan_spi",
-               .bus            = &spi_bus_type,
                .owner          = THIS_MODULE,
 #ifdef CONFIG_PM
                .pm             = &cw1200_pm_ops,
index 08eb229e7816010f11e702d679cb178b213362d2..36818c7f30b962d549867c354521cc72cbb4d26d 100644 (file)
@@ -1410,7 +1410,7 @@ static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv)
 static int ipw2100_hw_phy_off(struct ipw2100_priv *priv)
 {
 
-#define HW_PHY_OFF_LOOP_DELAY (HZ / 5000)
+#define HW_PHY_OFF_LOOP_DELAY (msecs_to_jiffies(50))
 
        struct host_command cmd = {
                .host_command = CARD_DISABLE_PHY_OFF,
index 7f4cb692cc57e97de9b6bd78ea717df97d03221f..af1b3e6839fa6db3e69e90bee7a50923f1d0230e 100644 (file)
@@ -3259,7 +3259,7 @@ il3945_show_measurement(struct device *d, struct device_attribute *attr,
 
        while (size && PAGE_SIZE - len) {
                hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-                                  PAGE_SIZE - len, 1);
+                                  PAGE_SIZE - len, true);
                len = strlen(buf);
                if (PAGE_SIZE - len)
                        buf[len++] = '\n';
index 34401015319631bb21afda0f48f283f13f6a2343..908b9f4fef6f3b4e3522b8f2c5a03166ca0cf2b8 100644 (file)
@@ -515,12 +515,8 @@ il_dbgfs_nvm_read(struct file *file, char __user *user_buf, size_t count,
            scnprintf(buf + pos, buf_size - pos, "EEPROM " "version: 0x%x\n",
                      eeprom_ver);
        for (ofs = 0; ofs < eeprom_len; ofs += 16) {
-               pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
-               hex_dump_to_buffer(ptr + ofs, 16, 16, 2, buf + pos,
-                                  buf_size - pos, 0);
-               pos += strlen(buf + pos);
-               if (buf_size - pos > 0)
-                       buf[pos++] = '\n';
+               pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x %16ph\n",
+                                ofs, ptr + ofs);
        }
 
        ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
index b15e4c7acbecd2ed44b1e76360464ef23f3fd9f3..ff63cb5632eb089a817422dddfa9dda0069b2478 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "cfg80211.h"
 #include "main.h"
+#include "11n.h"
 
 static char *reg_alpha2;
 module_param(reg_alpha2, charp, 0);
@@ -34,12 +35,38 @@ static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
        },
 };
 
-static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
+static const struct ieee80211_iface_combination
+mwifiex_iface_comb_ap_sta = {
        .limits = mwifiex_ap_sta_limits,
        .num_different_channels = 1,
        .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
        .max_interfaces = MWIFIEX_MAX_BSS_NUM,
        .beacon_int_infra_match = true,
+       .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                               BIT(NL80211_CHAN_WIDTH_20) |
+                               BIT(NL80211_CHAN_WIDTH_40),
+};
+
+static const struct ieee80211_iface_combination
+mwifiex_iface_comb_ap_sta_vht = {
+       .limits = mwifiex_ap_sta_limits,
+       .num_different_channels = 1,
+       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
+       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
+       .beacon_int_infra_match = true,
+       .radar_detect_widths =  BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                               BIT(NL80211_CHAN_WIDTH_20) |
+                               BIT(NL80211_CHAN_WIDTH_40) |
+                               BIT(NL80211_CHAN_WIDTH_80),
+};
+
+static const struct
+ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = {
+       .limits = mwifiex_ap_sta_limits,
+       .num_different_channels = 2,
+       .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits),
+       .max_interfaces = MWIFIEX_MAX_BSS_NUM,
+       .beacon_int_infra_match = true,
 };
 
 /*
@@ -441,7 +468,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
  *      - Country codes
  *      - Sub bands (first channel, number of channels, maximum Tx power)
  */
-static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
+int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
 {
        u8 no_of_triplet = 0;
        struct ieee80211_country_ie_triplet *t;
@@ -804,10 +831,13 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
                priv->bss_type = MWIFIEX_BSS_TYPE_STA;
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
-       case NL80211_IFTYPE_P2P_GO:
                priv->bss_role =  MWIFIEX_BSS_ROLE_STA;
                priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
                break;
+       case NL80211_IFTYPE_P2P_GO:
+               priv->bss_role =  MWIFIEX_BSS_ROLE_UAP;
+               priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
+               break;
        case NL80211_IFTYPE_AP:
                priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
                priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
@@ -1115,8 +1145,10 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy,
        case NL80211_IFTYPE_P2P_GO:
                switch (type) {
                case NL80211_IFTYPE_STATION:
-                       if (mwifiex_cfg80211_init_p2p_client(priv))
+                       if (mwifiex_cfg80211_deinit_p2p(priv))
                                return -EFAULT;
+                       priv->adapter->curr_iface_comb.p2p_intf--;
+                       priv->adapter->curr_iface_comb.sta_intf++;
                        dev->ieee80211_ptr->iftype = type;
                        break;
                case NL80211_IFTYPE_ADHOC:
@@ -2788,6 +2820,7 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
        struct mwifiex_adapter *adapter = priv->adapter;
+       struct sk_buff *skb, *tmp;
 
 #ifdef CONFIG_DEBUG_FS
        mwifiex_dev_debugfs_remove(priv);
@@ -2795,6 +2828,9 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
 
        mwifiex_stop_net_dev_queue(priv->netdev, adapter);
 
+       skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+
        if (netif_carrier_ok(priv->netdev))
                netif_carrier_off(priv->netdev);
 
@@ -2954,7 +2990,6 @@ static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv,
                                        MWIFIEX_MEF_MAX_BYTESEQ)) {
                        mwifiex_dbg(priv->adapter, ERROR,
                                    "Pattern not supported\n");
-                       kfree(mef_entry);
                        return -EOPNOTSUPP;
                }
 
@@ -3036,9 +3071,12 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv,
 
        mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]);
 
-       if (wowlan->n_patterns || wowlan->magic_pkt)
+       if (wowlan->n_patterns || wowlan->magic_pkt) {
                ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg,
                                                   &mef_entry[1], wowlan);
+               if (ret)
+                       goto err;
+       }
 
        if (!mef_cfg.criteria)
                mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST |
@@ -3048,6 +3086,8 @@ static int mwifiex_set_mef_filter(struct mwifiex_private *priv,
        ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG,
                        HostCmd_ACT_GEN_SET, 0,
                        &mef_cfg, true);
+
+err:
        kfree(mef_entry);
        return ret;
 }
@@ -3359,6 +3399,72 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
        return mwifiex_tdls_oper(priv, peer, action);
 }
 
+static int
+mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev,
+                                 const u8 *addr, u8 oper_class,
+                                 struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+       u16 chan;
+       u8 second_chan_offset, band;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_ptr = mwifiex_get_sta_entry(priv, addr);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (!sta_ptr) {
+               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
+                         __func__, addr);
+               return -ENOENT;
+       }
+
+       if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] &
+             WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) {
+               wiphy_err(wiphy, "%pM do not support tdls cs\n", addr);
+               return -ENOENT;
+       }
+
+       if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
+           sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) {
+               wiphy_err(wiphy, "channel switch is running, abort request\n");
+               return -EALREADY;
+       }
+
+       chan = chandef->chan->hw_value;
+       second_chan_offset = mwifiex_get_sec_chan_offset(chan);
+       band = chandef->chan->band;
+       mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band);
+
+       return 0;
+}
+
+static void
+mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy,
+                                        struct net_device *dev,
+                                        const u8 *addr)
+{
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+
+       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+       sta_ptr = mwifiex_get_sta_entry(priv, addr);
+       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+       if (!sta_ptr) {
+               wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n",
+                         __func__, addr);
+       } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING ||
+                    sta_ptr->tdls_status == TDLS_IN_BASE_CHAN ||
+                    sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) {
+               wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n",
+                         addr);
+       } else
+               mwifiex_stop_tdls_cs(priv, addr);
+}
+
 static int
 mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev,
                             const u8 *mac, struct station_parameters *params)
@@ -3575,6 +3681,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
        .set_coalesce = mwifiex_cfg80211_set_coalesce,
        .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt,
        .tdls_oper = mwifiex_cfg80211_tdls_oper,
+       .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch,
+       .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch,
        .add_station = mwifiex_cfg80211_add_station,
        .change_station = mwifiex_cfg80211_change_station,
        .get_channel = mwifiex_cfg80211_get_channel,
@@ -3672,7 +3780,12 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
        else
                wiphy->bands[IEEE80211_BAND_5GHZ] = NULL;
 
-       wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
+       if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
+               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs;
+       else if (adapter->is_hw_11ac_capable)
+               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht;
+       else
+               wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta;
        wiphy->n_iface_combinations = 1;
 
        /* Initialize cipher suits */
@@ -3709,6 +3822,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
                           NL80211_FEATURE_INACTIVITY_TIMER |
                           NL80211_FEATURE_NEED_OBSS_SCAN;
 
+       if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
+               wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
+
        if (adapter->fw_api_ver == MWIFIEX_FW_V15)
                wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
 
index 51e344789ba214bbbd5cfe7dc29a0a6ac1244527..098e1f14dc9a47efc4aae6e9611f1165c2af5624 100644 (file)
@@ -141,6 +141,9 @@ enum mwifiex_tdls_status {
        TDLS_SETUP_COMPLETE,
        TDLS_SETUP_FAILURE,
        TDLS_LINK_TEARDOWN,
+       TDLS_CHAN_SWITCHING,
+       TDLS_IN_BASE_CHAN,
+       TDLS_IN_OFF_CHAN,
 };
 
 enum mwifiex_tdls_error_code {
index cd09051710e6cee82c624e6960f4c8accd452338..cff38ad129aad93fa8f63c7a8636afc80b51eb96 100644 (file)
@@ -169,14 +169,17 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_TYPE_UAP_PS_AO_TIMER    (PROPRIETARY_TLV_BASE_ID + 123)
 #define TLV_TYPE_PWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 145)
 #define TLV_TYPE_GWK_CIPHER         (PROPRIETARY_TLV_BASE_ID + 146)
+#define TLV_TYPE_TX_PAUSE           (PROPRIETARY_TLV_BASE_ID + 148)
 #define TLV_TYPE_COALESCE_RULE      (PROPRIETARY_TLV_BASE_ID + 154)
 #define TLV_TYPE_KEY_PARAM_V2       (PROPRIETARY_TLV_BASE_ID + 156)
+#define TLV_TYPE_MULTI_CHAN_INFO    (PROPRIETARY_TLV_BASE_ID + 183)
 #define TLV_TYPE_TDLS_IDLE_TIMEOUT  (PROPRIETARY_TLV_BASE_ID + 194)
 #define TLV_TYPE_SCAN_CHANNEL_GAP   (PROPRIETARY_TLV_BASE_ID + 197)
 #define TLV_TYPE_API_REV            (PROPRIETARY_TLV_BASE_ID + 199)
 #define TLV_TYPE_CHANNEL_STATS      (PROPRIETARY_TLV_BASE_ID + 198)
 #define TLV_BTCOEX_WL_AGGR_WINSIZE  (PROPRIETARY_TLV_BASE_ID + 202)
 #define TLV_BTCOEX_WL_SCANTIME      (PROPRIETARY_TLV_BASE_ID + 203)
+#define TLV_TYPE_BSS_MODE           (PROPRIETARY_TLV_BASE_ID + 206)
 
 #define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
 
@@ -200,6 +203,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 
 #define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11))
 #define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14))
+#define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15))
 #define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16))
 
 #define MWIFIEX_DEF_HT_CAP     (IEEE80211_HT_CAP_DSSSCCK40 | \
@@ -359,6 +363,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_MGMT_FRAME_REG                    0x010c
 #define HostCmd_CMD_REMAIN_ON_CHAN                    0x010d
 #define HostCmd_CMD_11AC_CFG                         0x0112
+#define HostCmd_CMD_TDLS_CONFIG                       0x0100
+#define HostCmd_CMD_MC_POLICY                         0x0121
 #define HostCmd_CMD_TDLS_OPER                         0x0122
 #define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG               0x0223
 
@@ -509,8 +515,10 @@ enum P2P_MODES {
 #define EVENT_TDLS_GENERIC_EVENT        0x00000052
 #define EVENT_RADAR_DETECTED           0x00000053
 #define EVENT_CHANNEL_REPORT_RDY        0x00000054
+#define EVENT_TX_DATA_PAUSE             0x00000055
 #define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
+#define EVENT_MULTI_CHAN_INFO           0x0000006a
 #define EVENT_TX_STATUS_REPORT         0x00000074
 #define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
 
@@ -545,7 +553,27 @@ enum P2P_MODES {
 #define ACT_TDLS_DELETE            0x00
 #define ACT_TDLS_CREATE            0x01
 #define ACT_TDLS_CONFIG            0x02
-#define TDLS_EVENT_LINK_TEAR_DOWN  3
+
+#define TDLS_EVENT_LINK_TEAR_DOWN      3
+#define TDLS_EVENT_CHAN_SWITCH_RESULT  7
+#define TDLS_EVENT_START_CHAN_SWITCH   8
+#define TDLS_EVENT_CHAN_SWITCH_STOPPED 9
+
+#define TDLS_BASE_CHANNEL             0
+#define TDLS_OFF_CHANNEL              1
+
+#define ACT_TDLS_CS_ENABLE_CONFIG 0x00
+#define ACT_TDLS_CS_INIT         0x06
+#define ACT_TDLS_CS_STOP         0x07
+#define ACT_TDLS_CS_PARAMS       0x08
+
+#define MWIFIEX_DEF_CS_UNIT_TIME       2
+#define MWIFIEX_DEF_CS_THR_OTHERLINK   10
+#define MWIFIEX_DEF_THR_DIRECTLINK     0
+#define MWIFIEX_DEF_CS_TIME            10
+#define MWIFIEX_DEF_CS_TIMEOUT         16
+#define MWIFIEX_DEF_CS_REG_CLASS       12
+#define MWIFIEX_DEF_CS_PERIODICITY     1
 
 #define MWIFIEX_FW_V15            15
 
@@ -1131,6 +1159,13 @@ struct host_cmd_ds_tx_rate_query {
        u8 ht_info;
 } __packed;
 
+struct mwifiex_tx_pause_tlv {
+       struct mwifiex_ie_types_header header;
+       u8 peermac[ETH_ALEN];
+       u8 tx_pause;
+       u8 pkt_cnt;
+} __packed;
+
 enum Host_Sleep_Action {
        HS_CONFIGURE = 0x0001,
        HS_ACTIVATE  = 0x0002,
@@ -1249,6 +1284,36 @@ struct host_cmd_ds_tdls_oper {
        u8 peer_mac[ETH_ALEN];
 } __packed;
 
+struct mwifiex_tdls_config {
+       __le16 enable;
+};
+
+struct mwifiex_tdls_config_cs_params {
+       u8 unit_time;
+       u8 thr_otherlink;
+       u8 thr_directlink;
+};
+
+struct mwifiex_tdls_init_cs_params {
+       u8 peer_mac[ETH_ALEN];
+       u8 primary_chan;
+       u8 second_chan_offset;
+       u8 band;
+       __le16 switch_time;
+       __le16 switch_timeout;
+       u8 reg_class;
+       u8 periodicity;
+} __packed;
+
+struct mwifiex_tdls_stop_cs_params {
+       u8 peer_mac[ETH_ALEN];
+};
+
+struct host_cmd_ds_tdls_config {
+       __le16 tdls_action;
+       u8 tdls_data[1];
+} __packed;
+
 struct mwifiex_chan_desc {
        __le16 start_freq;
        u8 chan_width;
@@ -1370,6 +1435,11 @@ struct host_cmd_ds_802_11_scan_ext {
        u8    tlv_buffer[1];
 } __packed;
 
+struct mwifiex_ie_types_bss_mode {
+       struct mwifiex_ie_types_header  header;
+       u8 bss_mode;
+} __packed;
+
 struct mwifiex_ie_types_bss_scan_rsp {
        struct mwifiex_ie_types_header header;
        u8 bssid[ETH_ALEN];
@@ -1908,6 +1978,12 @@ struct mwifiex_radar_det_event {
        __le32 passed;
 } __packed;
 
+struct mwifiex_ie_types_multi_chan_info {
+       struct mwifiex_ie_types_header header;
+       __le16 status;
+       u8 tlv_buffer[0];
+} __packed;
+
 struct meas_rpt_map {
        u8 rssi:3;
        u8 unmeasured:1;
@@ -1927,10 +2003,18 @@ struct host_cmd_ds_802_11_subsc_evt {
        __le16 events;
 } __packed;
 
+struct chan_switch_result {
+       u8 cur_chan;
+       u8 status;
+       u8 reason;
+} __packed;
+
 struct mwifiex_tdls_generic_event {
        __le16 type;
        u8 peer_mac[ETH_ALEN];
        union {
+               struct chan_switch_result switch_result;
+               u8 cs_stop_reason;
                __le16 reason_code;
                __le16 reserved;
        } u;
@@ -1971,6 +2055,11 @@ struct host_cmd_ds_coalesce_cfg {
        struct coalesce_receive_filt_rule rule[0];
 } __packed;
 
+struct host_cmd_ds_multi_chan_policy {
+       __le16 action;
+       __le16 policy;
+} __packed;
+
 struct host_cmd_ds_command {
        __le16 command;
        __le16 size;
@@ -2035,9 +2124,11 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_sta_list sta_list;
                struct host_cmd_11ac_vht_cfg vht_cfg;
                struct host_cmd_ds_coalesce_cfg coalesce_cfg;
+               struct host_cmd_ds_tdls_config tdls_config;
                struct host_cmd_ds_tdls_oper tdls_oper;
                struct host_cmd_ds_chan_rpt_req chan_rpt_req;
                struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg;
+               struct host_cmd_ds_multi_chan_policy mc_policy;
        } params;
 } __packed;
 
index 0ba8945094139c5e02374a11034e66777186c074..abf52d25b9815b720399221e2da00bff9381a2c9 100644 (file)
@@ -409,6 +409,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
        int ret;
 
        ret = mwifiex_uap_parse_tail_ies(priv, info);
+
+       if (ret)
                return ret;
 
        return mwifiex_set_mgmt_beacon_data_ies(priv, info);
@@ -477,6 +479,7 @@ int mwifiex_del_mgmt_ies(struct mwifiex_private *priv)
                                                   ar_ie, &priv->assocresp_idx);
 
 done:
+       kfree(gen_ie);
        kfree(beacon_ie);
        kfree(pr_ie);
        kfree(ar_ie);
index df7fdc09d38c7f1e326b59ad8fd0a9ea53485f74..8fa363add9706364843207a85d475096f20dbeb7 100644 (file)
@@ -77,7 +77,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
 
        priv->media_connected = false;
        eth_broadcast_addr(priv->curr_addr);
-
+       priv->port_open = false;
        priv->pkt_tx_ctrl = 0;
        priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
        priv->data_rate = 0;    /* Initially indicate the rate as auto */
@@ -499,6 +499,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
                INIT_LIST_HEAD(&priv->sta_list);
                INIT_LIST_HEAD(&priv->auto_tdls_list);
                skb_queue_head_init(&priv->tdls_txq);
+               skb_queue_head_init(&priv->bypass_txq);
 
                spin_lock_init(&priv->tx_ba_stream_tbl_lock);
                spin_lock_init(&priv->rx_reorder_tbl_lock);
index 56b024a6aaa58d2b89ca25692c37163367eda597..3cda1f956f0b1654ec438291e22f416ada279e17 100644 (file)
@@ -783,6 +783,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
 
        if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled)
                priv->scan_block = true;
+       else
+               priv->port_open = true;
 
 done:
        /* Need to indicate IOCTL complete */
index 3ba4e0e04223bcde4fd0da162db6bb6db6160b62..278dc94eaecbb28e12a075526572c342e52f31cf 100644 (file)
@@ -276,6 +276,7 @@ process_start:
                     !adapter->pm_wakeup_fw_try) &&
                    (is_command_pending(adapter) ||
                     !skb_queue_empty(&adapter->tx_data_q) ||
+                    !mwifiex_bypass_txlist_empty(adapter) ||
                     !mwifiex_wmm_lists_empty(adapter))) {
                        adapter->pm_wakeup_fw_try = true;
                        mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3));
@@ -299,9 +300,16 @@ process_start:
 
                        if ((!adapter->scan_chan_gap_enabled &&
                             adapter->scan_processing) || adapter->data_sent ||
+                            mwifiex_is_tdls_chan_switching
+                            (mwifiex_get_priv(adapter,
+                                              MWIFIEX_BSS_ROLE_STA)) ||
                            (mwifiex_wmm_lists_empty(adapter) &&
+                            mwifiex_bypass_txlist_empty(adapter) &&
                             skb_queue_empty(&adapter->tx_data_q))) {
                                if (adapter->cmd_sent || adapter->curr_cmd ||
+                                       !mwifiex_is_send_cmd_allowed
+                                               (mwifiex_get_priv(adapter,
+                                               MWIFIEX_BSS_ROLE_STA)) ||
                                    (!is_command_pending(adapter)))
                                        break;
                        }
@@ -342,7 +350,9 @@ process_start:
                        continue;
                }
 
-               if (!adapter->cmd_sent && !adapter->curr_cmd) {
+               if (!adapter->cmd_sent && !adapter->curr_cmd &&
+                   mwifiex_is_send_cmd_allowed
+                   (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
                        if (mwifiex_exec_next_cmd(adapter) == -1) {
                                ret = -1;
                                break;
@@ -365,7 +375,25 @@ process_start:
 
                if ((adapter->scan_chan_gap_enabled ||
                     !adapter->scan_processing) &&
-                   !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter)) {
+                   !adapter->data_sent &&
+                   !mwifiex_bypass_txlist_empty(adapter) &&
+                   !mwifiex_is_tdls_chan_switching
+                       (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
+                       mwifiex_process_bypass_tx(adapter);
+                       if (adapter->hs_activated) {
+                               adapter->is_hs_configured = false;
+                               mwifiex_hs_activated_event
+                                       (mwifiex_get_priv
+                                        (adapter, MWIFIEX_BSS_ROLE_ANY),
+                                        false);
+                       }
+               }
+
+               if ((adapter->scan_chan_gap_enabled ||
+                    !adapter->scan_processing) &&
+                   !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) &&
+                   !mwifiex_is_tdls_chan_switching
+                       (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) {
                        mwifiex_wmm_process_tx(adapter);
                        if (adapter->hs_activated) {
                                adapter->is_hs_configured = false;
@@ -379,6 +407,7 @@ process_start:
                if (adapter->delay_null_pkt && !adapter->cmd_sent &&
                    !adapter->curr_cmd && !is_command_pending(adapter) &&
                    (mwifiex_wmm_lists_empty(adapter) &&
+                    mwifiex_bypass_txlist_empty(adapter) &&
                     skb_queue_empty(&adapter->tx_data_q))) {
                        if (!mwifiex_send_null_packet
                            (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA),
@@ -649,6 +678,26 @@ mwifiex_close(struct net_device *dev)
        return 0;
 }
 
+static bool
+mwifiex_bypass_tx_queue(struct mwifiex_private *priv,
+                       struct sk_buff *skb)
+{
+       struct ethhdr *eth_hdr = (struct ethhdr *)skb->data;
+
+       if (ntohs(eth_hdr->h_proto) == ETH_P_PAE ||
+           mwifiex_is_skb_mgmt_frame(skb) ||
+           (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA &&
+            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+            (ntohs(eth_hdr->h_proto) == ETH_P_TDLS))) {
+               mwifiex_dbg(priv->adapter, DATA,
+                           "bypass txqueue; eth type %#x, mgmt %d\n",
+                            ntohs(eth_hdr->h_proto),
+                            mwifiex_is_skb_mgmt_frame(skb));
+               return true;
+       }
+
+       return false;
+}
 /*
  * Add buffer into wmm tx queue and queue work to transmit it.
  */
@@ -666,8 +715,14 @@ int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb)
                }
        }
 
-       atomic_inc(&priv->adapter->tx_pending);
-       mwifiex_wmm_add_buf_txqueue(priv, skb);
+       if (mwifiex_bypass_tx_queue(priv, skb)) {
+               atomic_inc(&priv->adapter->tx_pending);
+               atomic_inc(&priv->adapter->bypass_tx_pending);
+               mwifiex_wmm_add_buf_bypass_txqueue(priv, skb);
+        } else {
+               atomic_inc(&priv->adapter->tx_pending);
+               mwifiex_wmm_add_buf_txqueue(priv, skb);
+        }
 
        mwifiex_queue_main_work(priv->adapter);
 
index ae98b5b83b1f0133cc216c2942095081ded5b52d..face7478937f6559e106c4932d6551569b8beaac 100644 (file)
@@ -281,6 +281,7 @@ struct mwifiex_ra_list_tbl {
        u8 amsdu_in_ampdu;
        u16 total_pkt_count;
        bool tdls_link;
+       bool tx_paused;
 };
 
 struct mwifiex_tid_tbl {
@@ -294,6 +295,7 @@ struct mwifiex_tid_tbl {
 struct mwifiex_wmm_desc {
        struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID];
        u32 packets_out[MAX_NUM_TID];
+       u32 pkts_paused[MAX_NUM_TID];
        /* spin lock to protect ra_list */
        spinlock_t ra_list_spinlock;
        struct mwifiex_wmm_ac_status ac_status[IEEE80211_NUM_ACS];
@@ -517,6 +519,7 @@ struct mwifiex_private {
        u8 frame_type;
        u8 curr_addr[ETH_ALEN];
        u8 media_connected;
+       u8 port_open;
        u32 num_tx_timeout;
        /* track consecutive timeout */
        u8 tx_timeout_cnt;
@@ -662,6 +665,7 @@ struct mwifiex_private {
        struct cfg80211_beacon_data beacon_after;
        struct mwifiex_11h_intf_state state_11h;
        struct mwifiex_ds_mem_rw mem_rw;
+       struct sk_buff_head bypass_txq;
 };
 
 
@@ -768,6 +772,7 @@ struct mwifiex_sta_node {
        u8 tdls_status;
        struct mwifiex_tdls_capab tdls_cap;
        struct mwifiex_station_stats stats;
+       u8 tx_pause;
 };
 
 struct mwifiex_auto_tdls_peer {
@@ -831,6 +836,7 @@ struct mwifiex_adapter {
        wait_queue_head_t init_wait_q;
        void *card;
        struct mwifiex_if_ops if_ops;
+       atomic_t bypass_tx_pending;
        atomic_t rx_pending;
        atomic_t tx_pending;
        atomic_t cmd_pending;
@@ -979,6 +985,7 @@ struct mwifiex_adapter {
        u8 coex_win_size;
        u8 coex_tx_win_size;
        u8 coex_rx_win_size;
+       bool drcs_enabled;
 };
 
 void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1330,6 +1337,21 @@ static inline u8 mwifiex_is_any_intf_active(struct mwifiex_private *priv)
        return 0;
 }
 
+static inline u8 mwifiex_is_tdls_link_setup(u8 status)
+{
+       switch (status) {
+       case TDLS_SETUP_COMPLETE:
+       case TDLS_CHAN_SWITCHING:
+       case TDLS_IN_BASE_CHAN:
+       case TDLS_IN_OFF_CHAN:
+               return true;
+       default:
+               break;
+       }
+
+       return false;
+}
+
 int mwifiex_init_shutdown_fw(struct mwifiex_private *priv,
                             u32 func_init_shutdown);
 int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8);
@@ -1458,6 +1480,9 @@ struct mwifiex_sta_node *
 mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
 struct mwifiex_sta_node *
 mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv);
+u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv);
+u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv);
 int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
                                 u8 action_code, u8 dialog_token,
                                 u16 status_code, const u8 *extra_ies,
@@ -1488,6 +1513,13 @@ void mwifiex_check_auto_tdls(unsigned long context);
 void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
 void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
 void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
+int mwifiex_config_tdls_enable(struct mwifiex_private *priv);
+int mwifiex_config_tdls_disable(struct mwifiex_private *priv);
+int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv);
+int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac);
+int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
+                         u8 primary_chan, u8 second_chan_offset, u8 band);
+
 int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
                                          struct host_cmd_ds_command *cmd,
                                          void *data_buf);
@@ -1522,6 +1554,12 @@ void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
 void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
 void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter);
 void mwifiex_11n_delba(struct mwifiex_private *priv, int tid);
+int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy);
+void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event);
+void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
+                                     struct sk_buff *event_skb);
+
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
 void mwifiex_debugfs_remove(void);
index baf9715ddc1034bc58e6ec4cea367caa670b571c..ef8da8ebcbab4ee5af196c4ec854b178c3b81322 100644 (file)
@@ -823,6 +823,7 @@ mwifiex_config_scan(struct mwifiex_private *priv,
        int i;
        u8 ssid_filter;
        struct mwifiex_ie_types_htcap *ht_cap;
+       struct mwifiex_ie_types_bss_mode *bss_mode;
 
        /* The tlv_buf_len is calculated for each scan command.  The TLVs added
           in this routine will be preserved since the routine that sends the
@@ -908,6 +909,10 @@ mwifiex_config_scan(struct mwifiex_private *priv,
                                wildcard_ssid_tlv->max_ssid_length =
                                                        IEEE80211_MAX_SSID_LEN;
 
+                       if (!memcmp(user_scan_in->ssid_list[i].ssid,
+                                   "DIRECT-", 7))
+                               wildcard_ssid_tlv->max_ssid_length = 0xfe;
+
                        memcpy(wildcard_ssid_tlv->ssid,
                               user_scan_in->ssid_list[i].ssid, ssid_len);
 
@@ -968,6 +973,15 @@ mwifiex_config_scan(struct mwifiex_private *priv,
        else
                *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
 
+       if (adapter->ext_scan) {
+               bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
+               bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
+               bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
+               bss_mode->bss_mode = scan_cfg_out->bss_mode;
+               tlv_pos += sizeof(bss_mode->header) +
+                          le16_to_cpu(bss_mode->header.len);
+       }
+
        /* If the input config or adapter has the number of Probes set,
           add tlv */
        if (num_probes) {
index 037adcd1f484abeb5f54478893ab7b1ff2b7ab76..a49a80dd773edbf02fe99d433d9eddee48349c76 100644 (file)
 #include "11n.h"
 #include "11ac.h"
 
+static bool drcs;
+module_param(drcs, bool, 0644);
+MODULE_PARM_DESC(drcs, "multi-channel operation:1, single-channel operation:0");
+
 static bool disable_auto_ds;
 module_param(disable_auto_ds, bool, 0);
 MODULE_PARM_DESC(disable_auto_ds,
@@ -1511,6 +1515,22 @@ static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv,
        return 0;
 }
 
+static int
+mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv,
+                         struct host_cmd_ds_command *cmd,
+                         u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy;
+       const u16 *drcs_info = data_buf;
+
+       mc_pol->action = cpu_to_le16(cmd_action);
+       mc_pol->policy = cpu_to_le16(*drcs_info);
+       cmd->command = cpu_to_le16(HostCmd_CMD_MC_POLICY);
+       cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) +
+                               S_DS_GEN);
+       return 0;
+}
+
 static int
 mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
                         struct host_cmd_ds_command *cmd,
@@ -1575,6 +1595,50 @@ mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv,
        return 0;
 }
 
+static int
+mwifiex_cmd_tdls_config(struct mwifiex_private *priv,
+                       struct host_cmd_ds_command *cmd,
+                       u16 cmd_action, void *data_buf)
+{
+       struct host_cmd_ds_tdls_config *tdls_config = &cmd->params.tdls_config;
+       struct mwifiex_tdls_init_cs_params *config;
+       struct mwifiex_tdls_config *init_config;
+       u16 len;
+
+       cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_CONFIG);
+       cmd->size = cpu_to_le16(S_DS_GEN);
+       tdls_config->tdls_action = cpu_to_le16(cmd_action);
+       le16_add_cpu(&cmd->size, sizeof(tdls_config->tdls_action));
+
+       switch (cmd_action) {
+       case ACT_TDLS_CS_ENABLE_CONFIG:
+               init_config = data_buf;
+               len = sizeof(*init_config);
+               memcpy(tdls_config->tdls_data, init_config, len);
+               break;
+       case ACT_TDLS_CS_INIT:
+               config = data_buf;
+               len = sizeof(*config);
+               memcpy(tdls_config->tdls_data, config, len);
+               break;
+       case ACT_TDLS_CS_STOP:
+               len = sizeof(struct mwifiex_tdls_stop_cs_params);
+               memcpy(tdls_config->tdls_data, data_buf, len);
+               break;
+       case ACT_TDLS_CS_PARAMS:
+               len = sizeof(struct mwifiex_tdls_config_cs_params);
+               memcpy(tdls_config->tdls_data, data_buf, len);
+               break;
+       default:
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Unknown TDLS configuration\n");
+               return -ENOTSUPP;
+       }
+
+       le16_add_cpu(&cmd->size, len);
+       return 0;
+}
+
 static int
 mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
                      struct host_cmd_ds_command *cmd,
@@ -1933,10 +1997,12 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                if (priv->bss_mode == NL80211_IFTYPE_ADHOC)
                        cmd_ptr->params.bss_mode.con_type =
                                CONNECTION_TYPE_ADHOC;
-               else if (priv->bss_mode == NL80211_IFTYPE_STATION)
+               else if (priv->bss_mode == NL80211_IFTYPE_STATION ||
+                        priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT)
                        cmd_ptr->params.bss_mode.con_type =
                                CONNECTION_TYPE_INFRA;
-               else if (priv->bss_mode == NL80211_IFTYPE_AP)
+               else if (priv->bss_mode == NL80211_IFTYPE_AP ||
+                        priv->bss_mode == NL80211_IFTYPE_P2P_GO)
                        cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP;
                cmd_ptr->size = cpu_to_le16(sizeof(struct
                                host_cmd_ds_set_bss_mode) + S_DS_GEN);
@@ -1958,6 +2024,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
        case HostCmd_CMD_TDLS_OPER:
                ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf);
                break;
+       case HostCmd_CMD_TDLS_CONFIG:
+               ret = mwifiex_cmd_tdls_config(priv, cmd_ptr, cmd_action,
+                                             data_buf);
+               break;
        case HostCmd_CMD_CHAN_REPORT_REQUEST:
                ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr,
                                                            data_buf);
@@ -1966,6 +2036,10 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action,
                                                   data_buf);
                break;
+       case HostCmd_CMD_MC_POLICY:
+               ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action,
+                                               data_buf);
+               break;
        default:
                mwifiex_dbg(priv->adapter, ERROR,
                            "PREP_CMD: unknown cmd- %#x\n", cmd_no);
@@ -2082,6 +2156,18 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init)
                        if (ret)
                                return -1;
                }
+
+               if (drcs) {
+                       adapter->drcs_enabled = true;
+                       if (ISSUPP_DRCS_ENABLED(adapter->fw_cap_info))
+                               ret = mwifiex_send_cmd(priv,
+                                                      HostCmd_CMD_MC_POLICY,
+                                                      HostCmd_ACT_GEN_SET, 0,
+                                                      &adapter->drcs_enabled,
+                                                      true);
+                       if (ret)
+                               return -1;
+               }
        }
 
        /* get tx rate */
index b645884b3b97a2c1491f745e436d217dec3b5f4d..89e8dafb473876a23d48819f5550b4a24fa0bb1d 100644 (file)
@@ -599,6 +599,7 @@ static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv,
                                    "info: key: GTK is set\n");
                        priv->wpa_is_gtk_set = true;
                        priv->scan_block = false;
+                       priv->port_open = true;
                }
        }
 
@@ -629,6 +630,7 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv,
                        mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n");
                        priv->wpa_is_gtk_set = true;
                        priv->scan_block = false;
+                       priv->port_open = true;
                }
        }
 
@@ -1191,12 +1193,15 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                break;
        case HostCmd_CMD_TDLS_OPER:
                ret = mwifiex_ret_tdls_oper(priv, resp);
+       case HostCmd_CMD_MC_POLICY:
                break;
        case HostCmd_CMD_CHAN_REPORT_REQUEST:
                break;
        case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG:
                ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp);
                break;
+       case HostCmd_CMD_TDLS_CONFIG:
+               break;
        default:
                mwifiex_dbg(adapter, ERROR,
                            "CMD_RESP: unknown cmd response %#x\n",
index 848de2621958cfaacbcd500ae7317fddf6d92085..3d18c585e5436769061a3de767e17c22674206c7 100644 (file)
@@ -54,6 +54,7 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
        priv->media_connected = false;
 
        priv->scan_block = false;
+       priv->port_open = false;
 
        if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
            ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) {
@@ -153,6 +154,7 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
        struct mwifiex_sta_node *sta_ptr;
        struct mwifiex_tdls_generic_event *tdls_evt =
                        (void *)event_skb->data + sizeof(adapter->event_cause);
+       u8 *mac = tdls_evt->peer_mac;
 
        /* reserved 2 bytes are not mandatory in tdls event */
        if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) -
@@ -175,6 +177,59 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
                                           le16_to_cpu(tdls_evt->u.reason_code),
                                           GFP_KERNEL);
                break;
+       case TDLS_EVENT_CHAN_SWITCH_RESULT:
+               mwifiex_dbg(adapter, EVENT, "tdls channel switch result :\n");
+               mwifiex_dbg(adapter, EVENT,
+                           "status=0x%x, reason=0x%x cur_chan=%d\n",
+                           tdls_evt->u.switch_result.status,
+                           tdls_evt->u.switch_result.reason,
+                           tdls_evt->u.switch_result.cur_chan);
+
+               /* tdls channel switch failed */
+               if (tdls_evt->u.switch_result.status != 0) {
+                       switch (tdls_evt->u.switch_result.cur_chan) {
+                       case TDLS_BASE_CHANNEL:
+                               sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
+                               break;
+                       case TDLS_OFF_CHANNEL:
+                               sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
+                               break;
+                       default:
+                               break;
+                       }
+                       return ret;
+               }
+
+               /* tdls channel switch success */
+               switch (tdls_evt->u.switch_result.cur_chan) {
+               case TDLS_BASE_CHANNEL:
+                       if (sta_ptr->tdls_status == TDLS_IN_BASE_CHAN)
+                               break;
+                       mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
+                                                                 false);
+                       sta_ptr->tdls_status = TDLS_IN_BASE_CHAN;
+                       break;
+               case TDLS_OFF_CHANNEL:
+                       if (sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)
+                               break;
+                       mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac,
+                                                                 true);
+                       sta_ptr->tdls_status = TDLS_IN_OFF_CHAN;
+                       break;
+               default:
+                       break;
+               }
+
+               break;
+       case TDLS_EVENT_START_CHAN_SWITCH:
+               mwifiex_dbg(adapter, EVENT, "tdls start channel switch...\n");
+               sta_ptr->tdls_status = TDLS_CHAN_SWITCHING;
+               break;
+       case TDLS_EVENT_CHAN_SWITCH_STOPPED:
+               mwifiex_dbg(adapter, EVENT,
+                           "tdls chan switch stopped, reason=%d\n",
+                           tdls_evt->u.cs_stop_reason);
+               break;
        default:
                break;
        }
@@ -182,6 +237,145 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
        return ret;
 }
 
+static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv,
+                                        struct mwifiex_ie_types_header *tlv)
+{
+       struct mwifiex_tx_pause_tlv *tp;
+       struct mwifiex_sta_node *sta_ptr;
+       unsigned long flags;
+
+       tp = (void *)tlv;
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "uap tx_pause: %pM pause=%d, pkts=%d\n",
+                   tp->peermac, tp->tx_pause,
+                   tp->pkt_cnt);
+
+       if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) {
+               if (tp->tx_pause)
+                       priv->port_open = false;
+               else
+                       priv->port_open = true;
+       } else if (is_multicast_ether_addr(tp->peermac)) {
+               mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause);
+       } else {
+               spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+               sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
+               spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+               if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
+                       sta_ptr->tx_pause = tp->tx_pause;
+                       mwifiex_update_ralist_tx_pause(priv, tp->peermac,
+                                                      tp->tx_pause);
+               }
+       }
+}
+
+static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv,
+                                        struct mwifiex_ie_types_header *tlv)
+{
+       struct mwifiex_tx_pause_tlv *tp;
+       struct mwifiex_sta_node *sta_ptr;
+       int status;
+       unsigned long flags;
+
+       tp = (void *)tlv;
+       mwifiex_dbg(priv->adapter, EVENT,
+                   "sta tx_pause: %pM pause=%d, pkts=%d\n",
+                   tp->peermac, tp->tx_pause,
+                   tp->pkt_cnt);
+
+       if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) {
+               if (tp->tx_pause)
+                       priv->port_open = false;
+               else
+                       priv->port_open = true;
+       } else {
+               if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+                       return;
+
+               status = mwifiex_get_tdls_link_status(priv, tp->peermac);
+               if (mwifiex_is_tdls_link_setup(status)) {
+                       spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+                       sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac);
+                       spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+
+                       if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) {
+                               sta_ptr->tx_pause = tp->tx_pause;
+                               mwifiex_update_ralist_tx_pause(priv,
+                                                              tp->peermac,
+                                                              tp->tx_pause);
+                       }
+               }
+       }
+}
+
+void mwifiex_process_multi_chan_event(struct mwifiex_private *priv,
+                                     struct sk_buff *event_skb)
+{
+       struct mwifiex_ie_types_multi_chan_info *chan_info;
+       u16 status;
+
+       chan_info = (void *)event_skb->data + sizeof(u32);
+
+       if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "unknown TLV in chan_info event\n");
+               return;
+       }
+
+       status = le16_to_cpu(chan_info->status);
+
+       if (status) {
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "multi-channel operation started\n");
+       } else {
+               mwifiex_dbg(priv->adapter, EVENT,
+                           "multi-channel operation over\n");
+       }
+}
+
+void mwifiex_process_tx_pause_event(struct mwifiex_private *priv,
+                                   struct sk_buff *event_skb)
+{
+       struct mwifiex_ie_types_header *tlv;
+       u16 tlv_type, tlv_len;
+       int tlv_buf_left;
+
+       if (!priv->media_connected) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "tx_pause event while disconnected; bss_role=%d\n",
+                           priv->bss_role);
+               return;
+       }
+
+       tlv_buf_left = event_skb->len - sizeof(u32);
+       tlv = (void *)event_skb->data + sizeof(u32);
+
+       while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) {
+               tlv_type = le16_to_cpu(tlv->type);
+               tlv_len  = le16_to_cpu(tlv->len);
+               if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) >
+                   tlv_buf_left) {
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n",
+                                   tlv_len, tlv_buf_left);
+                       break;
+               }
+               if (tlv_type == TLV_TYPE_TX_PAUSE) {
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
+                               mwifiex_process_sta_tx_pause(priv, tlv);
+                       else
+                               mwifiex_process_uap_tx_pause(priv, tlv);
+               }
+
+               tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) +
+                               tlv_len;
+               tlv = (void *)((u8 *)tlv + tlv_len +
+                              sizeof(struct mwifiex_ie_types_header));
+       }
+
+}
+
 /*
 * This function handles coex events generated by firmware
 */
@@ -359,7 +553,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
        case EVENT_PS_AWAKE:
                mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n");
-               if (!adapter->pps_uapsd_mode &&
+               if (!adapter->pps_uapsd_mode && priv->port_open &&
                    priv->media_connected && adapter->sleep_period.period) {
                                adapter->pps_uapsd_mode = true;
                                mwifiex_dbg(adapter, EVENT,
@@ -438,6 +632,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 
        case EVENT_PORT_RELEASE:
                mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n");
+               priv->port_open = true;
                break;
 
        case EVENT_EXT_SCAN_REPORT:
@@ -573,6 +768,16 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
                break;
 
+       case EVENT_TX_DATA_PAUSE:
+               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
+               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_MULTI_CHAN_INFO:
+               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
+               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
+               break;
+
        case EVENT_TX_STATUS_REPORT:
                mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n");
                mwifiex_parse_tx_status_event(priv, adapter->event_body);
index 2faa1bc42abee2eb838d65c6c75c33a243f53875..aa3d3c5ed07b3671b8d9064ff020f8fab998efcd 100644 (file)
@@ -49,7 +49,7 @@ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
                tid = skb->priority;
                tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
 
-               if (status == TDLS_SETUP_COMPLETE) {
+               if (mwifiex_is_tdls_link_setup(status)) {
                        ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac);
                        ra_list->tdls_link = true;
                        tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
@@ -355,6 +355,7 @@ static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv,
        extcap->ieee_hdr.len = 8;
        memset(extcap->ext_capab, 0, 8);
        extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED;
+       extcap->ext_capab[3] |= WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH;
 
        if (priv->adapter->is_hw_11ac_capable)
                extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED;
@@ -1071,6 +1072,11 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
                        for (i = 0; i < MAX_NUM_TID; i++)
                                sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
                }
+               if (sta_ptr->tdls_cap.extcap.ext_capab[3] &
+                   WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) {
+                       mwifiex_config_tdls_enable(priv);
+                       mwifiex_config_tdls_cs_params(priv);
+               }
 
                memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
                mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
@@ -1141,7 +1147,7 @@ int mwifiex_get_tdls_list(struct mwifiex_private *priv,
 
        spin_lock_irqsave(&priv->sta_list_spinlock, flags);
        list_for_each_entry(sta_ptr, &priv->sta_list, list) {
-               if (sta_ptr->tdls_status == TDLS_SETUP_COMPLETE) {
+               if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) {
                        ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr);
                        peer++;
                        count++;
@@ -1295,7 +1301,7 @@ void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
                        if ((link_status == TDLS_NOT_SETUP) &&
                            (peer->tdls_status == TDLS_SETUP_INPROGRESS))
                                peer->failure_count++;
-                       else if (link_status == TDLS_SETUP_COMPLETE)
+                       else if (mwifiex_is_tdls_link_setup(link_status))
                                peer->failure_count = 0;
 
                        peer->tdls_status = link_status;
@@ -1367,7 +1373,7 @@ void mwifiex_check_auto_tdls(unsigned long context)
 
                if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
                     !tdls_peer->rssi) &&
-                   tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) {
+                   mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) {
                        tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
                        mwifiex_dbg(priv->adapter, MSG,
                                    "teardown TDLS link,peer=%pM rssi=%d\n",
@@ -1416,3 +1422,67 @@ void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
                mwifiex_flush_auto_tdls_list(priv);
        }
 }
+
+static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable)
+{
+       struct mwifiex_tdls_config config;
+
+       config.enable = cpu_to_le16(enable);
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true);
+}
+
+int mwifiex_config_tdls_enable(struct mwifiex_private *priv)
+{
+       return mwifiex_config_tdls(priv, true);
+}
+
+int mwifiex_config_tdls_disable(struct mwifiex_private *priv)
+{
+       return mwifiex_config_tdls(priv, false);
+}
+
+int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv)
+{
+       struct mwifiex_tdls_config_cs_params config_tdls_cs_params;
+
+       config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME;
+       config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK;
+       config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_PARAMS, 0,
+                               &config_tdls_cs_params, true);
+}
+
+int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac)
+{
+       struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params;
+
+       ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac);
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_STOP, 0,
+                               &stop_tdls_cs_params, true);
+}
+
+int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac,
+                         u8 primary_chan, u8 second_chan_offset, u8 band)
+{
+       struct mwifiex_tdls_init_cs_params start_tdls_cs_params;
+
+       ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac);
+       start_tdls_cs_params.primary_chan = primary_chan;
+       start_tdls_cs_params.second_chan_offset = second_chan_offset;
+       start_tdls_cs_params.band = band;
+
+       start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME);
+       start_tdls_cs_params.switch_timeout =
+                                       cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT);
+       start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS;
+       start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG,
+                               ACT_TDLS_CS_INIT, 0,
+                               &start_tdls_cs_params, true);
+}
index 5ed9b794053e760163dda372f205fd28463a9efe..8b1e5b5d47feee82a634a8de5856a94a135884fe 100644 (file)
@@ -370,8 +370,28 @@ void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
                        /* consumes ack_skb */
                        skb_complete_wifi_ack(ack_skb, !tx_status->status);
                } else {
+                       /* Remove broadcast address which was added by driver */
+                       memmove(ack_skb->data +
+                               sizeof(struct ieee80211_hdr_3addr) +
+                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16),
+                               ack_skb->data +
+                               sizeof(struct ieee80211_hdr_3addr) +
+                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
+                               ETH_ALEN, ack_skb->len -
+                               (sizeof(struct ieee80211_hdr_3addr) +
+                               MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) +
+                               ETH_ALEN));
+                       ack_skb->len = ack_skb->len - ETH_ALEN;
+                       /* Remove driver's proprietary header including 2 bytes
+                        * of packet length and pass actual management frame buffer
+                        * to cfg80211.
+                        */
                        cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie,
-                                               ack_skb->data, ack_skb->len,
+                                               ack_skb->data +
+                                               MWIFIEX_MGMT_FRAME_HEADER_SIZE +
+                                               sizeof(u16), ack_skb->len -
+                                               (MWIFIEX_MGMT_FRAME_HEADER_SIZE
+                                                + sizeof(u16)),
                                                !tx_status->status, GFP_ATOMIC);
                        dev_kfree_skb_any(ack_skb);
                }
index b74930054b8c0b1f1cc2066ef2d22f2ca542ebb4..4d5a6e3b6361700c9bcab06201a70cd29d38b66e 100644 (file)
@@ -808,7 +808,7 @@ void mwifiex_uap_set_channel(struct mwifiex_private *priv,
                             struct mwifiex_uap_bss_param *bss_cfg,
                             struct cfg80211_chan_def chandef)
 {
-       u8 config_bands = 0;
+       u8 config_bands = 0, old_bands = priv->adapter->config_bands;
 
        priv->bss_chandef = chandef;
 
@@ -834,6 +834,11 @@ void mwifiex_uap_set_channel(struct mwifiex_private *priv,
        }
 
        priv->adapter->config_bands = config_bands;
+
+       if (old_bands != config_bands) {
+               mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy);
+               mwifiex_dnld_txpwr_table(priv);
+       }
 }
 
 int mwifiex_config_start_uap(struct mwifiex_private *priv,
index 7bc1f850e3b7195302577738ef3c546f4fddd92a..492a8b3c636e2bcaac9b0fb81620bbf1d1327cd2 100644 (file)
@@ -176,6 +176,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
        case EVENT_UAP_BSS_IDLE:
                priv->media_connected = false;
+               priv->port_open = false;
                if (netif_carrier_ok(priv->netdev))
                        netif_carrier_off(priv->netdev);
                mwifiex_stop_net_dev_queue(priv->netdev, adapter);
@@ -185,6 +186,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                break;
        case EVENT_UAP_BSS_ACTIVE:
                priv->media_connected = true;
+               priv->port_open = true;
                if (!netif_carrier_ok(priv->netdev))
                        netif_carrier_on(priv->netdev);
                mwifiex_wake_up_net_dev_queue(priv->netdev, adapter);
@@ -192,6 +194,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
        case EVENT_UAP_BSS_START:
                mwifiex_dbg(adapter, EVENT,
                            "AP EVENT: event id: %#x\n", eventcause);
+               priv->port_open = false;
                memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
                       ETH_ALEN);
                if (priv->hist_data)
@@ -297,6 +300,16 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                mwifiex_bt_coex_wlan_param_update_event(priv,
                                                        adapter->event_skb);
                break;
+       case EVENT_TX_DATA_PAUSE:
+               mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n");
+               mwifiex_process_tx_pause_event(priv, adapter->event_skb);
+               break;
+
+       case EVENT_MULTI_CHAN_INFO:
+               mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n");
+               mwifiex_process_multi_chan_event(priv, adapter->event_skb);
+               break;
+
        default:
                mwifiex_dbg(adapter, EVENT,
                            "event: unknown event id: %#x\n", eventcause);
index aada93425f806a74b481e937d7f25fab5a68d4d3..fbad99c503078ab9e2e840da438892a2067e92aa 100644 (file)
@@ -244,9 +244,11 @@ setup_for_next:
        if (card->rx_cmd_ep == context->ep) {
                mwifiex_usb_submit_rx_urb(context, size);
        } else {
-               context->skb = NULL;
-               if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING)
+               if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING){
                        mwifiex_usb_submit_rx_urb(context, size);
+               }else{
+                       context->skb = NULL;
+               }
        }
 
        return;
index 790e61953abffc8218ea3ecc6ec5cc2d4d9c630f..2504e422364a526246581a963969bcf87e4fc01b 100644 (file)
@@ -531,6 +531,65 @@ mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
        return NULL;
 }
 
+static struct mwifiex_sta_node *
+mwifiex_get_tdls_sta_entry(struct mwifiex_private *priv, u8 status)
+{
+       struct mwifiex_sta_node *node;
+
+       list_for_each_entry(node, &priv->sta_list, list) {
+               if (node->tdls_status == status)
+                       return node;
+       }
+
+       return NULL;
+}
+
+/* If tdls channel switching is on-going, tx data traffic should be
+ * blocked until the switching stage completed.
+ */
+u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv)
+{
+       struct mwifiex_sta_node *sta_ptr;
+
+       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return false;
+
+       sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_CHAN_SWITCHING);
+       if (sta_ptr)
+               return true;
+
+       return false;
+}
+
+u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv)
+{
+       struct mwifiex_sta_node *sta_ptr;
+
+       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return false;
+
+       sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_IN_OFF_CHAN);
+       if (sta_ptr)
+               return true;
+
+       return false;
+}
+
+/* If tdls channel switching is on-going or tdls operate on off-channel,
+ * cmd path should be blocked until tdls switched to base-channel.
+ */
+u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv)
+{
+       if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
+               return true;
+
+       if (mwifiex_is_tdls_chan_switching(priv) ||
+           mwifiex_is_tdls_off_chan(priv))
+               return false;
+
+       return true;
+}
+
 /* This function will add a sta_node entry to associated station list
  * table with the given mac address.
  * If entry exist already, existing entry is returned.
index a8ea21c3340c73537c8f597ad6dc2d176b45f588..173d3663c2e042bfe44e680e04acf86cf43f7c30 100644 (file)
@@ -160,9 +160,10 @@ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
                ra_list->tdls_link = false;
                ra_list->ba_status = BA_SETUP_NONE;
                ra_list->amsdu_in_ampdu = false;
+               ra_list->tx_paused = false;
                if (!mwifiex_queuing_ra_based(priv)) {
-                       if (mwifiex_get_tdls_link_status(priv, ra) ==
-                           TDLS_SETUP_COMPLETE) {
+                       if (mwifiex_is_tdls_link_setup
+                               (mwifiex_get_tdls_link_status(priv, ra))) {
                                ra_list->tdls_link = true;
                                ra_list->is_11n_enabled =
                                        mwifiex_tdls_peer_11n_enabled(priv, ra);
@@ -448,6 +449,11 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter)
        }
 }
 
+int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter)
+{
+       return atomic_read(&adapter->bypass_tx_pending) ? false : true;
+}
+
 /*
  * This function checks if WMM Tx queue is empty.
  */
@@ -459,6 +465,8 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter)
 
        for (i = 0; i < adapter->priv_num; ++i) {
                priv = adapter->priv[i];
+               if (priv && !priv->port_open)
+                       continue;
                if (priv && atomic_read(&priv->wmm.tx_pkts_queued))
                        return false;
        }
@@ -580,6 +588,10 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
        skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
                mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
 
+       skb_queue_walk_safe(&priv->bypass_txq, skb, tmp)
+               mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
+       atomic_set(&priv->adapter->bypass_tx_pending, 0);
+
        idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
        idr_destroy(&priv->ack_status_frames);
 }
@@ -603,6 +615,88 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
        return NULL;
 }
 
+void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
+                                   u8 tx_pause)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       u32 pkt_cnt = 0, tx_pkts_queued;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               ra_list = mwifiex_wmm_get_ralist_node(priv, i, mac);
+               if (ra_list && ra_list->tx_paused != tx_pause) {
+                       pkt_cnt += ra_list->total_pkt_count;
+                       ra_list->tx_paused = tx_pause;
+                       if (tx_pause)
+                               priv->wmm.pkts_paused[i] +=
+                                       ra_list->total_pkt_count;
+                       else
+                               priv->wmm.pkts_paused[i] -=
+                                       ra_list->total_pkt_count;
+               }
+       }
+
+       if (pkt_cnt) {
+               tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued);
+               if (tx_pause)
+                       tx_pkts_queued -= pkt_cnt;
+               else
+                       tx_pkts_queued += pkt_cnt;
+
+               atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
+               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
+       }
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
+/* This function update non-tdls peer ralist tx_pause while
+ * tdls channel swithing
+ */
+void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
+                                              u8 *mac, u8 tx_pause)
+{
+       struct mwifiex_ra_list_tbl *ra_list;
+       u32 pkt_cnt = 0, tx_pkts_queued;
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
+
+       for (i = 0; i < MAX_NUM_TID; ++i) {
+               list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[i].ra_list,
+                                   list) {
+                       if (!memcmp(ra_list->ra, mac, ETH_ALEN))
+                               continue;
+
+                       if (ra_list && ra_list->tx_paused != tx_pause) {
+                               pkt_cnt += ra_list->total_pkt_count;
+                               ra_list->tx_paused = tx_pause;
+                               if (tx_pause)
+                                       priv->wmm.pkts_paused[i] +=
+                                               ra_list->total_pkt_count;
+                               else
+                                       priv->wmm.pkts_paused[i] -=
+                                               ra_list->total_pkt_count;
+                       }
+               }
+       }
+
+       if (pkt_cnt) {
+               tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued);
+               if (tx_pause)
+                       tx_pkts_queued -= pkt_cnt;
+               else
+                       tx_pkts_queued += pkt_cnt;
+
+               atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued);
+               atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID);
+       }
+       spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
+}
+
 /*
  * This function retrieves an RA list node for a given TID and
  * RA address pair.
@@ -669,6 +763,18 @@ mwifiex_is_ralist_valid(struct mwifiex_private *priv,
        return false;
 }
 
+/*
+ * This function adds a packet to bypass TX queue.
+ * This is special TX queue for packets which can be sent even when port_open
+ * is false.
+ */
+void
+mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
+                                  struct sk_buff *skb)
+{
+       skb_queue_tail(&priv->bypass_txq, skb);
+}
+
 /*
  * This function adds a packet to WMM queue.
  *
@@ -723,6 +829,9 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
            !mwifiex_is_skb_mgmt_frame(skb)) {
                switch (tdls_status) {
                case TDLS_SETUP_COMPLETE:
+               case TDLS_CHAN_SWITCHING:
+               case TDLS_IN_BASE_CHAN:
+               case TDLS_IN_OFF_CHAN:
                        ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down,
                                                              ra);
                        tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT;
@@ -765,7 +874,10 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
                atomic_set(&priv->wmm.highest_queued_prio,
                           priv->tos_to_tid_inv[tid_down]);
 
-       atomic_inc(&priv->wmm.tx_pkts_queued);
+       if (ra_list->tx_paused)
+               priv->wmm.pkts_paused[tid_down]++;
+       else
+               atomic_inc(&priv->wmm.tx_pkts_queued);
 
        spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
 }
@@ -970,7 +1082,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
 
                        priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv;
 
-                       if (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)
+                       if (!priv_tmp->port_open ||
+                           (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0))
                                continue;
 
                        /* iterate over the WMM queues of the BSS */
@@ -987,7 +1100,8 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter,
                                list_for_each_entry(ptr, &tid_ptr->ra_list,
                                                    list) {
 
-                                       if (!skb_queue_empty(&ptr->skb_head))
+                                       if (!ptr->tx_paused &&
+                                           !skb_queue_empty(&ptr->skb_head))
                                                /* holds both locks */
                                                goto found;
                                }
@@ -1339,6 +1453,38 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
        return 0;
 }
 
+void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter)
+{
+       struct mwifiex_tx_param tx_param;
+       struct sk_buff *skb;
+       struct mwifiex_txinfo *tx_info;
+       struct mwifiex_private *priv;
+       int i;
+
+       if (adapter->data_sent || adapter->tx_lock_flag)
+               return;
+
+       for (i = 0; i < adapter->priv_num; ++i) {
+               priv = adapter->priv[i];
+
+               if (skb_queue_empty(&priv->bypass_txq))
+                       continue;
+
+               skb = skb_dequeue(&priv->bypass_txq);
+               tx_info = MWIFIEX_SKB_TXCB(skb);
+
+               /* no aggregation for bypass packets */
+               tx_param.next_pkt_len = 0;
+
+               if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) {
+                       skb_queue_head(&priv->bypass_txq, skb);
+                       tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
+               } else {
+                       atomic_dec(&adapter->bypass_tx_pending);
+               }
+       }
+}
+
 /*
  * This function transmits the highest priority packet awaiting in the
  * WMM Queues.
index 48ece0b355919d3c3a4278dfc1727fc391f5848d..38f09762bd2f93ba90ef341ac5d0deda575046dc 100644 (file)
@@ -99,12 +99,16 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
 
 void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
                                 struct sk_buff *skb);
+void mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv,
+                                       struct sk_buff *skb);
 void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra);
 void mwifiex_rotate_priolists(struct mwifiex_private *priv,
                              struct mwifiex_ra_list_tbl *ra, int tid);
 
 int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter);
+int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter);
 void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter);
+void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter);
 int mwifiex_is_ralist_valid(struct mwifiex_private *priv,
                            struct mwifiex_ra_list_tbl *ra_list, int tid);
 
@@ -126,6 +130,10 @@ struct mwifiex_ra_list_tbl *
 mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
                            const u8 *ra_addr);
 u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid);
+void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac,
+                                   u8 tx_pause);
+void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv,
+                                              u8 *mac, u8 tx_pause);
 
 struct mwifiex_ra_list_tbl *mwifiex_wmm_get_ralist_node(struct mwifiex_private
                                        *priv, u8 tid, const u8 *ra_addr);
index c940a87175ca15d701bad48abbe2be5dd755091c..74a479ac323d53716e5e9b02f7d179d4370ae5c5 100644 (file)
 /*-------------------------------------------------------------------------
  *     Chip specific
  *-------------------------------------------------------------------------*/
-#define CHIP_8723                      BIT(2) /* RTL8723 With BT feature */
-#define CHIP_8723_DRV_REV              BIT(3) /* RTL8723 Driver Revised */
 #define NORMAL_CHIP                    BIT(4)
 #define CHIP_VENDOR_UMC                        BIT(5)
 #define CHIP_VENDOR_UMC_B_CUT          BIT(6)
 
-#define IS_8723_SERIES(version)                \
-       (((version) & CHIP_8723) ? true : false)
-
 #define IS_92C_1T2R(version)           \
        (((version) & CHIP_92C) && ((version) & CHIP_92C_1T2R))
 
 #define IS_VENDOR_UMC(version)         \
        (((version) & CHIP_VENDOR_UMC) ? true : false)
 
-#define IS_VENDOR_8723_A_CUT(version)  \
-       (((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6))) ? \
-       false : true) : false)
-
 #define CHIP_BONDING_92C_1T2R  0x1
 #define CHIP_BONDING_IDENTIFIER(_value)        (((_value) >> 22) & 0x3)
index 767358a553fb083dcc39297fe6f7ef6be74cbad4..7cf36619f25005e4395251ba663b2b15cd14e41a 100644 (file)
@@ -2280,7 +2280,6 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
        u8 u1tmp = 0;
        bool actuallyset = false;
@@ -2357,20 +2356,7 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
                if (ppsc->pwrdown_mode && e_rfpowerstate_toset == ERFOFF) {
                        /* Enable register area 0x0-0xc. */
                        rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0);
-                       if (IS_HARDWARE_TYPE_8723U(rtlhal)) {
-                               /*
-                                * We should configure HW PDn source for WiFi
-                                * ONLY, and then our HW will be set in
-                                * power-down mode if PDn source from all
-                                * functions are configured.
-                                */
-                               u1tmp = rtl_read_byte(rtlpriv,
-                                                     REG_MULTI_FUNC_CTRL);
-                               rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL,
-                                              (u1tmp|WL_HWPDN_EN));
-                       } else {
-                               rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x8812);
-                       }
+                       rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x8812);
                }
                if (e_rfpowerstate_toset == ERFOFF) {
                        if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM)
index 490a7cf7c702fa263b0f392b2ed103d0c4df6848..1c55a002d4bd9d9cc48986483a29cbfd5228b0ab 100644 (file)
@@ -69,8 +69,6 @@ void rtl92c_read_chip_version(struct ieee80211_hw *hw)
                chip_version = NORMAL_CHIP;
                chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0);
                chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0);
-               /* RTL8723 with BT function. */
-               chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0);
                if (IS_VENDOR_UMC(chip_version))
                        chip_version |= ((value32 & CHIP_VER_RTL_MASK) ?
                                         CHIP_VENDOR_UMC_B_CUT : 0);
@@ -78,10 +76,6 @@ void rtl92c_read_chip_version(struct ieee80211_hw *hw)
                        value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
                        chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) ==
                                 CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0);
-               } else if (IS_8723_SERIES(chip_version)) {
-                       value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
-                       chip_version |= ((value32 & RF_RL_ID) ?
-                                         CHIP_8723_DRV_REV : 0);
                }
        }
        rtlhal->version  = (enum version_8192c)chip_version;
@@ -114,12 +108,6 @@ void rtl92c_read_chip_version(struct ieee80211_hw *hw)
        case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
                versionid = "NORMAL_UMC_CHIP_88C_B_CUT";
                break;
-       case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT:
-               versionid = "NORMAL_UMC_CHIP_8723_1T1R_A_CUT";
-               break;
-       case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT:
-               versionid = "NORMAL_UMC_CHIP_8723_1T1R_B_CUT";
-               break;
        case VERSION_TEST_CHIP_92C:
                versionid = "TEST_CHIP_92C";
                break;
index 1961b8e28dc16eb7261bc267641cf64b06791b77..bb06fe836fe753037925bf18dcfa6f8d4186ffb8 100644 (file)
@@ -3515,14 +3515,14 @@ void rtl92d_update_bbrf_configuration(struct ieee80211_hw *hw)
        for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
             rfpath++) {
                if (rtlhal->current_bandtype == BAND_ON_2_4G) {
-                       /* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+                       /* MOD_AG for RF path_A 0x18 BIT8,BIT16 */
                        rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) | BIT(16) |
                                      BIT(18), 0);
                        /* RF0x0b[16:14] =3b'111 */
                        rtl_set_rfreg(hw, (enum radio_path)rfpath, 0x0B,
                                      0x1c000, 0x07);
                } else {
-                       /* MOD_AG for RF paht_A 0x18 BIT8,BIT16 */
+                       /* MOD_AG for RF path_A 0x18 BIT8,BIT16 */
                        rtl_set_rfreg(hw, rfpath, RF_CHNLBW, BIT(8) |
                                      BIT(16) | BIT(18),
                                      (BIT(16) | BIT(8)) >> 8);
index 3236d44b459df69efd4f2b363f4b651e478a10a4..b7f18e2155eb18358cf4d4f9f3f82774f9b6f522 100644 (file)
@@ -2180,7 +2180,7 @@ static int _rtl8821ae_set_media_status(struct ieee80211_hw *hw,
 
        rtl_write_byte(rtlpriv, MSR, bt_msr);
        rtlpriv->cfg->ops->led_control(hw, ledaction);
-       if ((bt_msr & 0xfc) == MSR_AP)
+       if ((bt_msr & MSR_MASK) == MSR_AP)
                rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
        else
                rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
index 53668fc8f23e211dab03085359ce013fc65b81c2..1d6110f9c1fb6e29e75e8bde9c1533b026a8b757 100644 (file)
 #define        MSR_ADHOC                               0x01
 #define        MSR_INFRA                               0x02
 #define        MSR_AP                                  0x03
+#define MSR_MASK                               0x03
 
 #define        RRSR_RSC_OFFSET                         21
 #define        RRSR_SHORT_OFFSET                       23
index e125974285cc890e0b40671886815c996ef37a11..7df672a84530b0217378d8f9b66c2e10d31e044e 100644 (file)
@@ -74,7 +74,8 @@ static void wl1271_rx_status(struct wl1271 *wl,
        if (desc->rate <= wl->hw_min_ht_rate)
                status->flag |= RX_FLAG_HT;
 
-       status->signal = desc->rssi;
+       status->signal = ((desc->rssi & RSSI_LEVEL_BITMASK) | BIT(7));
+       status->antenna = ((desc->rssi & ANT_DIVERSITY_BITMASK) >> 7);
 
        /*
         * FIXME: In wl1251, the SNR should be divided by two.  In wl1271 we
index a3b1618db27c202db4377c8e529aee4751c8c32a..f5a7087cfb97831fea0296186d59b3acbc0d7ac5 100644 (file)
@@ -30,6 +30,9 @@
 #define WL1271_RX_MAX_RSSI -30
 #define WL1271_RX_MIN_RSSI -95
 
+#define RSSI_LEVEL_BITMASK     0x7F
+#define ANT_DIVERSITY_BITMASK  BIT(7)
+
 #define SHORT_PREAMBLE_BIT   BIT(0)
 #define OFDM_RATE_BIT        BIT(6)
 #define PBCC_RATE_BIT        BIT(7)
index ea7e07abca4ebaccd37eaa1aac75567453b3e0a0..c172da56b550b8a59f88f5206a0160c1a878f5bb 100644 (file)
@@ -293,7 +293,8 @@ static int wl1271_probe(struct sdio_func *func,
        /* Use block mode for transferring over one block size of data */
        func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
 
-       if (wlcore_probe_of(&func->dev, &irq, &pdev_data))
+       ret = wlcore_probe_of(&func->dev, &irq, &pdev_data);
+       if (ret)
                goto out_free_glue;
 
        /* if sdio can keep power while host is suspended, enable wow */