Merge ath-next from ath.git
authorKalle Valo <kvalo@codeaurora.org>
Thu, 3 Dec 2015 15:10:25 +0000 (17:10 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 3 Dec 2015 15:10:25 +0000 (17:10 +0200)
Major changes:

ath10k

* support Manegement Frame Protection (MFP)
* add thermal throttling support for 10.4 firmware
* add support for pktlog in QCA99X0
* add debugfs file to enable Bluetooth coexistence feature
* use firmware's native mesh interface type instead of raw mode

20 files changed:
drivers/net/wireless/ath/ath10k/Kconfig
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/debug.h
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.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/thermal.c
drivers/net/wireless/ath/ath10k/txrx.c
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi-tlv.h
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/txrx.c

index 72acb82..03aa35f 100644 (file)
@@ -2,6 +2,7 @@ config ATH10K
         tristate "Atheros 802.11ac wireless cards support"
         depends on MAC80211 && HAS_DMA
        select ATH_COMMON
+       select CRC32
         ---help---
           This module adds support for wireless adapters based on
           Atheros IEEE 802.11ac family of chipsets.
index aa9bd92..fca702c 100644 (file)
@@ -58,6 +58,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        .dir = QCA988X_HW_2_0_FW_DIR,
                        .fw = QCA988X_HW_2_0_FW_FILE,
@@ -75,6 +76,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
                        .fw = QCA6174_HW_2_1_FW_FILE,
@@ -92,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        .dir = QCA6174_HW_3_0_FW_DIR,
                        .fw = QCA6174_HW_3_0_FW_FILE,
@@ -109,6 +112,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
                .fw = {
                        /* uses same binaries as hw3.0 */
                        .dir = QCA6174_HW_3_0_FW_DIR,
@@ -128,6 +132,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .continuous_frag_desc = true,
                .channel_counters_freq_hz = 150000,
                .max_probe_resp_desc_thres = 24,
+               .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
                .fw = {
                        .dir = QCA99X0_HW_2_0_FW_DIR,
                        .fw = QCA99X0_HW_2_0_FW_FILE,
@@ -167,6 +172,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
        [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
        [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
        [ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
+       [ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
 };
 
 static unsigned int ath10k_core_get_fw_feature_str(char *buf,
@@ -843,7 +849,7 @@ out:
        if (!ar->board_data || !ar->board_len) {
                ath10k_err(ar,
                           "failed to fetch board data for %s from %s/%s\n",
-                          ar->hw_params.fw.dir, boardname, filename);
+                          boardname, ar->hw_params.fw.dir, filename);
                ret = -ENODATA;
                goto err;
        }
@@ -1745,9 +1751,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
                goto err_power_down;
        }
 
+       ath10k_debug_print_hwfw_info(ar);
+
        ret = ath10k_core_get_board_id_from_otp(ar);
        if (ret && ret != -EOPNOTSUPP) {
-               ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n",
+               ath10k_err(ar, "failed to get board id from otp: %d\n",
                           ret);
                return ret;
        }
@@ -1758,6 +1766,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
                goto err_free_firmware_files;
        }
 
+       ath10k_debug_print_board_info(ar);
+
        ret = ath10k_core_init_firmware_features(ar);
        if (ret) {
                ath10k_err(ar, "fatal problem with firmware features: %d\n",
@@ -1780,7 +1790,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
                goto err_unlock;
        }
 
-       ath10k_print_driver_info(ar);
+       ath10k_debug_print_boot_info(ar);
        ath10k_core_stop(ar);
 
        mutex_unlock(&ar->conf_mutex);
index 018c64f..3c8a510 100644 (file)
@@ -81,26 +81,20 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
        return "unknown";
 }
 
+enum ath10k_skb_flags {
+       ATH10K_SKB_F_NO_HWCRYPT = BIT(0),
+       ATH10K_SKB_F_DTIM_ZERO = BIT(1),
+       ATH10K_SKB_F_DELIVER_CAB = BIT(2),
+       ATH10K_SKB_F_MGMT = BIT(3),
+       ATH10K_SKB_F_QOS = BIT(4),
+};
+
 struct ath10k_skb_cb {
        dma_addr_t paddr;
+       u8 flags;
        u8 eid;
-       u8 vdev_id;
-       enum ath10k_hw_txrx_mode txmode;
-       bool is_protected;
-
-       struct {
-               u8 tid;
-               u16 freq;
-               bool is_offchan;
-               bool nohwcrypt;
-               struct ath10k_htt_txbuf *txbuf;
-               u32 txbuf_paddr;
-       } __packed htt;
-
-       struct {
-               bool dtim_zero;
-               bool deliver_cab;
-       } bcn;
+       u16 msdu_id;
+       struct ieee80211_vif *vif;
 } __packed;
 
 struct ath10k_skb_rxcb {
@@ -151,6 +145,7 @@ struct ath10k_wmi {
        struct wmi_vdev_param_map *vdev_param;
        struct wmi_pdev_param_map *pdev_param;
        const struct wmi_ops *ops;
+       const struct wmi_peer_flags_map *peer_flags;
 
        u32 num_mem_chunks;
        u32 rx_decap_mode;
@@ -512,6 +507,9 @@ enum ath10k_fw_features {
        /* Firmware Supports Adaptive CCA*/
        ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
 
+       /* Firmware supports management frame protection */
+       ATH10K_FW_FEATURE_MFP_SUPPORT = 12,
+
        /* keep last */
        ATH10K_FW_FEATURE_COUNT,
 };
@@ -534,6 +532,9 @@ enum ath10k_dev_flags {
 
        /* Disable HW crypto engine */
        ATH10K_FLAG_HW_CRYPTO_DISABLED,
+
+       /* Bluetooth coexistance enabled */
+       ATH10K_FLAG_BTCOEX,
 };
 
 enum ath10k_cal_mode {
@@ -661,6 +662,9 @@ struct ath10k {
                 */
                u32 max_probe_resp_desc_thres;
 
+               /* The padding bytes's location is different on various chips */
+               enum ath10k_hw_4addr_pad hw_4addr_pad;
+
                struct ath10k_hw_params_fw {
                        const char *dir;
                        const char *fw;
index 6cc1aa3..39fe4f3 100644 (file)
@@ -19,6 +19,8 @@
 #include <linux/debugfs.h>
 #include <linux/vmalloc.h>
 #include <linux/utsname.h>
+#include <linux/crc32.h>
+#include <linux/firmware.h>
 
 #include "core.h"
 #include "debug.h"
@@ -122,28 +124,51 @@ void ath10k_info(struct ath10k *ar, const char *fmt, ...)
 }
 EXPORT_SYMBOL(ath10k_info);
 
-void ath10k_print_driver_info(struct ath10k *ar)
+void ath10k_debug_print_hwfw_info(struct ath10k *ar)
 {
        char fw_features[128] = {};
-       char boardinfo[100];
 
        ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
 
-       if (ar->id.bmi_ids_valid)
-               scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
-                         ar->id.bmi_chip_id, ar->id.bmi_board_id);
-       else
-               scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
-                         ar->id.subsystem_vendor, ar->id.subsystem_device);
-
-       ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
+       ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
                    ar->hw_params.name,
                    ar->target_version,
                    ar->chip_id,
-                   boardinfo,
+                   ar->id.subsystem_vendor, ar->id.subsystem_device);
+
+       ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
+                   config_enabled(CONFIG_ATH10K_DEBUG),
+                   config_enabled(CONFIG_ATH10K_DEBUGFS),
+                   config_enabled(CONFIG_ATH10K_TRACING),
+                   config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
+                   config_enabled(CONFIG_NL80211_TESTMODE));
+
+       ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
                    ar->hw->wiphy->fw_version,
                    ar->fw_api,
+                   fw_features,
+                   crc32_le(0, ar->firmware->data, ar->firmware->size));
+}
+
+void ath10k_debug_print_board_info(struct ath10k *ar)
+{
+       char boardinfo[100];
+
+       if (ar->id.bmi_ids_valid)
+               scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
+                         ar->id.bmi_chip_id, ar->id.bmi_board_id);
+       else
+               scnprintf(boardinfo, sizeof(boardinfo), "N/A");
+
+       ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
                    ar->bd_api,
+                   boardinfo,
+                   crc32_le(0, ar->board->data, ar->board->size));
+}
+
+void ath10k_debug_print_boot_info(struct ath10k *ar)
+{
+       ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
                    ar->htt.target_version_major,
                    ar->htt.target_version_minor,
                    ar->wmi.op_version,
@@ -151,14 +176,14 @@ void ath10k_print_driver_info(struct ath10k *ar)
                    ath10k_cal_mode_str(ar->cal_mode),
                    ar->max_num_stations,
                    test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
-                   !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
-                   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),
-                   config_enabled(CONFIG_ATH10K_TRACING),
-                   config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
-                   config_enabled(CONFIG_NL80211_TESTMODE));
+                   !test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
+}
+
+void ath10k_print_driver_info(struct ath10k *ar)
+{
+       ath10k_debug_print_hwfw_info(ar);
+       ath10k_debug_print_board_info(ar);
+       ath10k_debug_print_boot_info(ar);
 }
 EXPORT_SYMBOL(ath10k_print_driver_info);
 
@@ -2074,6 +2099,121 @@ static const struct file_operations fops_quiet_period = {
        .open = simple_open
 };
 
+static ssize_t ath10k_write_btcoex(struct file *file,
+                                  const char __user *ubuf,
+                                  size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       char buf[32];
+       size_t buf_size;
+       bool val;
+
+       buf_size = min(count, (sizeof(buf) - 1));
+       if (copy_from_user(buf, ubuf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
+               goto exit;
+
+       if (val)
+               set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+       else
+               clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+
+       if (ar->state != ATH10K_STATE_ON)
+               goto exit;
+
+       ath10k_info(ar, "restarting firmware due to btcoex change");
+
+       queue_work(ar->workqueue, &ar->restart_work);
+
+exit:
+       mutex_unlock(&ar->conf_mutex);
+
+       return count;
+}
+
+static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
+                                 size_t count, loff_t *ppos)
+{
+       char buf[32];
+       struct ath10k *ar = file->private_data;
+       int len = 0;
+
+       mutex_lock(&ar->conf_mutex);
+       len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+                       test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
+       mutex_unlock(&ar->conf_mutex);
+
+       return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_btcoex = {
+       .read = ath10k_read_btcoex,
+       .write = ath10k_write_btcoex,
+       .open = simple_open
+};
+
+static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
+                                             char __user *user_buf,
+                                             size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       unsigned int len = 0, buf_len = 4096;
+       ssize_t ret_cnt;
+       char *buf;
+
+       buf = kzalloc(buf_len, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (len > buf_len)
+               len = buf_len;
+
+       len += scnprintf(buf + len, buf_len - len,
+                        "firmware-N.bin\t\t%08x\n",
+                        crc32_le(0, ar->firmware->data, ar->firmware->size));
+       len += scnprintf(buf + len, buf_len - len,
+                        "athwlan\t\t\t%08x\n",
+                        crc32_le(0, ar->firmware_data, ar->firmware_len));
+       len += scnprintf(buf + len, buf_len - len,
+                        "otp\t\t\t%08x\n",
+                        crc32_le(0, ar->otp_data, ar->otp_len));
+       len += scnprintf(buf + len, buf_len - len,
+                        "codeswap\t\t%08x\n",
+                        crc32_le(0, ar->swap.firmware_codeswap_data,
+                                 ar->swap.firmware_codeswap_len));
+       len += scnprintf(buf + len, buf_len - len,
+                        "board-N.bin\t\t%08x\n",
+                        crc32_le(0, ar->board->data, ar->board->size));
+       len += scnprintf(buf + len, buf_len - len,
+                        "board\t\t\t%08x\n",
+                        crc32_le(0, ar->board_data, ar->board_len));
+
+       ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+
+       mutex_unlock(&ar->conf_mutex);
+
+       kfree(buf);
+       return ret_cnt;
+}
+
+static const struct file_operations fops_fw_checksums = {
+       .read = ath10k_debug_fw_checksums_read,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
+
 int ath10k_debug_create(struct ath10k *ar)
 {
        ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
@@ -2123,8 +2263,8 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
                            &fops_wmi_services);
 
-       debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
-                           ar, &fops_simulate_fw_crash);
+       debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
+                           ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
 
        debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
                            ar, &fops_fw_crash_dump);
@@ -2141,15 +2281,15 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
                            ar, &fops_chip_id);
 
-       debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
-                           ar, &fops_htt_stats_mask);
+       debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
+                           ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
 
        debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
                            ar->debug.debugfs_phy, ar,
                            &fops_htt_max_amsdu_ampdu);
 
-       debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
-                           ar, &fops_fw_dbglog);
+       debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
+                           ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
 
        debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
                            ar, &fops_cal_data);
@@ -2183,6 +2323,13 @@ int ath10k_debug_register(struct ath10k *ar)
        debugfs_create_file("tpc_stats", S_IRUSR,
                            ar->debug.debugfs_phy, ar, &fops_tpc_stats);
 
+       if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
+               debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
+                                   ar->debug.debugfs_phy, ar, &fops_btcoex);
+
+       debugfs_create_file("fw_checksums", S_IRUSR,
+                           ar->debug.debugfs_phy, ar, &fops_fw_checksums);
+
        return 0;
 }
 
index 7de780c..814719c 100644 (file)
@@ -63,6 +63,10 @@ extern unsigned int ath10k_debug_mask;
 __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
 __printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
 __printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
+
+void ath10k_debug_print_hwfw_info(struct ath10k *ar);
+void ath10k_debug_print_board_info(struct ath10k *ar);
+void ath10k_debug_print_boot_info(struct ath10k *ar);
 void ath10k_print_driver_info(struct ath10k *ar);
 
 #ifdef CONFIG_ATH10K_DEBUGFS
index 2bad50e..47ca048 100644 (file)
@@ -166,8 +166,13 @@ struct htt_data_tx_desc {
        __le16 len;
        __le16 id;
        __le32 frags_paddr;
-       __le16 peerid;
-       __le16 freq;
+       union {
+               __le32 peerid;
+               struct {
+                       __le16 peerid;
+                       __le16 freq;
+               } __packed offchan_tx;
+       } __packed;
        u8 prefetch[0]; /* start of frame, for FW classification engine */
 } __packed;
 
@@ -1597,6 +1602,10 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
 int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
 void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
 int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
-int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *);
+int ath10k_htt_tx(struct ath10k_htt *htt,
+                 enum ath10k_hw_txrx_mode txmode,
+                 struct sk_buff *msdu);
+void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
+                                            struct sk_buff *skb);
 
 #endif
index 6060dda..91afa3a 100644 (file)
@@ -536,7 +536,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 
        size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
 
-       vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
+       vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_KERNEL);
        if (!vaddr)
                goto err_dma_ring;
 
@@ -545,7 +545,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
 
        vaddr = dma_alloc_coherent(htt->ar->dev,
                                   sizeof(*htt->rx_ring.alloc_idx.vaddr),
-                                  &paddr, GFP_DMA);
+                                  &paddr, GFP_KERNEL);
        if (!vaddr)
                goto err_dma_idx;
 
@@ -674,7 +674,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
                rate &= ~RX_PPDU_START_RATE_FLAG;
 
                sband = &ar->mac.sbands[status->band];
-               status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
+               status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate, cck);
                break;
        case HTT_RX_HT:
        case HTT_RX_HT_WITH_TXBF:
@@ -1114,7 +1114,20 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
         */
 
        /* pull decapped header and copy SA & DA */
-       hdr = (struct ieee80211_hdr *)msdu->data;
+       if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) &&
+           ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) {
+               /* The QCA99X0 4 address mode pad 2 bytes at the
+                * beginning of MSDU
+                */
+               hdr = (struct ieee80211_hdr *)(msdu->data + 2);
+               /* The skb length need be extended 2 as the 2 bytes at the tail
+                * be excluded due to the padding
+                */
+               skb_put(msdu, 2);
+       } else {
+               hdr = (struct ieee80211_hdr *)(msdu->data);
+       }
+
        hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
        ether_addr_copy(da, ieee80211_get_DA(hdr));
        ether_addr_copy(sa, ieee80211_get_SA(hdr));
@@ -2127,6 +2140,18 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
 
+void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
+                                            struct sk_buff *skb)
+{
+       struct ath10k_pktlog_10_4_hdr *hdr =
+               (struct ath10k_pktlog_10_4_hdr *)skb->data;
+
+       trace_ath10k_htt_pktlog(ar, hdr->payload,
+                               sizeof(*hdr) + __le16_to_cpu(hdr->size));
+       dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
+
 static void ath10k_htt_txrx_compl_task(unsigned long ptr)
 {
        struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
index 1682397..b3adadb 100644 (file)
@@ -111,7 +111,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
        size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
        htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
                                                  &htt->txbuf.paddr,
-                                                 GFP_DMA);
+                                                 GFP_KERNEL);
        if (!htt->txbuf.vaddr) {
                ath10k_err(ar, "failed to alloc tx buffer\n");
                ret = -ENOMEM;
@@ -124,7 +124,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
        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);
+                                                 GFP_KERNEL);
        if (!htt->frag_desc.vaddr) {
                ath10k_warn(ar, "failed to alloc fragment desc memory\n");
                ret = -ENOMEM;
@@ -439,6 +439,35 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
        return 0;
 }
 
+static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
+       struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
+
+       if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+               return ar->scan.vdev_id;
+       else if (cb->vif)
+               return arvif->vdev_id;
+       else if (ar->monitor_started)
+               return ar->monitor_vdev_id;
+       else
+               return 0;
+}
+
+static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
+{
+       struct ieee80211_hdr *hdr = (void *)skb->data;
+       struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
+
+       if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
+               return HTT_DATA_TX_EXT_TID_MGMT;
+       else if (cb->flags & ATH10K_SKB_F_QOS)
+               return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
+       else
+               return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
+}
+
 int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 {
        struct ath10k *ar = htt->ar;
@@ -446,7 +475,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
        struct sk_buff *txdesc = NULL;
        struct htt_cmd *cmd;
        struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
-       u8 vdev_id = skb_cb->vdev_id;
+       u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
        int len = 0;
        int msdu_id = -1;
        int res;
@@ -477,6 +506,13 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 
        msdu_id = res;
 
+       if ((ieee80211_is_action(hdr->frame_control) ||
+            ieee80211_is_deauth(hdr->frame_control) ||
+            ieee80211_is_disassoc(hdr->frame_control)) &&
+            ieee80211_has_protected(hdr->frame_control)) {
+               skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
+       }
+
        txdesc = ath10k_htc_alloc_skb(ar, len);
        if (!txdesc) {
                res = -ENOMEM;
@@ -503,8 +539,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
        memcpy(cmd->mgmt_tx.hdr, msdu->data,
               min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN));
 
-       skb_cb->htt.txbuf = NULL;
-
        res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
        if (res)
                goto err_unmap_msdu;
@@ -525,21 +559,27 @@ err:
        return res;
 }
 
-int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
+int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
+                 struct sk_buff *msdu)
 {
        struct ath10k *ar = htt->ar;
        struct device *dev = ar->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
        struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
        struct ath10k_hif_sg_item sg_items[2];
+       struct ath10k_htt_txbuf *txbuf;
        struct htt_data_tx_desc_frag *frags;
-       u8 vdev_id = skb_cb->vdev_id;
-       u8 tid = skb_cb->htt.tid;
+       bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
+       u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
+       u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
        int prefetch_len;
        int res;
        u8 flags0 = 0;
        u16 msdu_id, flags1 = 0;
+       u16 freq = 0;
        u32 frags_paddr = 0;
+       u32 txbuf_paddr;
        struct htt_msdu_ext_desc *ext_desc = NULL;
        bool limit_mgmt_desc = false;
        bool is_probe_resp = false;
@@ -567,17 +607,17 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
        prefetch_len = min(htt->prefetch_len, msdu->len);
        prefetch_len = roundup(prefetch_len, 4);
 
-       skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id];
-       skb_cb->htt.txbuf_paddr = htt->txbuf.paddr +
-               (sizeof(struct ath10k_htt_txbuf) * msdu_id);
+       txbuf = &htt->txbuf.vaddr[msdu_id];
+       txbuf_paddr = htt->txbuf.paddr +
+                     (sizeof(struct ath10k_htt_txbuf) * msdu_id);
 
        if ((ieee80211_is_action(hdr->frame_control) ||
             ieee80211_is_deauth(hdr->frame_control) ||
             ieee80211_is_disassoc(hdr->frame_control)) &&
             ieee80211_has_protected(hdr->frame_control)) {
                skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
-       } else if (!skb_cb->htt.nohwcrypt &&
-                  skb_cb->txmode == ATH10K_HW_TXRX_RAW &&
+       } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
+                  txmode == ATH10K_HW_TXRX_RAW &&
                   ieee80211_has_protected(hdr->frame_control)) {
                skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
        }
@@ -590,7 +630,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
                goto err_free_msdu_id;
        }
 
-       switch (skb_cb->txmode) {
+       if (unlikely(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
+               freq = ar->scan.roc_freq;
+
+       switch (txmode) {
        case ATH10K_HW_TXRX_RAW:
        case ATH10K_HW_TXRX_NATIVE_WIFI:
                flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
@@ -610,16 +653,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
                        frags_paddr =  htt->frag_desc.paddr +
                                (sizeof(struct htt_msdu_ext_desc) * msdu_id);
                } else {
-                       frags = skb_cb->htt.txbuf->frags;
+                       frags = txbuf->frags;
                        frags[0].dword_addr.paddr =
                                __cpu_to_le32(skb_cb->paddr);
                        frags[0].dword_addr.len = __cpu_to_le32(msdu->len);
                        frags[1].dword_addr.paddr = 0;
                        frags[1].dword_addr.len = 0;
 
-                       frags_paddr = skb_cb->htt.txbuf_paddr;
+                       frags_paddr = txbuf_paddr;
                }
-               flags0 |= SM(skb_cb->txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
+               flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
                break;
        case ATH10K_HW_TXRX_MGMT:
                flags0 |= SM(ATH10K_HW_TXRX_MGMT,
@@ -646,17 +689,13 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
         * avoid extra memory allocations, compress data structures and thus
         * improve performance. */
 
-       skb_cb->htt.txbuf->htc_hdr.eid = htt->eid;
-       skb_cb->htt.txbuf->htc_hdr.len = __cpu_to_le16(
-                       sizeof(skb_cb->htt.txbuf->cmd_hdr) +
-                       sizeof(skb_cb->htt.txbuf->cmd_tx) +
-                       prefetch_len);
-       skb_cb->htt.txbuf->htc_hdr.flags = 0;
-
-       if (skb_cb->htt.nohwcrypt)
-               flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
+       txbuf->htc_hdr.eid = htt->eid;
+       txbuf->htc_hdr.len = __cpu_to_le16(sizeof(txbuf->cmd_hdr) +
+                                          sizeof(txbuf->cmd_tx) +
+                                          prefetch_len);
+       txbuf->htc_hdr.flags = 0;
 
-       if (!skb_cb->is_protected)
+       if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
                flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
 
        flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
@@ -675,20 +714,27 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
         */
        flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
 
-       skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
-       skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
-       skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
-       skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
-       skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
-       skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
-       skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
-       skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
+       txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
+       txbuf->cmd_tx.flags0 = flags0;
+       txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
+       txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
+       txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
+       txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
+       if (ath10k_mac_tx_frm_has_freq(ar)) {
+               txbuf->cmd_tx.offchan_tx.peerid =
+                               __cpu_to_le16(HTT_INVALID_PEERID);
+               txbuf->cmd_tx.offchan_tx.freq =
+                               __cpu_to_le16(freq);
+       } else {
+               txbuf->cmd_tx.peerid =
+                               __cpu_to_le32(HTT_INVALID_PEERID);
+       }
 
        trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
        ath10k_dbg(ar, ATH10K_DBG_HTT,
                   "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
                   flags0, flags1, msdu->len, msdu_id, frags_paddr,
-                  (u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
+                  (u32)skb_cb->paddr, vdev_id, tid, freq);
        ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
                        msdu->data, msdu->len);
        trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
@@ -696,12 +742,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
 
        sg_items[0].transfer_id = 0;
        sg_items[0].transfer_context = NULL;
-       sg_items[0].vaddr = &skb_cb->htt.txbuf->htc_hdr;
-       sg_items[0].paddr = skb_cb->htt.txbuf_paddr +
-                           sizeof(skb_cb->htt.txbuf->frags);
-       sg_items[0].len = sizeof(skb_cb->htt.txbuf->htc_hdr) +
-                         sizeof(skb_cb->htt.txbuf->cmd_hdr) +
-                         sizeof(skb_cb->htt.txbuf->cmd_tx);
+       sg_items[0].vaddr = &txbuf->htc_hdr;
+       sg_items[0].paddr = txbuf_paddr +
+                           sizeof(txbuf->frags);
+       sg_items[0].len = sizeof(txbuf->htc_hdr) +
+                         sizeof(txbuf->cmd_hdr) +
+                         sizeof(txbuf->cmd_tx);
 
        sg_items[1].transfer_id = 0;
        sg_items[1].transfer_context = NULL;
index 39966a0..b99b691 100644 (file)
@@ -273,6 +273,16 @@ struct ath10k_pktlog_hdr {
        u8 payload[0];
 } __packed;
 
+struct ath10k_pktlog_10_4_hdr {
+       __le16 flags;
+       __le16 missed_cnt;
+       __le16 log_type;
+       __le16 size;
+       __le32 timestamp;
+       __le32 type_specific_data;
+       u8 payload[0];
+} __packed;
+
 enum ath10k_hw_rate_ofdm {
        ATH10K_HW_RATE_OFDM_48M = 0,
        ATH10K_HW_RATE_OFDM_24M,
@@ -294,6 +304,11 @@ enum ath10k_hw_rate_cck {
        ATH10K_HW_RATE_CCK_SP_2M,
 };
 
+enum ath10k_hw_4addr_pad {
+       ATH10K_HW_4ADDR_PAD_AFTER,
+       ATH10K_HW_4ADDR_PAD_BEFORE,
+};
+
 /* Target specific defines for MAIN firmware */
 #define TARGET_NUM_VDEVS                       8
 #define TARGET_NUM_PEER_AST                    2
index a7411fe..8ae5216 100644 (file)
@@ -90,7 +90,7 @@ static u8 ath10k_mac_bitrate_to_rate(int bitrate)
 }
 
 u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
-                            u8 hw_rate)
+                            u8 hw_rate, bool cck)
 {
        const struct ieee80211_rate *rate;
        int i;
@@ -98,6 +98,9 @@ u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
        for (i = 0; i < sband->n_bitrates; i++) {
                rate = &sband->bitrates[i];
 
+               if (ath10k_mac_bitrate_is_cck(rate->bitrate) != cck)
+                       continue;
+
                if (rate->hw_value == hw_rate)
                        return i;
                else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
@@ -1960,7 +1963,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
        ether_addr_copy(arg->addr, sta->addr);
        arg->vdev_id = arvif->vdev_id;
        arg->peer_aid = aid;
-       arg->peer_flags |= WMI_PEER_AUTH;
+       arg->peer_flags |= arvif->ar->wmi.peer_flags->auth;
        arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
        arg->peer_num_spatial_streams = 1;
        arg->peer_caps = vif->bss_conf.assoc_capability;
@@ -1968,6 +1971,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
 
 static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
                                       struct ieee80211_vif *vif,
+                                      struct ieee80211_sta *sta,
                                       struct wmi_peer_assoc_complete_arg *arg)
 {
        struct ieee80211_bss_conf *info = &vif->bss_conf;
@@ -2002,12 +2006,17 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
        /* FIXME: base on RSN IE/WPA IE is a correct idea? */
        if (rsnie || wpaie) {
                ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__);
-               arg->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
+               arg->peer_flags |= ar->wmi.peer_flags->need_ptk_4_way;
        }
 
        if (wpaie) {
                ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__);
-               arg->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
+               arg->peer_flags |= ar->wmi.peer_flags->need_gtk_2_way;
+       }
+
+       if (sta->mfp &&
+           test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, ar->fw_features)) {
+               arg->peer_flags |= ar->wmi.peer_flags->pmf;
        }
 }
 
@@ -2104,7 +2113,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
            ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
                return;
 
-       arg->peer_flags |= WMI_PEER_HT;
+       arg->peer_flags |= ar->wmi.peer_flags->ht;
        arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
                                    ht_cap->ampdu_factor)) - 1;
 
@@ -2115,10 +2124,10 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
        arg->peer_rate_caps |= WMI_RC_HT_FLAG;
 
        if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
-               arg->peer_flags |= WMI_PEER_LDPC;
+               arg->peer_flags |= ar->wmi.peer_flags->ldbc;
 
        if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
-               arg->peer_flags |= WMI_PEER_40MHZ;
+               arg->peer_flags |= ar->wmi.peer_flags->bw40;
                arg->peer_rate_caps |= WMI_RC_CW40_FLAG;
        }
 
@@ -2132,7 +2141,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
 
        if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
                arg->peer_rate_caps |= WMI_RC_TX_STBC_FLAG;
-               arg->peer_flags |= WMI_PEER_STBC;
+               arg->peer_flags |= ar->wmi.peer_flags->stbc;
        }
 
        if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
@@ -2140,7 +2149,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
                stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
                stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
                arg->peer_rate_caps |= stbc;
-               arg->peer_flags |= WMI_PEER_STBC;
+               arg->peer_flags |= ar->wmi.peer_flags->stbc;
        }
 
        if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
@@ -2321,10 +2330,10 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
        if (ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
                return;
 
-       arg->peer_flags |= WMI_PEER_VHT;
+       arg->peer_flags |= ar->wmi.peer_flags->vht;
 
        if (def.chan->band == IEEE80211_BAND_2GHZ)
-               arg->peer_flags |= WMI_PEER_VHT_2G;
+               arg->peer_flags |= ar->wmi.peer_flags->vht_2g;
 
        arg->peer_vht_caps = vht_cap->cap;
 
@@ -2341,7 +2350,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
                                        ampdu_factor)) - 1);
 
        if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
-               arg->peer_flags |= WMI_PEER_80MHZ;
+               arg->peer_flags |= ar->wmi.peer_flags->bw80;
 
        arg->peer_vht_rates.rx_max_rate =
                __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
@@ -2366,27 +2375,28 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
        switch (arvif->vdev_type) {
        case WMI_VDEV_TYPE_AP:
                if (sta->wme)
-                       arg->peer_flags |= WMI_PEER_QOS;
+                       arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
 
                if (sta->wme && sta->uapsd_queues) {
-                       arg->peer_flags |= WMI_PEER_APSD;
+                       arg->peer_flags |= arvif->ar->wmi.peer_flags->apsd;
                        arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
                }
                break;
        case WMI_VDEV_TYPE_STA:
                if (vif->bss_conf.qos)
-                       arg->peer_flags |= WMI_PEER_QOS;
+                       arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
                break;
        case WMI_VDEV_TYPE_IBSS:
                if (sta->wme)
-                       arg->peer_flags |= WMI_PEER_QOS;
+                       arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
                break;
        default:
                break;
        }
 
        ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
-                  sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
+                  sta->addr, !!(arg->peer_flags &
+                  arvif->ar->wmi.peer_flags->qos));
 }
 
 static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
@@ -2479,7 +2489,7 @@ static int ath10k_peer_assoc_prepare(struct ath10k *ar,
        memset(arg, 0, sizeof(*arg));
 
        ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
-       ath10k_peer_assoc_h_crypto(ar, vif, arg);
+       ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
        ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
        ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
        ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
@@ -3112,35 +3122,11 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
        spin_unlock_bh(&ar->htt.tx_lock);
 }
 
-static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr)
-{
-       if (ieee80211_is_mgmt(hdr->frame_control))
-               return HTT_DATA_TX_EXT_TID_MGMT;
-
-       if (!ieee80211_is_data_qos(hdr->frame_control))
-               return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
-
-       if (!is_unicast_ether_addr(ieee80211_get_DA(hdr)))
-               return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
-
-       return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
-}
-
-static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, struct ieee80211_vif *vif)
-{
-       if (vif)
-               return ath10k_vif_to_arvif(vif)->vdev_id;
-
-       if (ar->monitor_started)
-               return ar->monitor_vdev_id;
-
-       ath10k_warn(ar, "failed to resolve vdev id\n");
-       return 0;
-}
-
 static enum ath10k_hw_txrx_mode
-ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
-                      struct ieee80211_sta *sta, struct sk_buff *skb)
+ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
+                          struct ieee80211_vif *vif,
+                          struct ieee80211_sta *sta,
+                          struct sk_buff *skb)
 {
        const struct ieee80211_hdr *hdr = (void *)skb->data;
        __le16 fc = hdr->frame_control;
@@ -3190,14 +3176,22 @@ ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
 }
 
 static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
-                                    struct sk_buff *skb) {
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+                                    struct sk_buff *skb)
+{
+       const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       const struct ieee80211_hdr *hdr = (void *)skb->data;
        const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT |
                         IEEE80211_TX_CTL_INJECTED;
+
+       if (!ieee80211_has_protected(hdr->frame_control))
+               return false;
+
        if ((info->flags & mask) == mask)
                return false;
+
        if (vif)
                return !ath10k_vif_to_arvif(vif)->nohwcrypt;
+
        return true;
 }
 
@@ -3224,7 +3218,7 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
         */
        hdr = (void *)skb->data;
        if (ieee80211_is_qos_nullfunc(hdr->frame_control))
-               cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
+               cb->flags &= ~ATH10K_SKB_F_QOS;
 
        hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
 }
@@ -3280,7 +3274,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
        }
 }
 
-static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
+bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
 {
        /* FIXME: Not really sure since when the behaviour changed. At some
         * point new firmware stopped requiring creation of peer entries for
@@ -3288,8 +3282,9 @@ static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
         * tx credit replenishment and reliability). Assuming it's at least 3.4
         * because that's when the `freq` was introduced to TX_FRM HTT command.
         */
-       return !(ar->htt.target_version_major >= 3 &&
-                ar->htt.target_version_minor >= 4);
+       return (ar->htt.target_version_major >= 3 &&
+               ar->htt.target_version_minor >= 4 &&
+               ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV);
 }
 
 static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
@@ -3314,24 +3309,24 @@ unlock:
        return ret;
 }
 
-static void ath10k_mac_tx(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode,
+                         struct sk_buff *skb)
 {
-       struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
        struct ath10k_htt *htt = &ar->htt;
        int ret = 0;
 
-       switch (cb->txmode) {
+       switch (txmode) {
        case ATH10K_HW_TXRX_RAW:
        case ATH10K_HW_TXRX_NATIVE_WIFI:
        case ATH10K_HW_TXRX_ETHERNET:
-               ret = ath10k_htt_tx(htt, skb);
+               ret = ath10k_htt_tx(htt, txmode, skb);
                break;
        case ATH10K_HW_TXRX_MGMT:
                if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
                             ar->fw_features))
                        ret = ath10k_mac_tx_wmi_mgmt(ar, skb);
                else if (ar->htt.target_version_major >= 3)
-                       ret = ath10k_htt_tx(htt, skb);
+                       ret = ath10k_htt_tx(htt, txmode, skb);
                else
                        ret = ath10k_htt_mgmt_tx(htt, skb);
                break;
@@ -3361,9 +3356,13 @@ void ath10k_offchan_tx_work(struct work_struct *work)
 {
        struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work);
        struct ath10k_peer *peer;
+       struct ath10k_vif *arvif;
        struct ieee80211_hdr *hdr;
+       struct ieee80211_vif *vif;
+       struct ieee80211_sta *sta;
        struct sk_buff *skb;
        const u8 *peer_addr;
+       enum ath10k_hw_txrx_mode txmode;
        int vdev_id;
        int ret;
        unsigned long time_left;
@@ -3388,9 +3387,9 @@ void ath10k_offchan_tx_work(struct work_struct *work)
 
                hdr = (struct ieee80211_hdr *)skb->data;
                peer_addr = ieee80211_get_DA(hdr);
-               vdev_id = ATH10K_SKB_CB(skb)->vdev_id;
 
                spin_lock_bh(&ar->data_lock);
+               vdev_id = ar->scan.vdev_id;
                peer = ath10k_peer_find(ar, vdev_id, peer_addr);
                spin_unlock_bh(&ar->data_lock);
 
@@ -3413,7 +3412,22 @@ void ath10k_offchan_tx_work(struct work_struct *work)
                ar->offchan_tx_skb = skb;
                spin_unlock_bh(&ar->data_lock);
 
-               ath10k_mac_tx(ar, skb);
+               /* It's safe to access vif and sta - conf_mutex guarantees that
+                * sta_state() and remove_interface() are locked exclusively
+                * out wrt to this offchannel worker.
+                */
+               arvif = ath10k_get_arvif(ar, vdev_id);
+               if (arvif) {
+                       vif = arvif->vif;
+                       sta = ieee80211_find_sta(vif, peer_addr);
+               } else {
+                       vif = NULL;
+                       sta = NULL;
+               }
+
+               txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
+
+               ath10k_mac_tx(ar, txmode, skb);
 
                time_left =
                wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
@@ -3488,6 +3502,7 @@ void __ath10k_scan_finish(struct ath10k *ar)
        case ATH10K_SCAN_STARTING:
                ar->scan.state = ATH10K_SCAN_IDLE;
                ar->scan_channel = NULL;
+               ar->scan.roc_freq = 0;
                ath10k_offchan_tx_purge(ar);
                cancel_delayed_work(&ar->scan.timeout);
                complete_all(&ar->scan.completed);
@@ -3631,25 +3646,32 @@ static void ath10k_tx(struct ieee80211_hw *hw,
                      struct sk_buff *skb)
 {
        struct ath10k *ar = hw->priv;
+       struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_vif *vif = info->control.vif;
        struct ieee80211_sta *sta = control->sta;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       __le16 fc = hdr->frame_control;
+       enum ath10k_hw_txrx_mode txmode;
 
        /* We should disable CCK RATE due to P2P */
        if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
                ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
 
-       ATH10K_SKB_CB(skb)->htt.is_offchan = false;
-       ATH10K_SKB_CB(skb)->htt.freq = 0;
-       ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
-       ATH10K_SKB_CB(skb)->htt.nohwcrypt = !ath10k_tx_h_use_hwcrypto(vif, skb);
-       ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
-       ATH10K_SKB_CB(skb)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb);
-       ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
+       txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
+
+       skb_cb->flags = 0;
+       if (!ath10k_tx_h_use_hwcrypto(vif, skb))
+               skb_cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
+
+       if (ieee80211_is_mgmt(hdr->frame_control))
+               skb_cb->flags |= ATH10K_SKB_F_MGMT;
 
-       switch (ATH10K_SKB_CB(skb)->txmode) {
+       if (ieee80211_is_data_qos(hdr->frame_control))
+               skb_cb->flags |= ATH10K_SKB_F_QOS;
+
+       skb_cb->vif = vif;
+
+       switch (txmode) {
        case ATH10K_HW_TXRX_MGMT:
        case ATH10K_HW_TXRX_NATIVE_WIFI:
                ath10k_tx_h_nwifi(hw, skb);
@@ -3668,15 +3690,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
        }
 
        if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
-               spin_lock_bh(&ar->data_lock);
-               ATH10K_SKB_CB(skb)->htt.freq = ar->scan.roc_freq;
-               ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id;
-               spin_unlock_bh(&ar->data_lock);
-
-               if (ath10k_mac_need_offchan_tx_work(ar)) {
-                       ATH10K_SKB_CB(skb)->htt.freq = 0;
-                       ATH10K_SKB_CB(skb)->htt.is_offchan = true;
-
+               if (!ath10k_mac_tx_frm_has_freq(ar)) {
                        ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
                                   skb);
 
@@ -3686,7 +3700,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
                }
        }
 
-       ath10k_mac_tx(ar, skb);
+       ath10k_mac_tx(ar, txmode, skb);
 }
 
 /* Must not be called with conf_mutex held as workers can use that also. */
@@ -4350,7 +4364,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
                arvif->vdev_type = WMI_VDEV_TYPE_IBSS;
                break;
        case NL80211_IFTYPE_MESH_POINT:
-               if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+               if (test_bit(WMI_SERVICE_MESH, ar->wmi.svc_map)) {
+                       arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH;
+               } else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
                        ret = -EINVAL;
                        ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n");
                        goto err;
@@ -6907,35 +6923,39 @@ void ath10k_mac_destroy(struct ath10k *ar)
 
 static const struct ieee80211_iface_limit ath10k_if_limits[] = {
        {
-       .max    = 8,
-       .types  = BIT(NL80211_IFTYPE_STATION)
-               | BIT(NL80211_IFTYPE_P2P_CLIENT)
+               .max    = 8,
+               .types  = BIT(NL80211_IFTYPE_STATION)
+                       | BIT(NL80211_IFTYPE_P2P_CLIENT)
        },
        {
-       .max    = 3,
-       .types  = BIT(NL80211_IFTYPE_P2P_GO)
+               .max    = 3,
+               .types  = BIT(NL80211_IFTYPE_P2P_GO)
        },
        {
-       .max    = 1,
-       .types  = BIT(NL80211_IFTYPE_P2P_DEVICE)
+               .max    = 1,
+               .types  = BIT(NL80211_IFTYPE_P2P_DEVICE)
        },
        {
-       .max    = 7,
-       .types  = BIT(NL80211_IFTYPE_AP)
+               .max    = 7,
+               .types  = BIT(NL80211_IFTYPE_AP)
 #ifdef CONFIG_MAC80211_MESH
-               | BIT(NL80211_IFTYPE_MESH_POINT)
+                       | BIT(NL80211_IFTYPE_MESH_POINT)
 #endif
        },
 };
 
 static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
        {
-       .max    = 8,
-       .types  = BIT(NL80211_IFTYPE_AP)
+               .max    = 8,
+               .types  = BIT(NL80211_IFTYPE_AP)
 #ifdef CONFIG_MAC80211_MESH
-               | BIT(NL80211_IFTYPE_MESH_POINT)
+                       | BIT(NL80211_IFTYPE_MESH_POINT)
 #endif
        },
+       {
+               .max    = 1,
+               .types  = BIT(NL80211_IFTYPE_STATION)
+       },
 };
 
 static const struct ieee80211_iface_combination ath10k_if_comb[] = {
index e3cefe4..5309158 100644 (file)
@@ -66,7 +66,7 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
                                     enum wmi_tlv_tx_pause_action action);
 
 u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
-                            u8 hw_rate);
+                            u8 hw_rate, bool cck);
 u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
                             u32 bitrate);
 
@@ -74,6 +74,7 @@ void ath10k_mac_tx_lock(struct ath10k *ar, int reason);
 void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
 void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason);
 void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason);
+bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar);
 
 static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 {
index 3fca200..5c91a67 100644 (file)
@@ -111,6 +111,7 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
 static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
 static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
 static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
 
 static const struct ce_attr host_ce_config_wlan[] = {
        /* CE0: host->target HTC control and raw streams */
@@ -189,6 +190,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
                .src_nentries = 0,
                .src_sz_max = 2048,
                .dest_nentries = 128,
+               .recv_cb = ath10k_pci_pktlog_rx_cb,
        },
 
        /* CE9 target autonomous qcache memcpy */
@@ -1208,6 +1210,15 @@ static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
        ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
 }
 
+/* Called by lower (CE) layer when data is received from the Target.
+ * Only 10.4 firmware uses separate CE to transfer pktlog data.
+ */
+static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+       ath10k_pci_process_rx_cb(ce_state,
+                                ath10k_htt_rx_pktlog_completion_handler);
+}
+
 /* Called by lower (CE) layer when a send to HTT Target completes. */
 static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
 {
index 60fe562..444b52c 100644 (file)
@@ -187,7 +187,7 @@ int ath10k_thermal_register(struct ath10k *ar)
        /* Do not register hwmon device when temperature reading is not
         * supported by firmware
         */
-       if (ar->wmi.op_version != ATH10K_FW_WMI_OP_VERSION_10_2_4)
+       if (!(ar->wmi.ops->gen_pdev_get_temperature))
                return 0;
 
        /* Avoid linking error on devm_hwmon_device_register_with_groups, I
index 6d1105a..fbfb608 100644 (file)
 
 static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
 {
-       if (!ATH10K_SKB_CB(skb)->htt.is_offchan)
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+       if (likely(!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)))
+               return;
+
+       if (ath10k_mac_tx_frm_has_freq(ar))
                return;
 
        /* If the original wait_for_completion() timed out before
@@ -52,8 +57,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
        struct ieee80211_tx_info *info;
        struct ath10k_skb_cb *skb_cb;
        struct sk_buff *msdu;
-       struct ieee80211_hdr *hdr;
-       __le16 fc;
        bool limit_mgmt_desc = false;
 
        ath10k_dbg(ar, ATH10K_DBG_HTT,
@@ -76,10 +79,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
                return;
        }
 
-       hdr = (struct ieee80211_hdr *)msdu->data;
-       fc = hdr->frame_control;
+       skb_cb = ATH10K_SKB_CB(msdu);
 
-       if (unlikely(ieee80211_is_mgmt(fc)) &&
+       if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) &&
            ar->hw_params.max_probe_resp_desc_thres)
                limit_mgmt_desc = true;
 
@@ -89,7 +91,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
                wake_up(&htt->empty_tx_wq);
        spin_unlock_bh(&htt->tx_lock);
 
-       skb_cb = ATH10K_SKB_CB(msdu);
        dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
 
        ath10k_report_offchan_tx(htt->ar, msdu);
index 6fbd17b..3b3a27b 100644 (file)
@@ -3485,6 +3485,24 @@ static const struct wmi_ops wmi_tlv_ops = {
        .fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
 };
 
+static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
+       .auth = WMI_TLV_PEER_AUTH,
+       .qos = WMI_TLV_PEER_QOS,
+       .need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_TLV_PEER_APSD,
+       .ht = WMI_TLV_PEER_HT,
+       .bw40 = WMI_TLV_PEER_40MHZ,
+       .stbc = WMI_TLV_PEER_STBC,
+       .ldbc = WMI_TLV_PEER_LDPC,
+       .dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
+       .vht = WMI_TLV_PEER_VHT,
+       .bw80 = WMI_TLV_PEER_80MHZ,
+       .pmf = WMI_TLV_PEER_PMF,
+};
+
 /************/
 /* TLV init */
 /************/
@@ -3495,4 +3513,5 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
        ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
        ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
        ar->wmi.ops = &wmi_tlv_ops;
+       ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
 }
index ad655c4..dd67859 100644 (file)
@@ -527,6 +527,24 @@ enum wmi_tlv_vdev_param {
        WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
 };
 
+enum wmi_tlv_peer_flags {
+       WMI_TLV_PEER_AUTH = 0x00000001,
+       WMI_TLV_PEER_QOS = 0x00000002,
+       WMI_TLV_PEER_NEED_PTK_4_WAY = 0x00000004,
+       WMI_TLV_PEER_NEED_GTK_2_WAY = 0x00000010,
+       WMI_TLV_PEER_APSD = 0x00000800,
+       WMI_TLV_PEER_HT = 0x00001000,
+       WMI_TLV_PEER_40MHZ = 0x00002000,
+       WMI_TLV_PEER_STBC = 0x00008000,
+       WMI_TLV_PEER_LDPC = 0x00010000,
+       WMI_TLV_PEER_DYN_MIMOPS = 0x00020000,
+       WMI_TLV_PEER_STATIC_MIMOPS = 0x00040000,
+       WMI_TLV_PEER_SPATIAL_MUX = 0x00200000,
+       WMI_TLV_PEER_VHT = 0x02000000,
+       WMI_TLV_PEER_80MHZ = 0x04000000,
+       WMI_TLV_PEER_PMF = 0x08000000,
+};
+
 enum wmi_tlv_tag {
        WMI_TLV_TAG_LAST_RESERVED = 15,
 
index 7569db0..2a44d63 100644 (file)
@@ -1546,6 +1546,61 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
        .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
 };
 
+static const struct wmi_peer_flags_map wmi_peer_flags_map = {
+       .auth = WMI_PEER_AUTH,
+       .qos = WMI_PEER_QOS,
+       .need_ptk_4_way = WMI_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_PEER_APSD,
+       .ht = WMI_PEER_HT,
+       .bw40 = WMI_PEER_40MHZ,
+       .stbc = WMI_PEER_STBC,
+       .ldbc = WMI_PEER_LDPC,
+       .dyn_mimops = WMI_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_PEER_SPATIAL_MUX,
+       .vht = WMI_PEER_VHT,
+       .bw80 = WMI_PEER_80MHZ,
+       .vht_2g = WMI_PEER_VHT_2G,
+       .pmf = WMI_PEER_PMF,
+};
+
+static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
+       .auth = WMI_10X_PEER_AUTH,
+       .qos = WMI_10X_PEER_QOS,
+       .need_ptk_4_way = WMI_10X_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_10X_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_10X_PEER_APSD,
+       .ht = WMI_10X_PEER_HT,
+       .bw40 = WMI_10X_PEER_40MHZ,
+       .stbc = WMI_10X_PEER_STBC,
+       .ldbc = WMI_10X_PEER_LDPC,
+       .dyn_mimops = WMI_10X_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_10X_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
+       .vht = WMI_10X_PEER_VHT,
+       .bw80 = WMI_10X_PEER_80MHZ,
+};
+
+static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
+       .auth = WMI_10_2_PEER_AUTH,
+       .qos = WMI_10_2_PEER_QOS,
+       .need_ptk_4_way = WMI_10_2_PEER_NEED_PTK_4_WAY,
+       .need_gtk_2_way = WMI_10_2_PEER_NEED_GTK_2_WAY,
+       .apsd = WMI_10_2_PEER_APSD,
+       .ht = WMI_10_2_PEER_HT,
+       .bw40 = WMI_10_2_PEER_40MHZ,
+       .stbc = WMI_10_2_PEER_STBC,
+       .ldbc = WMI_10_2_PEER_LDPC,
+       .dyn_mimops = WMI_10_2_PEER_DYN_MIMOPS,
+       .static_mimops = WMI_10_2_PEER_STATIC_MIMOPS,
+       .spatial_mux = WMI_10_2_PEER_SPATIAL_MUX,
+       .vht = WMI_10_2_PEER_VHT,
+       .bw80 = WMI_10_2_PEER_80MHZ,
+       .vht_2g = WMI_10_2_PEER_VHT_2G,
+       .pmf = WMI_10_2_PEER_PMF,
+};
+
 void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
                                const struct wmi_channel_arg *arg)
 {
@@ -1660,6 +1715,8 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
        struct ath10k *ar = arvif->ar;
        struct ath10k_skb_cb *cb;
        struct sk_buff *bcn;
+       bool dtim_zero;
+       bool deliver_cab;
        int ret;
 
        spin_lock_bh(&ar->data_lock);
@@ -1679,12 +1736,14 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
                arvif->beacon_state = ATH10K_BEACON_SENDING;
                spin_unlock_bh(&ar->data_lock);
 
+               dtim_zero = !!(cb->flags & ATH10K_SKB_F_DTIM_ZERO);
+               deliver_cab = !!(cb->flags & ATH10K_SKB_F_DELIVER_CAB);
                ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar,
                                                        arvif->vdev_id,
                                                        bcn->data, bcn->len,
                                                        cb->paddr,
-                                                       cb->bcn.dtim_zero,
-                                                       cb->bcn.deliver_cab);
+                                                       dtim_zero,
+                                                       deliver_cab);
 
                spin_lock_bh(&ar->data_lock);
 
@@ -1755,16 +1814,24 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
 static struct sk_buff *
 ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
 {
+       struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
+       struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
        struct wmi_mgmt_tx_cmd *cmd;
        struct ieee80211_hdr *hdr;
        struct sk_buff *skb;
        int len;
+       u32 vdev_id;
        u32 buf_len = msdu->len;
        u16 fc;
 
        hdr = (struct ieee80211_hdr *)msdu->data;
        fc = le16_to_cpu(hdr->frame_control);
 
+       if (cb->vif)
+               vdev_id = arvif->vdev_id;
+       else
+               vdev_id = 0;
+
        if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
                return ERR_PTR(-EINVAL);
 
@@ -1786,7 +1853,7 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
 
        cmd = (struct wmi_mgmt_tx_cmd *)skb->data;
 
-       cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(msdu)->vdev_id);
+       cmd->hdr.vdev_id = __cpu_to_le32(vdev_id);
        cmd->hdr.tx_rate = 0;
        cmd->hdr.tx_power = 0;
        cmd->hdr.buf_len = __cpu_to_le32(buf_len);
@@ -2204,22 +2271,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        ath10k_dbg(ar, ATH10K_DBG_MGMT,
                   "event mgmt rx status %08x\n", rx_status);
 
-       if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) {
-               dev_kfree_skb(skb);
-               return 0;
-       }
-
-       if (rx_status & WMI_RX_STATUS_ERR_CRC) {
+       if ((test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) ||
+           (rx_status & (WMI_RX_STATUS_ERR_DECRYPT |
+           WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) {
                dev_kfree_skb(skb);
                return 0;
        }
@@ -3115,10 +3169,10 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
        memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
 
        if (tim->dtim_count == 0) {
-               ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
+               ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DTIM_ZERO;
 
                if (__le32_to_cpu(tim_info->tim_mcast) == 1)
-                       ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
+                       ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DELIVER_CAB;
        }
 
        ath10k_dbg(ar, ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
@@ -5061,6 +5115,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_10_4_UPDATE_STATS_EVENTID:
                ath10k_wmi_event_update_stats(ar, skb);
                break;
+       case WMI_10_4_PDEV_TEMPERATURE_EVENTID:
+               ath10k_wmi_event_temperature(ar, skb);
+               break;
        default:
                ath10k_warn(ar, "Unknown eventid: %d\n", id);
                break;
@@ -5431,8 +5488,11 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
        cmd = (struct wmi_init_cmd_10_2 *)buf->data;
 
        features = WMI_10_2_RX_BATCH_MODE;
-       if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
+
+       if (test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) &&
+           test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
                features |= WMI_10_2_COEX_GPIO;
+
        cmd->resource_config.feature_mask = __cpu_to_le32(features);
 
        memcpy(&cmd->resource_config.common, &config, sizeof(config));
@@ -6328,6 +6388,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
        cmd->info0 = __cpu_to_le32(info0);
 }
 
+static void
+ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
+                               const struct wmi_peer_assoc_complete_arg *arg)
+{
+       struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
+
+       ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
+       cmd->peer_bw_rxnss_override = 0;
+}
+
 static int
 ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg)
 {
@@ -6416,6 +6486,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
        return skb;
 }
 
+static struct sk_buff *
+ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar,
+                                 const struct wmi_peer_assoc_complete_arg *arg)
+{
+       size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd);
+       struct sk_buff *skb;
+       int ret;
+
+       ret = ath10k_wmi_peer_assoc_check_arg(arg);
+       if (ret)
+               return ERR_PTR(ret);
+
+       skb = ath10k_wmi_alloc_skb(ar, len);
+       if (!skb)
+               return ERR_PTR(-ENOMEM);
+
+       ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg);
+
+       ath10k_dbg(ar, ATH10K_DBG_WMI,
+                  "wmi peer assoc vdev %d addr %pM (%s)\n",
+                  arg->vdev_id, arg->addr,
+                  arg->peer_reassoc ? "reassociate" : "new");
+       return skb;
+}
+
 static struct sk_buff *
 ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
 {
@@ -7536,6 +7631,7 @@ static const struct wmi_ops wmi_10_4_ops = {
        .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_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc,
        .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,
@@ -7555,8 +7651,8 @@ static const struct wmi_ops wmi_10_4_ops = {
        .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
 
        /* shared with 10.2 */
-       .gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
        .gen_request_stats = ath10k_wmi_op_gen_request_stats,
+       .gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
 };
 
 int ath10k_wmi_attach(struct ath10k *ar)
@@ -7567,30 +7663,35 @@ int ath10k_wmi_attach(struct ath10k *ar)
                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;
+               ar->wmi.peer_flags = &wmi_10_2_peer_flags_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;
                ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_2:
                ar->wmi.cmd = &wmi_10_2_cmd_map;
                ar->wmi.ops = &wmi_10_2_ops;
                ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_10_1:
                ar->wmi.cmd = &wmi_10x_cmd_map;
                ar->wmi.ops = &wmi_10_1_ops;
                ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_MAIN:
                ar->wmi.cmd = &wmi_cmd_map;
                ar->wmi.ops = &wmi_ops;
                ar->wmi.vdev_param = &wmi_vdev_param_map;
                ar->wmi.pdev_param = &wmi_pdev_param_map;
+               ar->wmi.peer_flags = &wmi_peer_flags_map;
                break;
        case ATH10K_FW_WMI_OP_VERSION_TLV:
                ath10k_wmi_tlv_attach(ar);
index 72a4ef7..d85ad78 100644 (file)
@@ -175,6 +175,8 @@ enum wmi_service {
        WMI_SERVICE_AUX_SPECTRAL_INTF,
        WMI_SERVICE_AUX_CHAN_LOAD_INTF,
        WMI_SERVICE_BSS_CHANNEL_INFO_64,
+       WMI_SERVICE_EXT_RES_CFG_SUPPORT,
+       WMI_SERVICE_MESH,
 
        /* keep last */
        WMI_SERVICE_MAX,
@@ -206,6 +208,11 @@ enum wmi_10x_service {
        WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
        WMI_10X_SERVICE_ATF,
        WMI_10X_SERVICE_COEX_GPIO,
+       WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
+       WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
+       WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
+       WMI_10X_SERVICE_MESH,
+       WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
 };
 
 enum wmi_main_service {
@@ -286,6 +293,8 @@ enum wmi_10_4_service {
        WMI_10_4_SERVICE_AUX_SPECTRAL_INTF,
        WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
        WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
+       WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
+       WMI_10_4_SERVICE_MESH,
 };
 
 static inline char *wmi_service_name(int service_id)
@@ -375,6 +384,8 @@ static inline char *wmi_service_name(int service_id)
        SVCSTR(WMI_SERVICE_AUX_SPECTRAL_INTF);
        SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF);
        SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64);
+       SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT);
+       SVCSTR(WMI_SERVICE_MESH);
        default:
                return NULL;
        }
@@ -442,6 +453,16 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
               WMI_SERVICE_ATF, len);
        SVCMAP(WMI_10X_SERVICE_COEX_GPIO,
               WMI_SERVICE_COEX_GPIO, len);
+       SVCMAP(WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
+              WMI_SERVICE_AUX_SPECTRAL_INTF, len);
+       SVCMAP(WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
+              WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
+       SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
+              WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
+       SVCMAP(WMI_10X_SERVICE_MESH,
+              WMI_SERVICE_MESH, len);
+       SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
+              WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
 }
 
 static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
@@ -600,6 +621,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
               WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
        SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
               WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
+       SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
+              WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
+       SVCMAP(WMI_10_4_SERVICE_MESH,
+              WMI_SERVICE_MESH, len);
 }
 
 #undef SVCMAP
@@ -1576,6 +1601,9 @@ enum wmi_10_4_cmd_id {
        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_EXT_RESOURCE_CFG_CMDID,
+       WMI_10_4_VDEV_SET_IE_CMDID,
+       WMI_10_4_SET_LTEU_CONFIG_CMDID,
        WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
 };
 
@@ -1638,6 +1666,7 @@ enum wmi_10_4_event_id {
        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_MU_REPORT_EVENTID,
        WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
 };
 
@@ -3650,6 +3679,12 @@ enum wmi_10_4_pdev_param {
        WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
        WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
        WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+       WMI_10_4_PDEV_PARAM_TXPOWER_DECR_DB,
+       WMI_10_4_PDEV_PARAM_RX_BATCHMODE,
+       WMI_10_4_PDEV_PARAM_PACKET_AGGR_DELAY,
+       WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCH,
+       WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCALING_FACTOR,
+       WMI_10_4_PDEV_PARAM_CUST_TXPOWER_SCALE,
 };
 
 struct wmi_pdev_set_param_cmd {
@@ -4239,6 +4274,8 @@ enum wmi_vdev_subtype {
        WMI_VDEV_SUBTYPE_P2P_DEVICE = 1,
        WMI_VDEV_SUBTYPE_P2P_CLIENT = 2,
        WMI_VDEV_SUBTYPE_P2P_GO     = 3,
+       WMI_VDEV_SUBTYPE_PROXY_STA      = 4,
+       WMI_VDEV_SUBTYPE_MESH           = 5,
 };
 
 /* values for vdev_subtype */
@@ -5641,21 +5678,79 @@ struct wmi_peer_set_q_empty_callback_cmd {
        __le32 callback_enable;
 } __packed;
 
-#define WMI_PEER_AUTH           0x00000001
-#define WMI_PEER_QOS            0x00000002
-#define WMI_PEER_NEED_PTK_4_WAY 0x00000004
-#define WMI_PEER_NEED_GTK_2_WAY 0x00000010
-#define WMI_PEER_APSD           0x00000800
-#define WMI_PEER_HT             0x00001000
-#define WMI_PEER_40MHZ          0x00002000
-#define WMI_PEER_STBC           0x00008000
-#define WMI_PEER_LDPC           0x00010000
-#define WMI_PEER_DYN_MIMOPS     0x00020000
-#define WMI_PEER_STATIC_MIMOPS  0x00040000
-#define WMI_PEER_SPATIAL_MUX    0x00200000
-#define WMI_PEER_VHT            0x02000000
-#define WMI_PEER_80MHZ          0x04000000
-#define WMI_PEER_VHT_2G         0x08000000
+struct wmi_peer_flags_map {
+       u32 auth;
+       u32 qos;
+       u32 need_ptk_4_way;
+       u32 need_gtk_2_way;
+       u32 apsd;
+       u32 ht;
+       u32 bw40;
+       u32 stbc;
+       u32 ldbc;
+       u32 dyn_mimops;
+       u32 static_mimops;
+       u32 spatial_mux;
+       u32 vht;
+       u32 bw80;
+       u32 vht_2g;
+       u32 pmf;
+};
+
+enum wmi_peer_flags {
+       WMI_PEER_AUTH = 0x00000001,
+       WMI_PEER_QOS = 0x00000002,
+       WMI_PEER_NEED_PTK_4_WAY = 0x00000004,
+       WMI_PEER_NEED_GTK_2_WAY = 0x00000010,
+       WMI_PEER_APSD = 0x00000800,
+       WMI_PEER_HT = 0x00001000,
+       WMI_PEER_40MHZ = 0x00002000,
+       WMI_PEER_STBC = 0x00008000,
+       WMI_PEER_LDPC = 0x00010000,
+       WMI_PEER_DYN_MIMOPS = 0x00020000,
+       WMI_PEER_STATIC_MIMOPS = 0x00040000,
+       WMI_PEER_SPATIAL_MUX = 0x00200000,
+       WMI_PEER_VHT = 0x02000000,
+       WMI_PEER_80MHZ = 0x04000000,
+       WMI_PEER_VHT_2G = 0x08000000,
+       WMI_PEER_PMF = 0x10000000,
+};
+
+enum wmi_10x_peer_flags {
+       WMI_10X_PEER_AUTH = 0x00000001,
+       WMI_10X_PEER_QOS = 0x00000002,
+       WMI_10X_PEER_NEED_PTK_4_WAY = 0x00000004,
+       WMI_10X_PEER_NEED_GTK_2_WAY = 0x00000010,
+       WMI_10X_PEER_APSD = 0x00000800,
+       WMI_10X_PEER_HT = 0x00001000,
+       WMI_10X_PEER_40MHZ = 0x00002000,
+       WMI_10X_PEER_STBC = 0x00008000,
+       WMI_10X_PEER_LDPC = 0x00010000,
+       WMI_10X_PEER_DYN_MIMOPS = 0x00020000,
+       WMI_10X_PEER_STATIC_MIMOPS = 0x00040000,
+       WMI_10X_PEER_SPATIAL_MUX = 0x00200000,
+       WMI_10X_PEER_VHT = 0x02000000,
+       WMI_10X_PEER_80MHZ = 0x04000000,
+};
+
+enum wmi_10_2_peer_flags {
+       WMI_10_2_PEER_AUTH = 0x00000001,
+       WMI_10_2_PEER_QOS = 0x00000002,
+       WMI_10_2_PEER_NEED_PTK_4_WAY = 0x00000004,
+       WMI_10_2_PEER_NEED_GTK_2_WAY = 0x00000010,
+       WMI_10_2_PEER_APSD = 0x00000800,
+       WMI_10_2_PEER_HT = 0x00001000,
+       WMI_10_2_PEER_40MHZ = 0x00002000,
+       WMI_10_2_PEER_STBC = 0x00008000,
+       WMI_10_2_PEER_LDPC = 0x00010000,
+       WMI_10_2_PEER_DYN_MIMOPS = 0x00020000,
+       WMI_10_2_PEER_STATIC_MIMOPS = 0x00040000,
+       WMI_10_2_PEER_SPATIAL_MUX = 0x00200000,
+       WMI_10_2_PEER_VHT = 0x02000000,
+       WMI_10_2_PEER_80MHZ = 0x04000000,
+       WMI_10_2_PEER_VHT_2G = 0x08000000,
+       WMI_10_2_PEER_PMF = 0x10000000,
+};
 
 /*
  * Peer rate capabilities.
@@ -5721,6 +5816,11 @@ struct wmi_10_2_peer_assoc_complete_cmd {
        __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
 } __packed;
 
+struct wmi_10_4_peer_assoc_complete_cmd {
+       struct wmi_10_2_peer_assoc_complete_cmd cmd;
+       __le32 peer_bw_rxnss_override;
+} __packed;
+
 struct wmi_peer_assoc_complete_arg {
        u8 addr[ETH_ALEN];
        u32 vdev_id;
index bb69a59..48687f1 100644 (file)
@@ -401,20 +401,26 @@ void wil_bcast_fini(struct wil6210_priv *wil)
 
 static void wil_connect_worker(struct work_struct *work)
 {
-       int rc;
+       int rc, cid, ringid;
        struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
                                                connect_worker);
        struct net_device *ndev = wil_to_ndev(wil);
 
-       int cid = wil->pending_connect_cid;
-       int ringid = wil_find_free_vring(wil);
+       mutex_lock(&wil->mutex);
 
+       cid = wil->pending_connect_cid;
        if (cid < 0) {
                wil_err(wil, "No connection pending\n");
-               return;
+               goto out;
+       }
+       ringid = wil_find_free_vring(wil);
+       if (ringid < 0) {
+               wil_err(wil, "No free vring found\n");
+               goto out;
        }
 
-       wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
+       wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n",
+                   cid, ringid);
 
        rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
        wil->pending_connect_cid = -1;
@@ -424,6 +430,8 @@ static void wil_connect_worker(struct work_struct *work)
        } else {
                wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true);
        }
+out:
+       mutex_unlock(&wil->mutex);
 }
 
 int wil_priv_init(struct wil6210_priv *wil)
index 3bc9bc0..7887e6c 100644 (file)
@@ -160,6 +160,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
        struct device *dev = wil_to_dev(wil);
        size_t sz = vring->size * sizeof(vring->va[0]);
 
+       lockdep_assert_held(&wil->mutex);
        if (tx) {
                int vring_index = vring - wil->vring_tx;
 
@@ -749,6 +750,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
 
        wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
                     cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
+       lockdep_assert_held(&wil->mutex);
 
        if (vring->va) {
                wil_err(wil, "Tx ring [%d] already allocated\n", id);
@@ -821,6 +823,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
 
        wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
                     cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
+       lockdep_assert_held(&wil->mutex);
 
        if (vring->va) {
                wil_err(wil, "Tx ring [%d] already allocated\n", id);
@@ -872,7 +875,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
        struct vring *vring = &wil->vring_tx[id];
        struct vring_tx_data *txdata = &wil->vring_tx_data[id];
 
-       WARN_ON(!mutex_is_locked(&wil->mutex));
+       lockdep_assert_held(&wil->mutex);
 
        if (!vring->va)
                return;