Merge tag 'wireless-drivers-next-2021-10-29' of git://git.kernel.org/pub/scm/linux...
authorJakub Kicinski <kuba@kernel.org>
Fri, 29 Oct 2021 15:58:39 +0000 (08:58 -0700)
committerJakub Kicinski <kuba@kernel.org>
Fri, 29 Oct 2021 15:58:40 +0000 (08:58 -0700)
Kalle Valo says:

====================
wireless-drivers-next patches for v5.16

Fourth set of patches for v5.16. Mostly fixes this time, wcn36xx and
iwlwifi have some new features but nothing really out of ordinary.
We have one conflict with kspp tree.

Major changes:

ath11k
 * fix QCA6390 A-MSDU handling (CVE-2020-24588)

wcn36xx
 * enable hardware scan offload for 5Ghz band
 * add missing 5GHz channels 136 and 144

iwlwifi
 * support a new ACPI table revision
 * improvements in the device selection code
 * new hardware support
 * support for WiFi 6E enablement via BIOS
 * support firmware API version 67
 * support for 160MHz in ranging measurements

====================

Link: https://lore.kernel.org/r/20211029134707.DE2B0C4360D@smtp.codeaurora.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
146 files changed:
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/coredump.c
drivers/net/wireless/ath/ath10k/coredump.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/usb.c
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/dp.c
drivers/net/wireless/ath/ath11k/dp_rx.c
drivers/net/wireless/ath/ath11k/hal_rx.c
drivers/net/wireless/ath/ath11k/hw.c
drivers/net/wireless/ath/ath11k/hw.h
drivers/net/wireless/ath/ath6kl/usb.c
drivers/net/wireless/ath/wcn36xx/dxe.c
drivers/net/wireless/ath/wcn36xx/hal.h
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/ath/wcn36xx/pmc.c
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/ath/wcn36xx/smd.h
drivers/net/wireless/ath/wcn36xx/txrx.c
drivers/net/wireless/ath/wcn36xx/txrx.h
drivers/net/wireless/ath/wcn36xx/wcn36xx.h
drivers/net/wireless/intel/iwlwifi/Makefile
drivers/net/wireless/intel/iwlwifi/cfg/1000.c
drivers/net/wireless/intel/iwlwifi/cfg/2000.c
drivers/net/wireless/intel/iwlwifi/cfg/22000.c
drivers/net/wireless/intel/iwlwifi/cfg/5000.c
drivers/net/wireless/intel/iwlwifi/cfg/6000.c
drivers/net/wireless/intel/iwlwifi/dvm/agn.h
drivers/net/wireless/intel/iwlwifi/dvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/dvm/dev.h
drivers/net/wireless/intel/iwlwifi/dvm/devices.c
drivers/net/wireless/intel/iwlwifi/dvm/led.c
drivers/net/wireless/intel/iwlwifi/dvm/led.h
drivers/net/wireless/intel/iwlwifi/dvm/lib.c
drivers/net/wireless/intel/iwlwifi/dvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/dvm/main.c
drivers/net/wireless/intel/iwlwifi/dvm/power.c
drivers/net/wireless/intel/iwlwifi/dvm/power.h
drivers/net/wireless/intel/iwlwifi/dvm/rs.c
drivers/net/wireless/intel/iwlwifi/dvm/rs.h
drivers/net/wireless/intel/iwlwifi/dvm/rx.c
drivers/net/wireless/intel/iwlwifi/dvm/rxon.c
drivers/net/wireless/intel/iwlwifi/dvm/scan.c
drivers/net/wireless/intel/iwlwifi/dvm/sta.c
drivers/net/wireless/intel/iwlwifi/dvm/tt.c
drivers/net/wireless/intel/iwlwifi/dvm/tt.h
drivers/net/wireless/intel/iwlwifi/dvm/tx.c
drivers/net/wireless/intel/iwlwifi/dvm/ucode.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.c
drivers/net/wireless/intel/iwlwifi/fw/acpi.h
drivers/net/wireless/intel/iwlwifi/fw/api/d3.h
drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
drivers/net/wireless/intel/iwlwifi/fw/api/debug.h
drivers/net/wireless/intel/iwlwifi/fw/api/location.h
drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h
drivers/net/wireless/intel/iwlwifi/fw/api/mac.h
drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h
drivers/net/wireless/intel/iwlwifi/fw/api/phy.h
drivers/net/wireless/intel/iwlwifi/fw/api/power.h
drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
drivers/net/wireless/intel/iwlwifi/fw/api/rx.h
drivers/net/wireless/intel/iwlwifi/fw/api/sta.h
drivers/net/wireless/intel/iwlwifi/fw/api/tx.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/dump.c
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
drivers/net/wireless/intel/iwlwifi/fw/file.h
drivers/net/wireless/intel/iwlwifi/fw/img.c
drivers/net/wireless/intel/iwlwifi/fw/img.h
drivers/net/wireless/intel/iwlwifi/fw/init.c
drivers/net/wireless/intel/iwlwifi/fw/paging.c
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
drivers/net/wireless/intel/iwlwifi/fw/rs.c [new file with mode: 0644]
drivers/net/wireless/intel/iwlwifi/fw/runtime.h
drivers/net/wireless/intel/iwlwifi/fw/uefi.h
drivers/net/wireless/intel/iwlwifi/iwl-config.h
drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
drivers/net/wireless/intel/iwlwifi/iwl-csr.h
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.h
drivers/net/wireless/intel/iwlwifi/iwl-debug.c
drivers/net/wireless/intel/iwlwifi/iwl-debug.h
drivers/net/wireless/intel/iwlwifi/iwl-devtrace-data.h
drivers/net/wireless/intel/iwlwifi/iwl-devtrace-io.h
drivers/net/wireless/intel/iwlwifi/iwl-devtrace-iwlwifi.h
drivers/net/wireless/intel/iwlwifi/iwl-devtrace-msg.h
drivers/net/wireless/intel/iwlwifi/iwl-devtrace-ucode.h
drivers/net/wireless/intel/iwlwifi/iwl-devtrace.c
drivers/net/wireless/intel/iwlwifi/iwl-devtrace.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-drv.h
drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
drivers/net/wireless/intel/iwlwifi/iwl-io.c
drivers/net/wireless/intel/iwlwifi/iwl-io.h
drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
drivers/net/wireless/intel/iwlwifi/iwl-prph.h
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c
drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/power.c
drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.c
drivers/net/wireless/intel/iwlwifi/mvm/rs.h
drivers/net/wireless/intel/iwlwifi/mvm/rx.c
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
drivers/net/wireless/intel/iwlwifi/mvm/scan.c
drivers/net/wireless/intel/iwlwifi/mvm/tx.c
drivers/net/wireless/intel/iwlwifi/mvm/utils.c
drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/marvell/libertas/if_usb.c
drivers/net/wireless/marvell/libertas/mesh.c
drivers/net/wireless/marvell/libertas_tf/if_usb.c
drivers/net/wireless/marvell/mwifiex/usb.c
drivers/net/wireless/mediatek/mt76/eeprom.c
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7915/main.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
drivers/net/wireless/mediatek/mt76/mt7915/regs.h
drivers/net/wireless/mediatek/mt76/mt7921/init.c
drivers/net/wireless/mediatek/mt76/util.h
drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/pci.h
drivers/net/wireless/realtek/rtw89/rtw8852a.c
drivers/net/wireless/rsi/rsi_91x_usb.c
drivers/net/wireless/ti/wlcore/spi.c

index 112e04b..5935e09 100644 (file)
@@ -2690,9 +2690,16 @@ static int ath10k_core_copy_target_iram(struct ath10k *ar)
        int i, ret;
        u32 len, remaining_len;
 
-       hw_mem = ath10k_coredump_get_mem_layout(ar);
+       /* copy target iram feature must work also when
+        * ATH10K_FW_CRASH_DUMP_RAM_DATA is disabled, so
+        * _ath10k_coredump_get_mem_layout() to accomplist that
+        */
+       hw_mem = _ath10k_coredump_get_mem_layout(ar);
        if (!hw_mem)
-               return -ENOMEM;
+               /* if CONFIG_DEV_COREDUMP is disabled we get NULL, then
+                * just silently disable the feature by doing nothing
+                */
+               return 0;
 
        for (i = 0; i < hw_mem->region_table.size; i++) {
                tmp = &hw_mem->region_table.regions[i];
index 7eb7229..55e7e11 100644 (file)
@@ -1447,11 +1447,17 @@ static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
 
 const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar)
 {
-       int i;
-
        if (!test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask))
                return NULL;
 
+       return _ath10k_coredump_get_mem_layout(ar);
+}
+EXPORT_SYMBOL(ath10k_coredump_get_mem_layout);
+
+const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar)
+{
+       int i;
+
        if (WARN_ON(ar->target_version == 0))
                return NULL;
 
@@ -1464,7 +1470,6 @@ const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k
 
        return NULL;
 }
-EXPORT_SYMBOL(ath10k_coredump_get_mem_layout);
 
 struct ath10k_fw_crash_data *ath10k_coredump_new(struct ath10k *ar)
 {
index 42404e2..240d705 100644 (file)
@@ -176,6 +176,7 @@ int ath10k_coredump_register(struct ath10k *ar);
 void ath10k_coredump_unregister(struct ath10k *ar);
 void ath10k_coredump_destroy(struct ath10k *ar);
 
+const struct ath10k_hw_mem_layout *_ath10k_coredump_get_mem_layout(struct ath10k *ar);
 const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k *ar);
 
 #else /* CONFIG_DEV_COREDUMP */
@@ -214,6 +215,12 @@ ath10k_coredump_get_mem_layout(struct ath10k *ar)
        return NULL;
 }
 
+static inline const struct ath10k_hw_mem_layout *
+_ath10k_coredump_get_mem_layout(struct ath10k *ar)
+{
+       return NULL;
+}
+
 #endif /* CONFIG_DEV_COREDUMP */
 
 #endif /* _COREDUMP_H_ */
index 5ec19d9..1f73fbf 100644 (file)
@@ -5583,7 +5583,15 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
                if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL) {
                        arvif->beacon_buf = kmalloc(IEEE80211_MAX_FRAME_LEN,
                                                    GFP_KERNEL);
-                       arvif->beacon_paddr = (dma_addr_t)arvif->beacon_buf;
+
+                       /* Using a kernel pointer in place of a dma_addr_t
+                        * token can lead to undefined behavior if that
+                        * makes it into cache management functions. Use a
+                        * known-invalid address token instead, which
+                        * avoids the warning and makes it easier to catch
+                        * bugs if it does end up getting used.
+                        */
+                       arvif->beacon_paddr = DMA_MAPPING_ERROR;
                } else {
                        arvif->beacon_buf =
                                dma_alloc_coherent(ar->dev,
index 19b9c27..3d98f19 100644 (file)
@@ -525,7 +525,7 @@ static int ath10k_usb_submit_ctrl_in(struct ath10k *ar,
                              req,
                              USB_DIR_IN | USB_TYPE_VENDOR |
                              USB_RECIP_DEVICE, value, index, buf,
-                             size, 2 * HZ);
+                             size, 2000);
 
        if (ret < 0) {
                ath10k_warn(ar, "Failed to read usb control message: %d\n",
@@ -853,6 +853,11 @@ static int ath10k_usb_setup_pipe_resources(struct ath10k *ar,
                                   le16_to_cpu(endpoint->wMaxPacketSize),
                                   endpoint->bInterval);
                }
+
+               /* Ignore broken descriptors. */
+               if (usb_endpoint_maxp(endpoint) == 0)
+                       continue;
+
                urbcount = 0;
 
                pipe_num =
index b0d6922..b5a2af3 100644 (file)
@@ -81,6 +81,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
                .fix_l1ss = true,
                .max_tx_ring = DP_TCL_NUM_RING_MAX,
+               .hal_params = &ath11k_hw_hal_params_ipq8074,
        },
        {
                .hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -129,6 +130,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
                .fix_l1ss = true,
                .max_tx_ring = DP_TCL_NUM_RING_MAX,
+               .hal_params = &ath11k_hw_hal_params_ipq8074,
        },
        {
                .name = "qca6390 hw2.0",
@@ -176,6 +178,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074),
                .fix_l1ss = true,
                .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
+               .hal_params = &ath11k_hw_hal_params_qca6390,
        },
        {
                .name = "qcn9074 hw1.0",
@@ -223,6 +226,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .hal_desc_sz = sizeof(struct hal_rx_desc_qcn9074),
                .fix_l1ss = true,
                .max_tx_ring = DP_TCL_NUM_RING_MAX,
+               .hal_params = &ath11k_hw_hal_params_ipq8074,
        },
        {
                .name = "wcn6855 hw2.0",
@@ -270,6 +274,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
                .fix_l1ss = false,
                .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
+               .hal_params = &ath11k_hw_hal_params_qca6390,
        },
 };
 
index c52d49c..8baaeeb 100644 (file)
@@ -739,6 +739,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
                           int budget)
 {
        struct napi_struct *napi = &irq_grp->napi;
+       const struct ath11k_hw_hal_params *hal_params;
        int grp_id = irq_grp->grp_id;
        int work_done = 0;
        int i = 0, j;
@@ -821,8 +822,9 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
                                struct ath11k_pdev_dp *dp = &ar->dp;
                                struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
 
+                               hal_params = ab->hw_params.hal_params;
                                ath11k_dp_rxbufs_replenish(ab, id, rx_ring, 0,
-                                                          HAL_RX_BUF_RBM_SW3_BM);
+                                                          hal_params->rx_buf_rbm);
                        }
                }
        }
index 1232bbe..c532084 100644 (file)
@@ -499,7 +499,7 @@ static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar,
 
        rx_ring->bufs_max = num_entries;
        ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id, rx_ring, num_entries,
-                                  HAL_RX_BUF_RBM_SW3_BM);
+                                  ar->ab->hw_params.hal_params->rx_buf_rbm);
        return 0;
 }
 
@@ -2756,7 +2756,7 @@ try_again:
                rx_ring = &ar->dp.rx_refill_buf_ring;
 
                ath11k_dp_rxbufs_replenish(ab, i, rx_ring, num_buffs_reaped[i],
-                                          HAL_RX_BUF_RBM_SW3_BM);
+                                          ab->hw_params.hal_params->rx_buf_rbm);
        }
 
        ath11k_dp_rx_process_received_packets(ab, napi, &msdu_list,
@@ -2949,6 +2949,7 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
                                             int *budget, struct sk_buff_head *skb_list)
 {
        struct ath11k *ar;
+       const struct ath11k_hw_hal_params *hal_params;
        struct ath11k_pdev_dp *dp;
        struct dp_rxdma_ring *rx_ring;
        struct hal_srng *srng;
@@ -3019,8 +3020,9 @@ move_next:
                                                        &buf_id);
 
                if (!skb) {
+                       hal_params = ab->hw_params.hal_params;
                        ath11k_hal_rx_buf_addr_info_set(rx_mon_status_desc, 0, 0,
-                                                       HAL_RX_BUF_RBM_SW3_BM);
+                                                       hal_params->rx_buf_rbm);
                        num_buffs_reaped++;
                        break;
                }
@@ -3030,7 +3032,8 @@ move_next:
                         FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id);
 
                ath11k_hal_rx_buf_addr_info_set(rx_mon_status_desc, rxcb->paddr,
-                                               cookie, HAL_RX_BUF_RBM_SW3_BM);
+                                               cookie,
+                                               ab->hw_params.hal_params->rx_buf_rbm);
                ath11k_hal_srng_src_get_next_entry(ab, srng);
                num_buffs_reaped++;
        }
@@ -3419,7 +3422,8 @@ static int ath11k_dp_rx_h_defrag_reo_reinject(struct ath11k *ar, struct dp_rx_ti
        cookie = FIELD_PREP(DP_RXDMA_BUF_COOKIE_PDEV_ID, dp->mac_id) |
                 FIELD_PREP(DP_RXDMA_BUF_COOKIE_BUF_ID, buf_id);
 
-       ath11k_hal_rx_buf_addr_info_set(msdu0, paddr, cookie, HAL_RX_BUF_RBM_SW3_BM);
+       ath11k_hal_rx_buf_addr_info_set(msdu0, paddr, cookie,
+                                       ab->hw_params.hal_params->rx_buf_rbm);
 
        /* Fill mpdu details into reo entrace ring */
        srng = &ab->hal.srng_list[ab->dp.reo_reinject_ring.ring_id];
@@ -3796,7 +3800,7 @@ int ath11k_dp_process_rx_err(struct ath11k_base *ab, struct napi_struct *napi,
                ath11k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies,
                                                 &rbm);
                if (rbm != HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST &&
-                   rbm != HAL_RX_BUF_RBM_SW3_BM) {
+                   rbm != ab->hw_params.hal_params->rx_buf_rbm) {
                        ab->soc_stats.invalid_rbm++;
                        ath11k_warn(ab, "invalid return buffer manager %d\n", rbm);
                        ath11k_dp_rx_link_desc_return(ab, desc,
@@ -3852,7 +3856,7 @@ exit:
                rx_ring = &ar->dp.rx_refill_buf_ring;
 
                ath11k_dp_rxbufs_replenish(ab, i, rx_ring, n_bufs_reaped[i],
-                                          HAL_RX_BUF_RBM_SW3_BM);
+                                          ab->hw_params.hal_params->rx_buf_rbm);
        }
 
        return tot_n_bufs_reaped;
@@ -4148,7 +4152,7 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab,
                rx_ring = &ar->dp.rx_refill_buf_ring;
 
                ath11k_dp_rxbufs_replenish(ab, i, rx_ring, num_buffs_reaped[i],
-                                          HAL_RX_BUF_RBM_SW3_BM);
+                                          ab->hw_params.hal_params->rx_buf_rbm);
        }
 
        rcu_read_lock();
@@ -4257,7 +4261,7 @@ int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget)
 
        if (num_buf_freed)
                ath11k_dp_rxbufs_replenish(ab, mac_id, rx_ring, num_buf_freed,
-                                          HAL_RX_BUF_RBM_SW3_BM);
+                                          ab->hw_params.hal_params->rx_buf_rbm);
 
        return budget - quota;
 }
@@ -4976,6 +4980,7 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
 {
        struct ath11k_pdev_dp *dp = &ar->dp;
        struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
+       const struct ath11k_hw_hal_params *hal_params;
        void *ring_entry;
        void *mon_dst_srng;
        u32 ppdu_id;
@@ -5039,16 +5044,18 @@ static void ath11k_dp_rx_mon_dest_process(struct ath11k *ar, int mac_id,
 
        if (rx_bufs_used) {
                rx_mon_stats->dest_ppdu_done++;
+               hal_params = ar->ab->hw_params.hal_params;
+
                if (ar->ab->hw_params.rxdma1_enable)
                        ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
                                                   &dp->rxdma_mon_buf_ring,
                                                   rx_bufs_used,
-                                                  HAL_RX_BUF_RBM_SW3_BM);
+                                                  hal_params->rx_buf_rbm);
                else
                        ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id,
                                                   &dp->rx_refill_buf_ring,
                                                   rx_bufs_used,
-                                                  HAL_RX_BUF_RBM_SW3_BM);
+                                                  hal_params->rx_buf_rbm);
        }
 }
 
index 325055c..329c404 100644 (file)
@@ -356,6 +356,7 @@ int ath11k_hal_wbm_desc_parse_err(struct ath11k_base *ab, void *desc,
        struct hal_wbm_release_ring *wbm_desc = desc;
        enum hal_wbm_rel_desc_type type;
        enum hal_wbm_rel_src_module rel_src;
+       enum hal_rx_buf_return_buf_manager ret_buf_mgr;
 
        type = FIELD_GET(HAL_WBM_RELEASE_INFO0_DESC_TYPE,
                         wbm_desc->info0);
@@ -371,8 +372,9 @@ int ath11k_hal_wbm_desc_parse_err(struct ath11k_base *ab, void *desc,
            rel_src != HAL_WBM_REL_SRC_MODULE_REO)
                return -EINVAL;
 
-       if (FIELD_GET(BUFFER_ADDR_INFO1_RET_BUF_MGR,
-                     wbm_desc->buf_addr_info.info1) != HAL_RX_BUF_RBM_SW3_BM) {
+       ret_buf_mgr = FIELD_GET(BUFFER_ADDR_INFO1_RET_BUF_MGR,
+                               wbm_desc->buf_addr_info.info1);
+       if (ret_buf_mgr != ab->hw_params.hal_params->rx_buf_rbm) {
                ab->soc_stats.invalid_rbm++;
                return -EINVAL;
        }
index 7a343db..da35fcf 100644 (file)
@@ -7,10 +7,11 @@
 #include <linux/bitops.h>
 #include <linux/bitfield.h>
 
-#include "hw.h"
 #include "core.h"
 #include "ce.h"
 #include "hif.h"
+#include "hal.h"
+#include "hw.h"
 
 /* Map from pdev index to hw mac index */
 static u8 ath11k_hw_ipq8074_mac_from_pdev_id(int pdev_idx)
@@ -2124,3 +2125,11 @@ const struct ath11k_hw_regs wcn6855_regs = {
        .pcie_qserdes_sysclk_en_sel = 0x01e0c0ac,
        .pcie_pcs_osc_dtct_config_base = 0x01e0c628,
 };
+
+const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074 = {
+       .rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
+};
+
+const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390 = {
+       .rx_buf_rbm = HAL_RX_BUF_RBM_SW1_BM,
+};
index 8f92210..19223d3 100644 (file)
@@ -6,6 +6,7 @@
 #ifndef ATH11K_HW_H
 #define ATH11K_HW_H
 
+#include "hal.h"
 #include "wmi.h"
 
 /* Target configuration defines */
@@ -119,6 +120,10 @@ struct ath11k_hw_ring_mask {
        u8 host2rxdma[ATH11K_EXT_IRQ_GRP_NUM_MAX];
 };
 
+struct ath11k_hw_hal_params {
+       enum hal_rx_buf_return_buf_manager rx_buf_rbm;
+};
+
 struct ath11k_hw_params {
        const char *name;
        u16 hw_rev;
@@ -170,6 +175,7 @@ struct ath11k_hw_params {
        u32 hal_desc_sz;
        bool fix_l1ss;
        u8 max_tx_ring;
+       const struct ath11k_hw_hal_params *hal_params;
 };
 
 struct ath11k_hw_ops {
@@ -223,6 +229,9 @@ extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074;
 extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390;
 extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qcn9074;
 
+extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_ipq8074;
+extern const struct ath11k_hw_hal_params ath11k_hw_hal_params_qca6390;
+
 static inline
 int ath11k_hw_get_mac_from_pdev_id(struct ath11k_hw_params *hw,
                                   int pdev_idx)
index 5372e94..aba70f3 100644 (file)
@@ -340,6 +340,11 @@ static int ath6kl_usb_setup_pipe_resources(struct ath6kl_usb *ar_usb)
                                   le16_to_cpu(endpoint->wMaxPacketSize),
                                   endpoint->bInterval);
                }
+
+               /* Ignore broken descriptors. */
+               if (usb_endpoint_maxp(endpoint) == 0)
+                       continue;
+
                urbcount = 0;
 
                pipe_num =
@@ -907,7 +912,7 @@ static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb,
                                 req,
                                 USB_DIR_IN | USB_TYPE_VENDOR |
                                 USB_RECIP_DEVICE, value, index, buf,
-                                size, 2 * HZ);
+                                size, 2000);
 
        if (ret < 0) {
                ath6kl_warn("Failed to read usb control message: %d\n", ret);
index 8e1dbfd..aff04ef 100644 (file)
@@ -403,8 +403,21 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
                        dma_unmap_single(wcn->dev, ctl->desc->src_addr_l,
                                         ctl->skb->len, DMA_TO_DEVICE);
                        info = IEEE80211_SKB_CB(ctl->skb);
-                       if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
-                               /* Keep frame until TX status comes */
+                       if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
+                               if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
+                                       info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+                                       ieee80211_tx_status_irqsafe(wcn->hw, ctl->skb);
+                               } else {
+                                       /* Wait for the TX ack indication or timeout... */
+                                       spin_lock(&wcn->dxe_lock);
+                                       if (WARN_ON(wcn->tx_ack_skb))
+                                               ieee80211_free_txskb(wcn->hw, wcn->tx_ack_skb);
+                                       wcn->tx_ack_skb = ctl->skb; /* Tracking ref */
+                                       mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10);
+                                       spin_unlock(&wcn->dxe_lock);
+                               }
+                               /* do not free, ownership transferred to mac80211 status cb */
+                       } else {
                                ieee80211_free_txskb(wcn->hw, ctl->skb);
                        }
 
@@ -426,7 +439,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
 {
        struct wcn36xx *wcn = (struct wcn36xx *)dev;
        int int_src, int_reason;
-       bool transmitted = false;
 
        wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src);
 
@@ -466,7 +478,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
                if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
                                  WCN36XX_CH_STAT_INT_ED_MASK)) {
                        reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch);
-                       transmitted = true;
                }
        }
 
@@ -479,7 +490,6 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
                                           WCN36XX_DXE_0_INT_CLR,
                                           WCN36XX_INT_MASK_CHAN_TX_L);
 
-
                if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK ) {
                        wcn36xx_dxe_write_register(wcn,
                                                   WCN36XX_DXE_0_INT_ERR_CLR,
@@ -507,25 +517,8 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev)
                if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK |
                                  WCN36XX_CH_STAT_INT_ED_MASK)) {
                        reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch);
-                       transmitted = true;
-               }
-       }
-
-       spin_lock(&wcn->dxe_lock);
-       if (wcn->tx_ack_skb && transmitted) {
-               struct ieee80211_tx_info *info = IEEE80211_SKB_CB(wcn->tx_ack_skb);
-
-               /* TX complete, no need to wait for 802.11 ack indication */
-               if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS &&
-                   info->flags & IEEE80211_TX_CTL_NO_ACK) {
-                       info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
-                       del_timer(&wcn->tx_ack_timer);
-                       ieee80211_tx_status_irqsafe(wcn->hw, wcn->tx_ack_skb);
-                       wcn->tx_ack_skb = NULL;
-                       ieee80211_wake_queues(wcn->hw);
                }
        }
-       spin_unlock(&wcn->dxe_lock);
 
        return IRQ_HANDLED;
 }
@@ -613,6 +606,10 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
        dxe = ctl->desc;
 
        while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) {
+               /* do not read until we own DMA descriptor */
+               dma_rmb();
+
+               /* read/modify DMA descriptor */
                skb = ctl->skb;
                dma_addr = dxe->dst_addr_l;
                ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl, GFP_ATOMIC);
@@ -623,9 +620,15 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
                        dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
                                        DMA_FROM_DEVICE);
                        wcn36xx_rx_skb(wcn, skb);
-               } /* else keep old skb not submitted and use it for rx DMA */
+               }
+               /* else keep old skb not submitted and reuse it for rx DMA
+                * (dropping the packet that it contained)
+                */
 
+               /* flush descriptor changes before re-marking as valid */
+               dma_wmb();
                dxe->ctrl = ctrl;
+
                ctl = ctl->next;
                dxe = ctl->desc;
        }
index 5f1f248..9bea2b0 100644 (file)
@@ -359,6 +359,8 @@ enum wcn36xx_hal_host_msg_type {
        WCN36XX_HAL_START_SCAN_OFFLOAD_RSP = 205,
        WCN36XX_HAL_STOP_SCAN_OFFLOAD_REQ = 206,
        WCN36XX_HAL_STOP_SCAN_OFFLOAD_RSP = 207,
+       WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ = 208,
+       WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP = 209,
        WCN36XX_HAL_SCAN_OFFLOAD_IND = 210,
 
        WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
@@ -1353,6 +1355,36 @@ struct wcn36xx_hal_stop_scan_offload_rsp_msg {
        u32 status;
 } __packed;
 
+#define WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK  0x000000ff
+#define WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK  0x0000ff00
+#define WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK  0x00ff0000
+#define WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK 0xff000000
+#define WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK 0x000000ff
+#define WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE  BIT(7)
+#define WCN36XX_HAL_CHAN_INFO_FLAG_DFS      BIT(10)
+#define WCN36XX_HAL_CHAN_INFO_FLAG_HT       BIT(11)
+#define WCN36XX_HAL_CHAN_INFO_FLAG_VHT      BIT(12)
+#define WCN36XX_HAL_CHAN_INFO_PHY_11A       0
+#define WCN36XX_HAL_CHAN_INFO_PHY_11BG      1
+#define WCN36XX_HAL_DEFAULT_ANT_GAIN        6
+#define WCN36XX_HAL_DEFAULT_MIN_POWER       6
+
+struct wcn36xx_hal_channel_param {
+       u32 mhz;
+       u32 band_center_freq1;
+       u32 band_center_freq2;
+       u32 channel_info;
+       u32 reg_info_1;
+       u32 reg_info_2;
+} __packed;
+
+struct wcn36xx_hal_update_channel_list_req_msg {
+       struct wcn36xx_hal_msg_header header;
+
+       u8 num_channel;
+       struct wcn36xx_hal_channel_param channels[80];
+} __packed;
+
 enum wcn36xx_hal_rate_index {
        HW_RATE_INDEX_1MBPS     = 0x82,
        HW_RATE_INDEX_2MBPS     = 0x84,
index 263af65..b04533b 100644 (file)
@@ -85,7 +85,9 @@ static struct ieee80211_channel wcn_5ghz_channels[] = {
        CHAN5G(5620, 124, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
        CHAN5G(5640, 128, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
        CHAN5G(5660, 132, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
+       CHAN5G(5680, 136, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
        CHAN5G(5700, 140, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
+       CHAN5G(5720, 144, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH),
        CHAN5G(5745, 149, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW),
        CHAN5G(5765, 153, PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW),
        CHAN5G(5785, 157, PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH),
@@ -135,7 +137,9 @@ static struct ieee80211_supported_band wcn_band_2ghz = {
                .cap =  IEEE80211_HT_CAP_GRN_FLD |
                        IEEE80211_HT_CAP_SGI_20 |
                        IEEE80211_HT_CAP_DSSSCCK40 |
-                       IEEE80211_HT_CAP_LSIG_TXOP_PROT,
+                       IEEE80211_HT_CAP_LSIG_TXOP_PROT |
+                       IEEE80211_HT_CAP_SGI_40 |
+                       IEEE80211_HT_CAP_SUP_WIDTH_20_40,
                .ht_supported = true,
                .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
                .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
@@ -613,15 +617,6 @@ static int wcn36xx_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
                                }
                        }
                }
-               /* FIXME: Only enable bmps support when encryption is enabled.
-                * For any reasons, when connected to open/no-security BSS,
-                * the wcn36xx controller in bmps mode does not forward
-                * 'wake-up' beacons despite AP sends DTIM with station AID.
-                * It could be due to a firmware issue or to the way driver
-                * configure the station.
-                */
-               if (vif->type == NL80211_IFTYPE_STATION)
-                       vif_priv->allow_bmps = true;
                break;
        case DISABLE_KEY:
                if (!(IEEE80211_KEY_FLAG_PAIRWISE & key_conf->flags)) {
@@ -659,19 +654,19 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
                           struct ieee80211_scan_request *hw_req)
 {
        struct wcn36xx *wcn = hw->priv;
-       int i;
 
        if (!get_feat_caps(wcn->fw_feat_caps, SCAN_OFFLOAD)) {
                /* fallback to mac80211 software scan */
                return 1;
        }
 
-       /* For unknown reason, the hardware offloaded scan only works with
-        * 2.4Ghz channels, fallback to software scan in other cases.
+       /* Firmware scan offload is limited to 48 channels, fallback to
+        * software driven scanning otherwise.
         */
-       for (i = 0; i < hw_req->req.n_channels; i++) {
-               if (hw_req->req.channels[i]->band != NL80211_BAND_2GHZ)
-                       return 1;
+       if (hw_req->req.n_channels > 48) {
+               wcn36xx_warn("Offload scan aborted, n_channels=%u",
+                            hw_req->req.n_channels);
+               return 1;
        }
 
        mutex_lock(&wcn->scan_lock);
@@ -685,6 +680,7 @@ static int wcn36xx_hw_scan(struct ieee80211_hw *hw,
 
        mutex_unlock(&wcn->scan_lock);
 
+       wcn36xx_smd_update_channel_list(wcn, &hw_req->req);
        return wcn36xx_smd_start_hw_scan(wcn, vif, &hw_req->req);
 }
 
@@ -922,7 +918,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
                                    vif->addr,
                                    bss_conf->aid);
                        vif_priv->sta_assoc = false;
-                       vif_priv->allow_bmps = false;
                        wcn36xx_smd_set_link_st(wcn,
                                                bss_conf->bssid,
                                                vif->addr,
@@ -1132,6 +1127,13 @@ static int wcn36xx_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wow)
                        goto out;
                ret = wcn36xx_smd_wlan_host_suspend_ind(wcn);
        }
+
+       /* Disable IRQ, we don't want to handle any packet before mac80211 is
+        * resumed and ready to receive packets.
+        */
+       disable_irq(wcn->tx_irq);
+       disable_irq(wcn->rx_irq);
+
 out:
        mutex_unlock(&wcn->conf_mutex);
        return ret;
@@ -1154,6 +1156,10 @@ static int wcn36xx_resume(struct ieee80211_hw *hw)
                wcn36xx_smd_ipv6_ns_offload(wcn, vif, false);
                wcn36xx_smd_arp_offload(wcn, vif, false);
        }
+
+       enable_irq(wcn->tx_irq);
+       enable_irq(wcn->rx_irq);
+
        mutex_unlock(&wcn->conf_mutex);
 
        return 0;
@@ -1347,7 +1353,6 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
        ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL);
        ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS);
        ieee80211_hw_set(wcn->hw, REPORTS_TX_ACK_STATUS);
-       ieee80211_hw_set(wcn->hw, CONNECTION_MONITOR);
 
        wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                BIT(NL80211_IFTYPE_AP) |
@@ -1499,6 +1504,7 @@ static int wcn36xx_probe(struct platform_device *pdev)
        mutex_init(&wcn->conf_mutex);
        mutex_init(&wcn->hal_mutex);
        mutex_init(&wcn->scan_lock);
+       __skb_queue_head_init(&wcn->amsdu);
 
        wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL);
        if (!wcn->hal_buf) {
@@ -1576,6 +1582,8 @@ static int wcn36xx_remove(struct platform_device *pdev)
        iounmap(wcn->dxe_base);
        iounmap(wcn->ccu_base);
 
+       __skb_queue_purge(&wcn->amsdu);
+
        mutex_destroy(&wcn->hal_mutex);
        ieee80211_free_hw(hw);
 
index 2d0780f..2c66045 100644 (file)
 
 #include "wcn36xx.h"
 
+#define WCN36XX_BMPS_FAIL_THREHOLD 3
+
 int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
                                 struct ieee80211_vif *vif)
 {
        int ret = 0;
        struct wcn36xx_vif *vif_priv = wcn36xx_vif_to_priv(vif);
-
-       if (!vif_priv->allow_bmps)
-               return -ENOTSUPP;
-
+       /* TODO: Make sure the TX chain clean */
        ret = wcn36xx_smd_enter_bmps(wcn, vif);
        if (!ret) {
                wcn36xx_dbg(WCN36XX_DBG_PMC, "Entered BMPS\n");
                vif_priv->pw_state = WCN36XX_BMPS;
+               vif_priv->bmps_fail_ct = 0;
                vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
        } else {
                /*
@@ -39,6 +39,11 @@ int wcn36xx_pmc_enter_bmps_state(struct wcn36xx *wcn,
                 * received just after auth complete
                 */
                wcn36xx_err("Can not enter BMPS!\n");
+
+               if (vif_priv->bmps_fail_ct++ == WCN36XX_BMPS_FAIL_THREHOLD) {
+                       ieee80211_connection_loss(vif);
+                       vif_priv->bmps_fail_ct = 0;
+               }
        }
        return ret;
 }
index 3979171..ed45e2c 100644 (file)
@@ -16,6 +16,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/bitfield.h>
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
 #include <linux/bitops.h>
@@ -266,7 +267,8 @@ static void wcn36xx_smd_set_sta_ht_params(struct ieee80211_sta *sta,
 
                sta_params->max_ampdu_size = sta->ht_cap.ampdu_factor;
                sta_params->max_ampdu_density = sta->ht_cap.ampdu_density;
-               sta_params->max_amsdu_size = is_cap_supported(caps,
+               /* max_amsdu_size: 1 : 3839 bytes, 0 : 7935 bytes (max) */
+               sta_params->max_amsdu_size = !is_cap_supported(caps,
                        IEEE80211_HT_CAP_MAX_AMSDU);
                sta_params->sgi_20Mhz = is_cap_supported(caps,
                        IEEE80211_HT_CAP_SGI_20);
@@ -927,6 +929,86 @@ out:
        return ret;
 }
 
+int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req)
+{
+       struct wcn36xx_hal_update_channel_list_req_msg *msg_body;
+       int ret, i;
+
+       msg_body = kzalloc(sizeof(*msg_body), GFP_KERNEL);
+       if (!msg_body)
+               return -ENOMEM;
+
+       INIT_HAL_MSG((*msg_body), WCN36XX_HAL_UPDATE_CHANNEL_LIST_REQ);
+
+       msg_body->num_channel = min_t(u8, req->n_channels, sizeof(msg_body->channels));
+       for (i = 0; i < msg_body->num_channel; i++) {
+               struct wcn36xx_hal_channel_param *param = &msg_body->channels[i];
+               u32 min_power = WCN36XX_HAL_DEFAULT_MIN_POWER;
+               u32 ant_gain = WCN36XX_HAL_DEFAULT_ANT_GAIN;
+
+               param->mhz = req->channels[i]->center_freq;
+               param->band_center_freq1 = req->channels[i]->center_freq;
+               param->band_center_freq2 = 0;
+
+               if (req->channels[i]->flags & IEEE80211_CHAN_NO_IR)
+                       param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_PASSIVE;
+
+               if (req->channels[i]->flags & IEEE80211_CHAN_RADAR)
+                       param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_DFS;
+
+               if (req->channels[i]->band == NL80211_BAND_5GHZ) {
+                       param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_HT;
+                       param->channel_info |= WCN36XX_HAL_CHAN_INFO_FLAG_VHT;
+                       param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11A;
+               } else {
+                       param->channel_info |= WCN36XX_HAL_CHAN_INFO_PHY_11BG;
+               }
+
+               if (min_power > req->channels[i]->max_power)
+                       min_power = req->channels[i]->max_power;
+
+               if (req->channels[i]->max_antenna_gain)
+                       ant_gain = req->channels[i]->max_antenna_gain;
+
+               u32p_replace_bits(&param->reg_info_1, min_power,
+                                 WCN36XX_HAL_CHAN_REG1_MIN_PWR_MASK);
+               u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_power,
+                                 WCN36XX_HAL_CHAN_REG1_MAX_PWR_MASK);
+               u32p_replace_bits(&param->reg_info_1, req->channels[i]->max_reg_power,
+                                 WCN36XX_HAL_CHAN_REG1_REG_PWR_MASK);
+               u32p_replace_bits(&param->reg_info_1, 0,
+                                 WCN36XX_HAL_CHAN_REG1_CLASS_ID_MASK);
+               u32p_replace_bits(&param->reg_info_2, ant_gain,
+                                 WCN36XX_HAL_CHAN_REG2_ANT_GAIN_MASK);
+
+               wcn36xx_dbg(WCN36XX_DBG_HAL,
+                           "%s: freq=%u, channel_info=%08x, reg_info1=%08x, reg_info2=%08x\n",
+                           __func__, param->mhz, param->channel_info, param->reg_info_1,
+                           param->reg_info_2);
+       }
+
+       mutex_lock(&wcn->hal_mutex);
+
+       PREPARE_HAL_BUF(wcn->hal_buf, (*msg_body));
+
+       ret = wcn36xx_smd_send_and_wait(wcn, msg_body->header.len);
+       if (ret) {
+               wcn36xx_err("Sending hal_update_channel_list failed\n");
+               goto out;
+       }
+
+       ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len);
+       if (ret) {
+               wcn36xx_err("hal_update_channel_list response failed err=%d\n", ret);
+               goto out;
+       }
+
+out:
+       kfree(msg_body);
+       mutex_unlock(&wcn->hal_mutex);
+       return ret;
+}
+
 static int wcn36xx_smd_switch_channel_rsp(void *buf, size_t len)
 {
        struct wcn36xx_hal_switch_channel_rsp_msg *rsp;
@@ -2394,8 +2476,11 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
        INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
 
        set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
-       if (wcn->rf_id == RF_IRIS_WCN3680)
+       if (wcn->rf_id == RF_IRIS_WCN3680) {
                set_feat_caps(msg_body.feat_caps, DOT11AC);
+               set_feat_caps(msg_body.feat_caps, WLAN_CH144);
+               set_feat_caps(msg_body.feat_caps, ANTENNA_DIVERSITY_SELECTION);
+       }
 
        PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
 
@@ -3137,6 +3222,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,
        case WCN36XX_HAL_HOST_RESUME_RSP:
        case WCN36XX_HAL_ENTER_IMPS_RSP:
        case WCN36XX_HAL_EXIT_IMPS_RSP:
+       case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP:
                memcpy(wcn->hal_buf, buf, len);
                wcn->hal_rsp_len = len;
                complete(&wcn->hal_rsp_compl);
index 5f98c1d..88e045d 100644 (file)
@@ -70,6 +70,7 @@ int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t cha
 int wcn36xx_smd_start_hw_scan(struct wcn36xx *wcn, struct ieee80211_vif *vif,
                              struct cfg80211_scan_request *req);
 int wcn36xx_smd_stop_hw_scan(struct wcn36xx *wcn);
+int wcn36xx_smd_update_channel_list(struct wcn36xx *wcn, struct cfg80211_scan_request *req);
 int wcn36xx_smd_add_sta_self(struct wcn36xx *wcn, struct ieee80211_vif *vif);
 int wcn36xx_smd_delete_sta_self(struct wcn36xx *wcn, u8 *addr);
 int wcn36xx_smd_delete_sta(struct wcn36xx *wcn, u8 sta_index);
index cab196b..75951cc 100644 (file)
@@ -31,6 +31,13 @@ struct wcn36xx_rate {
        enum rate_info_bw bw;
 };
 
+/* Buffer descriptor rx_ch field is limited to 5-bit (4+1), a mapping is used
+ * for 11A Channels.
+ */
+static const u8 ab_rx_ch_map[] = { 36, 40, 44, 48, 52, 56, 60, 64, 100, 104,
+                                  108, 112, 116, 120, 124, 128, 132, 136, 140,
+                                  149, 153, 157, 161, 165, 144 };
+
 static const struct wcn36xx_rate wcn36xx_rate_table[] = {
        /* 11b rates */
        {  10, 0, RX_ENC_LEGACY, 0, RATE_INFO_BW_20 },
@@ -224,6 +231,41 @@ static const struct wcn36xx_rate wcn36xx_rate_table[] = {
        { 4333, 9, RX_ENC_VHT, RX_ENC_FLAG_SHORT_GI, RATE_INFO_BW_80 },
 };
 
+static struct sk_buff *wcn36xx_unchain_msdu(struct sk_buff_head *amsdu)
+{
+       struct sk_buff *skb, *first;
+       int total_len = 0;
+       int space;
+
+       first = __skb_dequeue(amsdu);
+
+       skb_queue_walk(amsdu, skb)
+               total_len += skb->len;
+
+       space = total_len - skb_tailroom(first);
+       if (space > 0 && pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0) {
+               __skb_queue_head(amsdu, first);
+               return NULL;
+       }
+
+       /* Walk list again, copying contents into msdu_head */
+       while ((skb = __skb_dequeue(amsdu))) {
+               skb_copy_from_linear_data(skb, skb_put(first, skb->len),
+                                         skb->len);
+               dev_kfree_skb_irq(skb);
+       }
+
+       return first;
+}
+
+static void __skb_queue_purge_irq(struct sk_buff_head *list)
+{
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(list)) != NULL)
+               dev_kfree_skb_irq(skb);
+}
+
 int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
 {
        struct ieee80211_rx_status status;
@@ -245,6 +287,26 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
                         "BD   <<< ", (char *)bd,
                         sizeof(struct wcn36xx_rx_bd));
 
+       if (bd->pdu.mpdu_data_off <= bd->pdu.mpdu_header_off ||
+           bd->pdu.mpdu_len < bd->pdu.mpdu_header_len)
+               goto drop;
+
+       if (bd->asf && !bd->esf) { /* chained A-MSDU chunks */
+               /* Sanity check */
+               if (bd->pdu.mpdu_data_off + bd->pdu.mpdu_len > WCN36XX_PKT_SIZE)
+                       goto drop;
+
+               skb_put(skb, bd->pdu.mpdu_data_off + bd->pdu.mpdu_len);
+               skb_pull(skb, bd->pdu.mpdu_data_off);
+
+               /* Only set status for first chained BD (with mac header) */
+               goto done;
+       }
+
+       if (bd->pdu.mpdu_header_off < sizeof(*bd) ||
+           bd->pdu.mpdu_header_off + bd->pdu.mpdu_len > WCN36XX_PKT_SIZE)
+               goto drop;
+
        skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len);
        skb_pull(skb, bd->pdu.mpdu_header_off);
 
@@ -291,6 +353,22 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
            ieee80211_is_probe_resp(hdr->frame_control))
                status.boottime_ns = ktime_get_boottime_ns();
 
+       if (bd->scan_learn) {
+               /* If packet originates from hardware scanning, extract the
+                * band/channel from bd descriptor.
+                */
+               u8 hwch = (bd->reserved0 << 4) + bd->rx_ch;
+
+               if (bd->rf_band != 1 && hwch <= sizeof(ab_rx_ch_map) && hwch >= 1) {
+                       status.band = NL80211_BAND_5GHZ;
+                       status.freq = ieee80211_channel_to_frequency(ab_rx_ch_map[hwch - 1],
+                                                                    status.band);
+               } else {
+                       status.band = NL80211_BAND_2GHZ;
+                       status.freq = ieee80211_channel_to_frequency(hwch, status.band);
+               }
+       }
+
        memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 
        if (ieee80211_is_beacon(hdr->frame_control)) {
@@ -305,9 +383,37 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb)
                                 (char *)skb->data, skb->len);
        }
 
+done:
+       /*  Chained AMSDU ? slow path */
+       if (unlikely(bd->asf && !(bd->lsf && bd->esf))) {
+               if (bd->esf && !skb_queue_empty(&wcn->amsdu)) {
+                       wcn36xx_err("Discarding non complete chain");
+                       __skb_queue_purge_irq(&wcn->amsdu);
+               }
+
+               __skb_queue_tail(&wcn->amsdu, skb);
+
+               if (!bd->lsf)
+                       return 0; /* Not the last AMSDU, wait for more */
+
+               skb = wcn36xx_unchain_msdu(&wcn->amsdu);
+               if (!skb)
+                       goto drop;
+       }
+
        ieee80211_rx_irqsafe(wcn->hw, skb);
 
        return 0;
+
+drop: /* drop everything */
+       wcn36xx_err("Drop frame! skb:%p len:%u hoff:%u doff:%u asf=%u esf=%u lsf=%u\n",
+                   skb, bd->pdu.mpdu_len, bd->pdu.mpdu_header_off,
+                   bd->pdu.mpdu_data_off, bd->asf, bd->esf, bd->lsf);
+
+       dev_kfree_skb_irq(skb);
+       __skb_queue_purge_irq(&wcn->amsdu);
+
+       return -EINVAL;
 }
 
 static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
@@ -321,8 +427,6 @@ static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
                bd->pdu.mpdu_header_off;
        bd->pdu.mpdu_len = len;
        bd->pdu.tid = tid;
-       /* Use seq number generated by mac80211 */
-       bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST;
 }
 
 static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
@@ -419,6 +523,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
                tid = ieee80211_get_tid(hdr);
                /* TID->QID is one-to-one mapping */
                bd->queue_id = tid;
+               bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS;
+       } else {
+               bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS;
        }
 
        if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT ||
@@ -429,6 +536,9 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
        if (ieee80211_is_any_nullfunc(hdr->frame_control)) {
                /* Don't use a regular queue for null packet (no ampdu) */
                bd->queue_id = WCN36XX_TX_U_WQ_ID;
+               bd->bd_rate = WCN36XX_BD_RATE_CTRL;
+               if (ieee80211_is_qos_nullfunc(hdr->frame_control))
+                       bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_HOST;
        }
 
        if (bcast) {
@@ -488,6 +598,8 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
                bd->queue_id = WCN36XX_TX_U_WQ_ID;
        *vif_priv = __vif_priv;
 
+       bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS;
+
        wcn36xx_set_tx_pdu(bd,
                           ieee80211_is_data_qos(hdr->frame_control) ?
                           sizeof(struct ieee80211_qos_hdr) :
@@ -502,10 +614,11 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct wcn36xx_vif *vif_priv = NULL;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       unsigned long flags;
        bool is_low = ieee80211_is_data(hdr->frame_control);
        bool bcast = is_broadcast_ether_addr(hdr->addr1) ||
                is_multicast_ether_addr(hdr->addr1);
+       bool ack_ind = (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) &&
+                                       !(info->flags & IEEE80211_TX_CTL_NO_ACK);
        struct wcn36xx_tx_bd bd;
        int ret;
 
@@ -521,30 +634,16 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
 
        bd.dpu_rf = WCN36XX_BMU_WQ_TX;
 
-       if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
+       if (unlikely(ack_ind)) {
                wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
 
-               spin_lock_irqsave(&wcn->dxe_lock, flags);
-               if (wcn->tx_ack_skb) {
-                       spin_unlock_irqrestore(&wcn->dxe_lock, flags);
-                       wcn36xx_warn("tx_ack_skb already set\n");
-                       return -EINVAL;
-               }
-
-               wcn->tx_ack_skb = skb;
-               spin_unlock_irqrestore(&wcn->dxe_lock, flags);
-
                /* Only one at a time is supported by fw. Stop the TX queues
                 * until the ack status gets back.
                 */
                ieee80211_stop_queues(wcn->hw);
 
-               /* TX watchdog if no TX irq or ack indication received  */
-               mod_timer(&wcn->tx_ack_timer, jiffies + HZ / 10);
-
                /* Request ack indication from the firmware */
-               if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
-                       bd.tx_comp = 1;
+               bd.tx_comp = 1;
        }
 
        /* Data frames served first*/
@@ -558,14 +657,8 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
        bd.tx_bd_sign = 0xbdbdbdbd;
 
        ret = wcn36xx_dxe_tx_frame(wcn, vif_priv, &bd, skb, is_low);
-       if (ret && (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
-               /* If the skb has not been transmitted,
-                * don't keep a reference to it.
-                */
-               spin_lock_irqsave(&wcn->dxe_lock, flags);
-               wcn->tx_ack_skb = NULL;
-               spin_unlock_irqrestore(&wcn->dxe_lock, flags);
-
+       if (unlikely(ret && ack_ind)) {
+               /* If the skb has not been transmitted, resume TX queue */
                ieee80211_wake_queues(wcn->hw);
        }
 
index 032216e..b54311f 100644 (file)
@@ -110,7 +110,8 @@ struct wcn36xx_rx_bd {
        /* 0x44 */
        u32     exp_seq_num:12;
        u32     cur_seq_num:12;
-       u32     fr_type_subtype:8;
+       u32     rf_band:2;
+       u32     fr_type_subtype:6;
 
        /* 0x48 */
        u32     msdu_size:16;
index add6e52..1c8d918 100644 (file)
@@ -128,7 +128,6 @@ struct wcn36xx_vif {
        enum wcn36xx_hal_bss_type bss_type;
 
        /* Power management */
-       bool allow_bmps;
        enum wcn36xx_power_state pw_state;
 
        u8 bss_index;
@@ -151,6 +150,8 @@ struct wcn36xx_vif {
        } rekey_data;
 
        struct list_head sta_list;
+
+       int bmps_fail_ct;
 };
 
 /**
@@ -269,6 +270,9 @@ struct wcn36xx {
        struct sk_buff          *tx_ack_skb;
        struct timer_list       tx_ack_timer;
 
+       /* For A-MSDU re-aggregation */
+       struct sk_buff_head amsdu;
+
        /* RF module */
        unsigned                rf_id;
 
@@ -276,7 +280,6 @@ struct wcn36xx {
        /* Debug file system entry */
        struct wcn36xx_dfs_entry    dfs;
 #endif /* CONFIG_WCN36XX_DEBUGFS */
-
 };
 
 static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
index d86918d..0d4656e 100644 (file)
@@ -15,7 +15,7 @@ iwlwifi-objs          += iwl-dbg-tlv.o
 iwlwifi-objs           += iwl-trans.o
 iwlwifi-objs           += queue/tx.o
 
-iwlwifi-objs           += fw/img.o fw/notif-wait.o
+iwlwifi-objs           += fw/img.o fw/notif-wait.o fw/rs.o
 iwlwifi-objs           += fw/dbg.o fw/pnvm.o fw/dump.o
 iwlwifi-$(CONFIG_IWLMVM) += fw/paging.o fw/smem.o fw/init.o
 iwlwifi-$(CONFIG_ACPI) += fw/acpi.o
index 44c4fe9..116defb 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2018 - 2020 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/module.h>
index df6ac00..ab2038a 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2018 - 2020 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/module.h>
index c18b27b..1572097 100644 (file)
@@ -9,7 +9,7 @@
 #include "iwl-prph.h"
 
 /* Highest firmware API version supported */
-#define IWL_22000_UCODE_API_MAX        66
+#define IWL_22000_UCODE_API_MAX        67
 
 /* Lowest firmware API version supported */
 #define IWL_22000_UCODE_API_MIN        39
@@ -53,6 +53,9 @@
 #define IWL_BZ_A_GF_A_FW_PRE           "iwlwifi-bz-a0-gf-a0-"
 #define IWL_BZ_A_GF4_A_FW_PRE          "iwlwifi-bz-a0-gf4-a0-"
 #define IWL_BZ_A_MR_A_FW_PRE           "iwlwifi-bz-a0-mr-a0-"
+#define IWL_BZ_A_FM_A_FW_PRE           "iwlwifi-bz-a0-fm-a0-"
+#define IWL_GL_A_FM_A_FW_PRE           "iwlwifi-gl-a0-fm7-a0-"
+
 
 #define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \
        IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode"
        IWL_BZ_A_GF4_A_FW_PRE __stringify(api) ".ucode"
 #define IWL_BZ_A_MR_A_MODULE_FIRMWARE(api) \
        IWL_BZ_A_MR_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_BZ_A_FM_A_MODULE_FIRMWARE(api) \
+               IWL_BZ_A_FM_A_FW_PRE __stringify(api) ".ucode"
+#define IWL_GL_A_FM_A_MODULE_FIRMWARE(api) \
+               IWL_GL_A_FM_A_FW_PRE __stringify(api) ".ucode"
 
 static const struct iwl_base_params iwl_22000_base_params = {
        .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
@@ -469,6 +476,14 @@ const char iwl_ax210_killer_1675w_name[] =
        "Killer(R) Wi-Fi 6E AX1675w 160MHz Wireless Network Adapter (210D2W)";
 const char iwl_ax210_killer_1675x_name[] =
        "Killer(R) Wi-Fi 6E AX1675x 160MHz Wireless Network Adapter (210NGW)";
+const char iwl_ax211_killer_1675s_name[] =
+       "Killer(R) Wi-Fi 6E AX1675s 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax211_killer_1675i_name[] =
+       "Killer(R) Wi-Fi 6E AX1675i 160MHz Wireless Network Adapter (211NGW)";
+const char iwl_ax411_killer_1690s_name[] =
+       "Killer(R) Wi-Fi 6E AX1690s 160MHz Wireless Network Adapter (411D2W)";
+const char iwl_ax411_killer_1690i_name[] =
+       "Killer(R) Wi-Fi 6E AX1690i 160MHz Wireless Network Adapter (411NGW)";
 
 const struct iwl_cfg iwl_qu_b0_hr1_b0 = {
        .fw_name_pre = IWL_QU_B_HR_B_FW_PRE,
@@ -850,6 +865,20 @@ const struct iwl_cfg iwl_cfg_bz_a0_mr_a0 = {
        .num_rbds = IWL_NUM_RBDS_AX210_HE,
 };
 
+const struct iwl_cfg iwl_cfg_bz_a0_fm_a0 = {
+       .fw_name_pre = IWL_BZ_A_FM_A_FW_PRE,
+       .uhb_supported = true,
+       IWL_DEVICE_BZ,
+       .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
+const struct iwl_cfg iwl_cfg_gl_a0_fm_a0 = {
+       .fw_name_pre = IWL_GL_A_FM_A_FW_PRE,
+       .uhb_supported = true,
+       IWL_DEVICE_BZ,
+       .num_rbds = IWL_NUM_RBDS_AX210_HE,
+};
+
 MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
@@ -876,3 +905,5 @@ MODULE_FIRMWARE(IWL_BZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL_BZ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL_BZ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL_BZ_A_MR_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_BZ_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL_GL_A_FM_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX));
index 6cdd7d9..e2e23d2 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2018 - 2020 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/module.h>
index 541a3ec..20929e5 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2018 - 2020 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/module.h>
index 1276df1..abb8696 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2005-2014 Intel Corporation
+ * Copyright (C) 2005-2014, 2021 Intel Corporation
  */
 #ifndef __iwl_agn_h__
 #define __iwl_agn_h__
@@ -398,8 +398,10 @@ do {                                                                       \
        if (!iwl_is_rfkill((m)))                                        \
                IWL_ERR(m, fmt, ##args);                                \
        else                                                            \
-               __iwl_err((m)->dev, true,                               \
-                         !iwl_have_debug_level(IWL_DL_RADIO),          \
+               __iwl_err((m)->dev,                                     \
+                         iwl_have_debug_level(IWL_DL_RADIO) ?          \
+                               IWL_ERR_MODE_RFKILL :                   \
+                               IWL_ERR_MODE_TRACE_ONLY,                \
                          fmt, ##args);                                 \
 } while (0)
 #else
@@ -408,7 +410,8 @@ do {                                                                        \
        if (!iwl_is_rfkill((m)))                                        \
                IWL_ERR(m, fmt, ##args);                                \
        else                                                            \
-               __iwl_err((m)->dev, true, true, fmt, ##args);   \
+               __iwl_err((m)->dev, IWL_ERR_MODE_TRACE_ONLY,            \
+                         fmt, ##args);                                 \
 } while (0)
 #endif                         /* CONFIG_IWLWIFI_DEBUG */
 
index 9110492..b246dbd 100644 (file)
@@ -3,10 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright (C) 2018 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
 
 #include <linux/slab.h>
index 4bd792c..bbd5740 100644 (file)
@@ -2,11 +2,6 @@
 /******************************************************************************
  *
  * Copyright(c) 2003 - 2014, 2020 Intel Corporation. All rights reserved.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 /*
  * Please use this file (dev.h) for driver implementation definitions.
index c3e2588..39e4090 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright (C) 2019 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/units.h>
index e8a4d60..71f67a0 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  * Copyright (C) 2019 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 
index 6fe2018..5038fc3 100644 (file)
@@ -2,11 +2,6 @@
 /******************************************************************************
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #ifndef __iwl_leds_h__
index 3b937a7..40d790b 100644 (file)
@@ -2,11 +2,6 @@
 /******************************************************************************
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 #include <linux/etherdevice.h>
 #include <linux/kernel.h>
index 75e7665..754876c 100644 (file)
@@ -6,11 +6,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 #include <linux/kernel.h>
 #include <linux/module.h>
index 69d1aae..fbd57a2 100644 (file)
@@ -6,11 +6,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -52,7 +47,6 @@
 
 #define DRV_DESCRIPTION        "Intel(R) Wireless WiFi Link AGN driver for Linux"
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 
 /* Please keep this array *SORTED* by hex value.
index 93ef023..6d16a71 100644 (file)
@@ -6,10 +6,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
 
 
index 3f8db1f..f38201c 100644 (file)
@@ -5,10 +5,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
 #ifndef __iwl_power_setting_h__
 #define __iwl_power_setting_h__
index 548540d..b7c8b20 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright (C) 2019 - 2020 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
index 68a840d..0b47f19 100644 (file)
@@ -2,11 +2,6 @@
 /******************************************************************************
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #ifndef __iwl_agn_rs_h__
index 3cd7b42..db0c41b 100644 (file)
@@ -7,11 +7,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portionhelp of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/etherdevice.h>
index 12a3d46..70338bc 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2015 Intel Deutschland GmbH
- *
- * Contact Information:
- * Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/etherdevice.h>
index c4ecf6e..2d38227 100644 (file)
@@ -3,10 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2018        Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
 #include <linux/slab.h>
 #include <linux/types.h>
index ddc1405..8f7a0f3 100644 (file)
@@ -5,11 +5,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 #include <linux/etherdevice.h>
 #include <net/mac80211.h>
index 2684a92..43e8d04 100644 (file)
@@ -6,10 +6,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
 
 
index 3b0ff45..7ace052 100644 (file)
@@ -5,10 +5,6 @@
  *
  * Portions of this file are derived from the ipw3945 project, as well
  * as portions of the ieee80211 subsystem header files.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  *****************************************************************************/
 #ifndef __iwl_tt_setting_h__
 #define __iwl_tt_setting_h__
index 847b8e0..60a7b61 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright (C) 2019 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/kernel.h>
index 24194c7..4b27a53 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2015 Intel Deutschland GmbH
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/kernel.h>
index 1efac0b..bf431fa 100644 (file)
@@ -184,9 +184,11 @@ int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
 }
 IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32);
 
-union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
-                                        union acpi_object *data,
-                                        int data_size, int *tbl_rev)
+union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
+                                              union acpi_object *data,
+                                              int min_data_size,
+                                              int max_data_size,
+                                              int *tbl_rev)
 {
        int i;
        union acpi_object *wifi_pkg;
@@ -196,7 +198,7 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
         * describes the domain, and one more entry, otherwise there's
         * no point in reading it.
         */
-       if (WARN_ON_ONCE(data_size < 2))
+       if (WARN_ON_ONCE(min_data_size < 2 || min_data_size > max_data_size))
                return ERR_PTR(-EINVAL);
 
        /*
@@ -222,7 +224,8 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
 
                /* skip entries that are not a package with the right size */
                if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
-                   wifi_pkg->package.count != data_size)
+                   wifi_pkg->package.count < min_data_size ||
+                   wifi_pkg->package.count > max_data_size)
                        continue;
 
                domain = &wifi_pkg->package.elements[0];
@@ -236,7 +239,7 @@ union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
 found:
        return wifi_pkg;
 }
-IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg);
+IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range);
 
 int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt,
                     __le32 *block_list_array,
@@ -707,49 +710,103 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
 {
        union acpi_object *wifi_pkg, *data;
        int i, j, k, ret, tbl_rev;
-       int idx = 1; /* start from one to skip the domain */
-       u8 num_bands;
+       u8 num_bands, num_profiles;
+       static const struct {
+               u8 revisions;
+               u8 bands;
+               u8 profiles;
+               u8 min_profiles;
+       } rev_data[] = {
+               {
+                       .revisions = BIT(3),
+                       .bands = ACPI_GEO_NUM_BANDS_REV2,
+                       .profiles = ACPI_NUM_GEO_PROFILES_REV3,
+                       .min_profiles = 3,
+               },
+               {
+                       .revisions = BIT(2),
+                       .bands = ACPI_GEO_NUM_BANDS_REV2,
+                       .profiles = ACPI_NUM_GEO_PROFILES,
+               },
+               {
+                       .revisions = BIT(0) | BIT(1),
+                       .bands = ACPI_GEO_NUM_BANDS_REV0,
+                       .profiles = ACPI_NUM_GEO_PROFILES,
+               },
+       };
+       int idx;
+       /* start from one to skip the domain */
+       int entry_idx = 1;
+
+       BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES_REV3 != IWL_NUM_GEO_PROFILES_V3);
+       BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES != IWL_NUM_GEO_PROFILES);
 
        data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD);
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       /* start by trying to read revision 2 */
-       wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
-                                        ACPI_WGDS_WIFI_DATA_SIZE_REV2,
-                                        &tbl_rev);
-       if (!IS_ERR(wifi_pkg)) {
-               if (tbl_rev != 2) {
-                       ret = PTR_ERR(wifi_pkg);
-                       goto out_free;
-               }
-
-               num_bands = ACPI_GEO_NUM_BANDS_REV2;
-
-               goto read_table;
-       }
-
-       /* then try revision 0 (which is the same as 1) */
-       wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
-                                        ACPI_WGDS_WIFI_DATA_SIZE_REV0,
-                                        &tbl_rev);
-       if (!IS_ERR(wifi_pkg)) {
-               if (tbl_rev != 0 && tbl_rev != 1) {
-                       ret = PTR_ERR(wifi_pkg);
-                       goto out_free;
+       /* read the highest revision we understand first */
+       for (idx = 0; idx < ARRAY_SIZE(rev_data); idx++) {
+               /* min_profiles != 0 requires num_profiles header */
+               u32 hdr_size = 1 + !!rev_data[idx].min_profiles;
+               u32 profile_size = ACPI_GEO_PER_CHAIN_SIZE *
+                                  rev_data[idx].bands;
+               u32 max_size = hdr_size + profile_size * rev_data[idx].profiles;
+               u32 min_size;
+
+               if (!rev_data[idx].min_profiles)
+                       min_size = max_size;
+               else
+                       min_size = hdr_size +
+                                  profile_size * rev_data[idx].min_profiles;
+
+               wifi_pkg = iwl_acpi_get_wifi_pkg_range(fwrt->dev, data,
+                                                      min_size, max_size,
+                                                      &tbl_rev);
+               if (!IS_ERR(wifi_pkg)) {
+                       if (!(BIT(tbl_rev) & rev_data[idx].revisions))
+                               continue;
+
+                       num_bands = rev_data[idx].bands;
+                       num_profiles = rev_data[idx].profiles;
+
+                       if (rev_data[idx].min_profiles) {
+                               /* read header that says # of profiles */
+                               union acpi_object *entry;
+
+                               entry = &wifi_pkg->package.elements[entry_idx];
+                               entry_idx++;
+                               if (entry->type != ACPI_TYPE_INTEGER ||
+                                   entry->integer.value > num_profiles) {
+                                       ret = -EINVAL;
+                                       goto out_free;
+                               }
+                               num_profiles = entry->integer.value;
+
+                               /*
+                                * this also validates >= min_profiles since we
+                                * otherwise wouldn't have gotten the data when
+                                * looking up in ACPI
+                                */
+                               if (wifi_pkg->package.count !=
+                                   min_size + profile_size * num_profiles) {
+                                       ret = -EINVAL;
+                                       goto out_free;
+                               }
+                       }
+                       goto read_table;
                }
-
-               num_bands = ACPI_GEO_NUM_BANDS_REV0;
-
-               goto read_table;
        }
 
-       ret = PTR_ERR(wifi_pkg);
+       if (idx < ARRAY_SIZE(rev_data))
+               ret = PTR_ERR(wifi_pkg);
+       else
+               ret = -ENOENT;
        goto out_free;
 
 read_table:
        fwrt->geo_rev = tbl_rev;
-       for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
+       for (i = 0; i < num_profiles; i++) {
                for (j = 0; j < ACPI_GEO_NUM_BANDS_REV2; j++) {
                        union acpi_object *entry;
 
@@ -762,7 +819,8 @@ read_table:
                                fwrt->geo_profiles[i].bands[j].max =
                                        fwrt->geo_profiles[i].bands[1].max;
                        } else {
-                               entry = &wifi_pkg->package.elements[idx++];
+                               entry = &wifi_pkg->package.elements[entry_idx];
+                               entry_idx++;
                                if (entry->type != ACPI_TYPE_INTEGER ||
                                    entry->integer.value > U8_MAX) {
                                        ret = -EINVAL;
@@ -779,7 +837,8 @@ read_table:
                                        fwrt->geo_profiles[i].bands[j].chains[k] =
                                                fwrt->geo_profiles[i].bands[1].chains[k];
                                } else {
-                                       entry = &wifi_pkg->package.elements[idx++];
+                                       entry = &wifi_pkg->package.elements[entry_idx];
+                                       entry_idx++;
                                        if (entry->type != ACPI_TYPE_INTEGER ||
                                            entry->integer.value > U8_MAX) {
                                                ret = -EINVAL;
@@ -803,10 +862,10 @@ IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table);
 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
 {
        /*
-        * The GEO_TX_POWER_LIMIT command is not supported on earlier
-        * firmware versions.  Unfortunately, we don't have a TLV API
-        * flag to rely on, so rely on the major version which is in
-        * the first byte of ucode_ver.  This was implemented
+        * The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on
+        * earlier firmware versions.  Unfortunately, we don't have a
+        * TLV API flag to rely on, so rely on the major version which
+        * is in the first byte of ucode_ver.  This was implemented
         * initially on version 38 and then backported to 17.  It was
         * also backported to 29, but only for 7265D devices.  The
         * intention was to have it in 36 as well, but not all 8000
@@ -822,14 +881,15 @@ bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
 IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
 
 int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
-                    struct iwl_per_chain_offset *table, u32 n_bands)
+                    struct iwl_per_chain_offset *table,
+                    u32 n_bands, u32 n_profiles)
 {
        int i, j;
 
        if (!iwl_sar_geo_support(fwrt))
                return -EOPNOTSUPP;
 
-       for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
+       for (i = 0; i < n_profiles; i++) {
                for (j = 0; j < n_bands; j++) {
                        struct iwl_per_chain_offset *chain =
                                &table[i * n_bands + j];
index 16ed099..4aaa8a6 100644 (file)
@@ -29,6 +29,7 @@
 #define ACPI_SAR_PROFILE_NUM           4
 
 #define ACPI_NUM_GEO_PROFILES          3
+#define ACPI_NUM_GEO_PROFILES_REV3     8
 #define ACPI_GEO_PER_CHAIN_SIZE                3
 
 #define ACPI_SAR_NUM_CHAINS_REV0       2
 #define ACPI_GEO_NUM_BANDS_REV2                3
 #define ACPI_GEO_NUM_CHAINS            2
 
-#define ACPI_WGDS_WIFI_DATA_SIZE_REV0  (ACPI_NUM_GEO_PROFILES *   \
-                                        ACPI_GEO_NUM_BANDS_REV0 * \
-                                        ACPI_GEO_PER_CHAIN_SIZE + 1)
-#define ACPI_WGDS_WIFI_DATA_SIZE_REV2  (ACPI_NUM_GEO_PROFILES *   \
-                                        ACPI_GEO_NUM_BANDS_REV2 * \
-                                        ACPI_GEO_PER_CHAIN_SIZE + 1)
-
 #define ACPI_WRDD_WIFI_DATA_SIZE       2
 #define ACPI_SPLC_WIFI_DATA_SIZE       2
 #define ACPI_ECKV_WIFI_DATA_SIZE       2
@@ -115,8 +109,10 @@ enum iwl_dsm_funcs_rev_0 {
        DSM_FUNC_QUERY = 0,
        DSM_FUNC_DISABLE_SRD = 1,
        DSM_FUNC_ENABLE_INDONESIA_5G2 = 2,
+       DSM_FUNC_ENABLE_6E = 3,
        DSM_FUNC_11AX_ENABLEMENT = 6,
-       DSM_FUNC_ENABLE_UNII4_CHAN = 7
+       DSM_FUNC_ENABLE_UNII4_CHAN = 7,
+       DSM_FUNC_ACTIVATE_CHANNEL = 8
 };
 
 enum iwl_dsm_values_srd {
@@ -158,10 +154,11 @@ int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func,
 int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
                         const guid_t *guid, u32 *value);
 
-union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
-                                        union acpi_object *data,
-                                        int data_size, int *tbl_rev);
-
+union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev,
+                                              union acpi_object *data,
+                                              int min_data_size,
+                                              int max_data_size,
+                                              int *tbl_rev);
 /**
  * iwl_acpi_get_mcc - read MCC from ACPI, if available
  *
@@ -198,7 +195,8 @@ int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);
 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
 
 int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
-                    struct iwl_per_chain_offset *table, u32 n_bands);
+                    struct iwl_per_chain_offset *table,
+                    u32 n_bands, u32 n_profiles);
 
 int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, __le32 *block_list_array,
                     int *block_list_size);
@@ -230,10 +228,11 @@ static inline int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func,
        return -ENOENT;
 }
 
-static inline union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
-                                                      union acpi_object *data,
-                                                      int data_size,
-                                                      int *tbl_rev)
+static inline union acpi_object *
+iwl_acpi_get_wifi_pkg_range(struct device *dev,
+                           union acpi_object *data,
+                           int min_data_size, int max_data_size,
+                           int *tbl_rev)
 {
        return ERR_PTR(-ENOENT);
 }
@@ -293,4 +292,14 @@ static inline __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt
 }
 
 #endif /* CONFIG_ACPI */
+
+static inline union acpi_object *
+iwl_acpi_get_wifi_pkg(struct device *dev,
+                     union acpi_object *data,
+                     int data_size, int *tbl_rev)
+{
+       return iwl_acpi_get_wifi_pkg_range(dev, data, data_size, data_size,
+                                          tbl_rev);
+}
+
 #endif /* __iwl_fw_acpi__ */
index 3ec82ca..1503119 100644 (file)
@@ -624,7 +624,7 @@ struct iwl_wowlan_status_v6 {
 } __packed; /* WOWLAN_STATUSES_API_S_VER_6 */
 
 /**
- * struct iwl_wowlan_status - WoWLAN status
+ * struct iwl_wowlan_status_v7 - WoWLAN status
  * @gtk: GTK data
  * @igtk: IGTK data
  * @replay_ctr: GTK rekey replay counter
@@ -693,49 +693,6 @@ struct iwl_wowlan_status_v9 {
        u8 wake_packet[]; /* can be truncated from _length to _bufsize */
 } __packed; /* WOWLAN_STATUSES_RSP_API_S_VER_9 */
 
-/**
- * struct iwl_wowlan_status - WoWLAN status
- * @gtk: GTK data
- * @igtk: IGTK data
- * @bigtk: BIGTK data
- * @replay_ctr: GTK rekey replay counter
- * @pattern_number: number of the matched pattern
- * @non_qos_seq_ctr: non-QoS sequence counter to use next
- * @qos_seq_ctr: QoS sequence counters to use next
- * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
- * @num_of_gtk_rekeys: number of GTK rekeys
- * @tid_tear_down: bitmap of TIDs torn down
- * @reserved: reserved
- * @received_beacons: number of received beacons
- * @wake_packet_length: wakeup packet length
- * @wake_packet_bufsize: wakeup packet buffer size
- * @tid_tear_down: bit mask of tids whose BA sessions were closed
- *                in suspend state
- * @wake_packet: wakeup packet
- */
-struct iwl_wowlan_status {
-       struct iwl_wowlan_gtk_status gtk[1];
-       struct iwl_wowlan_igtk_status igtk[1];
-       struct iwl_wowlan_igtk_status bigtk[WOWLAN_IGTK_KEYS_NUM];
-       __le64 replay_ctr;
-       __le16 pattern_number;
-       __le16 non_qos_seq_ctr;
-       __le16 qos_seq_ctr[8];
-       __le32 wakeup_reasons;
-       __le32 num_of_gtk_rekeys;
-       u8 tid_tear_down;
-       u8 reserved[3];
-       __le32 received_beacons;
-       __le32 wake_packet_length;
-       __le32 wake_packet_bufsize;
-       u8 wake_packet[]; /* can be truncated from _length to _bufsize */
-} __packed; /* WOWLAN_STATUSES_API_S_VER_11 */
-
-static inline u8 iwlmvm_wowlan_gtk_idx(struct iwl_wowlan_gtk_status *gtk)
-{
-       return gtk->key_flags & IWL_WOWLAN_GTK_IDX_MASK;
-}
-
 /* TODO: NetDetect API */
 
 #endif /* __iwl_fw_api_d3_h__ */
index d8b5870..3988f5f 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <linux/bitops.h>
 
+#define IWL_FW_INI_HW_SMEM_REGION_ID           15
 #define IWL_FW_INI_MAX_REGION_ID               64
 #define IWL_FW_INI_MAX_NAME                    32
 #define IWL_FW_INI_MAX_CFG_NAME                        64
@@ -243,6 +244,62 @@ struct iwl_fw_ini_hcmd_tlv {
 } __packed; /* FW_TLV_DEBUG_HCMD_API_S_VER_1 */
 
 /**
+* struct iwl_fw_ini_conf_tlv - preset configuration TLV
+*
+* @address: the base address
+* @value: value to set at address
+
+*/
+struct iwl_fw_ini_addr_val {
+       __le32 address;
+       __le32 value;
+} __packed; /* FW_TLV_DEBUG_ADDR_VALUE_VER_1 */
+
+/**
+ * struct iwl_fw_ini_conf_tlv - configuration TLV to set register/memory.
+ *
+ * @hdr: debug header
+ * @time_point: time point to apply config. One of &enum iwl_fw_ini_time_point
+ * @set_type: write access type preset token for time point.
+ *  one of &enum iwl_fw_ini_config_set_type
+ * @addr_offset: the offset to add to any item in address[0] field
+ * @addr_val: address value pair
+ */
+struct iwl_fw_ini_conf_set_tlv {
+       struct iwl_fw_ini_header hdr;
+       __le32 time_point;
+       __le32 set_type;
+       __le32 addr_offset;
+       struct iwl_fw_ini_addr_val addr_val[0];
+} __packed; /* FW_TLV_DEBUG_CONFIG_SET_API_S_VER_1 */
+
+/**
+ * enum iwl_fw_ini_config_set_type
+ *
+ * @IWL_FW_INI_CONFIG_SET_TYPE_INVALID: invalid config set
+ * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: for PERIPHERY MAC configuration
+ * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY: for PERIPHERY PHY configuration
+ * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX: for PERIPHERY AUX configuration
+ * @IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: for DEVICE MEMORY configuration
+ * @IWL_FW_INI_CONFIG_SET_TYPE_CSR: for CSR configuration
+ * @IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: for DBGC_DRAM_ADDR configuration
+ * @IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: for PERIPH SCRATCH HWM configuration
+ * @IWL_FW_INI_ALLOCATION_NUM: max number of configuration supported
+*/
+
+enum iwl_fw_ini_config_set_type {
+       IWL_FW_INI_CONFIG_SET_TYPE_INVALID = 0,
+       IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC,
+       IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_PHY,
+       IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_AUX,
+       IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY,
+       IWL_FW_INI_CONFIG_SET_TYPE_CSR,
+       IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR,
+       IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM,
+       IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM,
+} __packed;
+
+/**
  * enum iwl_fw_ini_allocation_id
  *
  * @IWL_FW_INI_ALLOCATION_INVALID: invalid
index 8adccd5..029ae64 100644 (file)
@@ -361,6 +361,41 @@ struct iwl_buf_alloc_cmd {
        struct iwl_buf_alloc_frag frags[BUF_ALLOC_MAX_NUM_FRAGS];
 } __packed; /* BUFFER_ALLOCATION_CMD_API_S_VER_2 */
 
+#define DRAM_INFO_FIRST_MAGIC_WORD 0x76543210
+#define DRAM_INFO_SECOND_MAGIC_WORD 0x89ABCDEF
+
+/**
+ * struct iwL_dram_info - DRAM fragments allocation struct
+ *
+ * Driver will fill in the first 1K(+) of the pointed DRAM fragment
+ *
+ * @first_word: magic word value
+ * @second_word: magic word value
+ * @framfrags: DRAM fragmentaion detail
+*/
+struct iwl_dram_info {
+       __le32 first_word;
+       __le32 second_word;
+       struct iwl_buf_alloc_cmd dram_frags[IWL_FW_INI_ALLOCATION_NUM - 1];
+} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
+
+/**
+ * struct iwl_dbgc1_info - DBGC1 address and size
+ *
+ * Driver will fill the dbcg1 address and size at address based on config TLV.
+ *
+ * @first_word: all 0 set as identifier
+ * @dbgc1_add_lsb: LSB bits of DBGC1 physical address
+ * @dbgc1_add_msb: MSB bits of DBGC1 physical address
+ * @dbgc1_size: DBGC1 size
+*/
+struct iwl_dbgc1_info {
+       __le32 first_word;
+       __le32 dbgc1_add_lsb;
+       __le32 dbgc1_add_msb;
+       __le32 dbgc1_size;
+} __packed; /* INIT_DRAM_FRAGS_ALLOCATIONS_S_VER_1 */
+
 /**
  * struct iwl_dbg_host_event_cfg_cmd
  * @enabled_severities: enabled severities
index 6bbb8b8..12af94e 100644 (file)
@@ -206,7 +206,7 @@ enum iwl_tof_responder_cfg_flags {
        IWL_TOF_RESPONDER_FLAGS_SPECIFIC_CALIB_MODE = BIT(8),
        IWL_TOF_RESPONDER_FLAGS_FAST_ALGO_SUPPORT = BIT(9),
        IWL_TOF_RESPONDER_FLAGS_RETRY_ON_ALGO_FAIL = BIT(10),
-       IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_ABC_MSK,
+       IWL_TOF_RESPONDER_FLAGS_FTM_TX_ANT = RATE_MCS_ANT_AB_MSK,
        IWL_TOF_RESPONDER_FLAGS_NDP_SUPPORT = BIT(24),
        IWL_TOF_RESPONDER_FLAGS_LMR_FEEDBACK = BIT(25),
        IWL_TOF_RESPONDER_FLAGS_SESSION_ID = BIT(27),
@@ -629,6 +629,7 @@ enum iwl_location_bw {
        IWL_LOCATION_BW_20MHZ,
        IWL_LOCATION_BW_40MHZ,
        IWL_LOCATION_BW_80MHZ,
+       IWL_LOCATION_BW_160MHZ,
 };
 
 #define TK_11AZ_LEN    32
@@ -1500,7 +1501,9 @@ struct iwl_tof_range_rsp_ap_entry_ntfy_v6 {
        u8 reserved[3];
        u8 rx_pn[IEEE80211_CCMP_PN_LEN];
        u8 tx_pn[IEEE80211_CCMP_PN_LEN];
-} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6 */
+} __packed; /* LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_6,
+              LOCATION_RANGE_RSP_AP_ETRY_NTFY_API_S_VER_7 */
+
 
 /**
  * enum iwl_tof_response_status - tof response status
@@ -1581,7 +1584,8 @@ struct iwl_tof_range_rsp_ntfy_v8 {
        u8 last_report;
        u8 reserved;
        struct iwl_tof_range_rsp_ap_entry_ntfy_v6 ap[IWL_MVM_TOF_MAX_APS];
-} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8 */
+} __packed; /* LOCATION_RANGE_RSP_NTFY_API_S_VER_8,
+              LOCATION_RANGE_RSP_NTFY_API_S_VER_9 */
 
 #define IWL_MVM_TOF_MCSI_BUF_SIZE  (245)
 /**
index 6610d12..d088c82 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -39,9 +39,9 @@ enum iwl_mac_conf_subcmd_ids {
        PROBE_RESPONSE_DATA_NOTIF = 0xFC,
 
        /**
-        * @CHANNEL_SWITCH_NOA_NOTIF: &struct iwl_channel_switch_noa_notif
+        * @CHANNEL_SWITCH_START_NOTIF: &struct iwl_channel_switch_start_notif
         */
-       CHANNEL_SWITCH_NOA_NOTIF = 0xFF,
+       CHANNEL_SWITCH_START_NOTIF = 0xFF,
 };
 
 #define IWL_P2P_NOA_DESC_COUNT (2)
@@ -102,11 +102,11 @@ struct iwl_missed_vap_notif {
 } __packed; /* MISSED_VAP_NTFY_API_S_VER_1 */
 
 /**
- * struct iwl_channel_switch_noa_notif - Channel switch NOA notification
+ * struct iwl_channel_switch_start_notif - Channel switch start notification
  *
  * @id_and_color: ID and color of the MAC
  */
-struct iwl_channel_switch_noa_notif {
+struct iwl_channel_switch_start_notif {
        __le32 id_and_color;
 } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */
 
index 7be7715..11f0bd2 100644 (file)
@@ -138,6 +138,8 @@ struct iwl_mac_data_ibss {
  * @FLEXIBLE_TWT_SUPPORTED: AP supports flexible TWT schedule
  * @PROTECTED_TWT_SUPPORTED: AP supports protected TWT frames (with 11w)
  * @BROADCAST_TWT_SUPPORTED: AP and STA support broadcast TWT
+ * @COEX_HIGH_PRIORITY_ENABLE: high priority mode for BT coex, to be used
+ *     during 802.1X negotiation (and allowed during 4-way-HS)
  */
 enum iwl_mac_data_policy {
        TWT_SUPPORTED = BIT(0),
@@ -145,6 +147,7 @@ enum iwl_mac_data_policy {
        FLEXIBLE_TWT_SUPPORTED = BIT(2),
        PROTECTED_TWT_SUPPORTED = BIT(3),
        BROADCAST_TWT_SUPPORTED = BIT(4),
+       COEX_HIGH_PRIORITY_ENABLE = BIT(5),
 };
 
 /**
index cf48c6f..3551a3f 100644 (file)
@@ -472,6 +472,29 @@ struct iwl_lari_config_change_cmd_v4 {
 } __packed; /* LARI_CHANGE_CONF_CMD_S_VER_4 */
 
 /**
+ * struct iwl_lari_config_change_cmd_v5 - change LARI configuration
+ * @config_bitmap: Bitmap of the config commands. Each bit will trigger a
+ *     different predefined FW config operation.
+ * @oem_uhb_allow_bitmap: Bitmap of UHB enabled MCC sets.
+ * @oem_11ax_allow_bitmap: Bitmap of 11ax allowed MCCs. There are two bits
+ *     per country, one to indicate whether to override and the other to
+ *     indicate the value to use.
+ * @oem_unii4_allow_bitmap: Bitmap of unii4 allowed MCCs.There are two bits
+ *     per country, one to indicate whether to override and the other to
+ *     indicate allow/disallow unii4 channels.
+ * @chan_state_active_bitmap: Bitmap for overriding channel state to active.
+ *     Each bit represents a country or region to activate, according to the BIOS
+ *     definitions.
+ */
+struct iwl_lari_config_change_cmd_v5 {
+       __le32 config_bitmap;
+       __le32 oem_uhb_allow_bitmap;
+       __le32 oem_11ax_allow_bitmap;
+       __le32 oem_unii4_allow_bitmap;
+       __le32 chan_state_active_bitmap;
+} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_5 */
+
+/**
  * struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
  * @status: PNVM image loading status
  */
index d07a632..c04f252 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2012-2014, 2019-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2019-2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -29,9 +29,9 @@ enum iwl_phy_ops_subcmd_ids {
        TEMP_REPORTING_THRESHOLDS_CMD = 0x04,
 
        /**
-        * @GEO_TX_POWER_LIMIT: &struct iwl_geo_tx_power_profiles_cmd
+        * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd
         */
-       GEO_TX_POWER_LIMIT = 0x05,
+       PER_CHAIN_LIMIT_OFFSET_CMD = 0x05,
 
        /**
         * @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd
index 8644538..4d671c8 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -378,9 +378,10 @@ struct iwl_dev_tx_power_cmd {
        };
 };
 
-#define IWL_NUM_GEO_PROFILES   3
-#define IWL_NUM_BANDS_PER_CHAIN_V1 2
-#define IWL_NUM_BANDS_PER_CHAIN_V2 3
+#define IWL_NUM_GEO_PROFILES           3
+#define IWL_NUM_GEO_PROFILES_V3                8
+#define IWL_NUM_BANDS_PER_CHAIN_V1     2
+#define IWL_NUM_BANDS_PER_CHAIN_V2     3
 
 /**
  * enum iwl_geo_per_chain_offset_operation - type of operation
@@ -390,10 +391,10 @@ struct iwl_dev_tx_power_cmd {
 enum iwl_geo_per_chain_offset_operation {
        IWL_PER_CHAIN_OFFSET_SET_TABLES,
        IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE,
-};  /* GEO_TX_POWER_LIMIT FLAGS TYPE */
+};  /* PER_CHAIN_OFFSET_OPERATION_E */
 
 /**
- * struct iwl_per_chain_offset - embedded struct for GEO_TX_POWER_LIMIT.
+ * struct iwl_per_chain_offset - embedded struct for PER_CHAIN_LIMIT_OFFSET_CMD.
  * @max_tx_power: maximum allowed tx power.
  * @chain_a: tx power offset for chain a.
  * @chain_b: tx power offset for chain b.
@@ -405,17 +406,17 @@ struct iwl_per_chain_offset {
 } __packed; /* PER_CHAIN_LIMIT_OFFSET_PER_CHAIN_S_VER_1 */
 
 /**
- * struct iwl_geo_tx_power_profile_cmd_v1 - struct for GEO_TX_POWER_LIMIT cmd.
+ * struct iwl_geo_tx_power_profile_cmd_v1 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
  * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
  * @table: offset profile per band.
  */
 struct iwl_geo_tx_power_profiles_cmd_v1 {
        __le32 ops;
        struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];
-} __packed; /* GEO_TX_POWER_LIMIT_VER_1 */
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_1 */
 
 /**
- * struct iwl_geo_tx_power_profile_cmd_v2 - struct for GEO_TX_POWER_LIMIT cmd.
+ * struct iwl_geo_tx_power_profile_cmd_v2 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
  * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
  * @table: offset profile per band.
  * @table_revision: BIOS table revision.
@@ -424,10 +425,10 @@ struct iwl_geo_tx_power_profiles_cmd_v2 {
        __le32 ops;
        struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V1];
        __le32 table_revision;
-} __packed; /* GEO_TX_POWER_LIMIT_VER_2 */
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_2 */
 
 /**
- * struct iwl_geo_tx_power_profile_cmd_v3 - struct for GEO_TX_POWER_LIMIT cmd.
+ * struct iwl_geo_tx_power_profile_cmd_v3 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
  * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
  * @table: offset profile per band.
  * @table_revision: BIOS table revision.
@@ -436,21 +437,47 @@ struct iwl_geo_tx_power_profiles_cmd_v3 {
        __le32 ops;
        struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES][IWL_NUM_BANDS_PER_CHAIN_V2];
        __le32 table_revision;
-} __packed; /* GEO_TX_POWER_LIMIT_VER_3 */
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_3 */
+
+/**
+ * struct iwl_geo_tx_power_profile_cmd_v4 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
+ * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
+ * @table: offset profile per band.
+ * @table_revision: BIOS table revision.
+ */
+struct iwl_geo_tx_power_profiles_cmd_v4 {
+       __le32 ops;
+       struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V1];
+       __le32 table_revision;
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_4 */
+
+/**
+ * struct iwl_geo_tx_power_profile_cmd_v5 - struct for PER_CHAIN_LIMIT_OFFSET_CMD cmd.
+ * @ops: operations, value from &enum iwl_geo_per_chain_offset_operation
+ * @table: offset profile per band.
+ * @table_revision: BIOS table revision.
+ */
+struct iwl_geo_tx_power_profiles_cmd_v5 {
+       __le32 ops;
+       struct iwl_per_chain_offset table[IWL_NUM_GEO_PROFILES_V3][IWL_NUM_BANDS_PER_CHAIN_V2];
+       __le32 table_revision;
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_CMD_VER_5 */
 
 union iwl_geo_tx_power_profiles_cmd {
        struct iwl_geo_tx_power_profiles_cmd_v1 v1;
        struct iwl_geo_tx_power_profiles_cmd_v2 v2;
        struct iwl_geo_tx_power_profiles_cmd_v3 v3;
+       struct iwl_geo_tx_power_profiles_cmd_v4 v4;
+       struct iwl_geo_tx_power_profiles_cmd_v5 v5;
 };
 
 /**
- * struct iwl_geo_tx_power_profiles_resp -  response to GEO_TX_POWER_LIMIT cmd
+ * struct iwl_geo_tx_power_profiles_resp -  response to PER_CHAIN_LIMIT_OFFSET_CMD cmd
  * @profile_idx: current geo profile in use
  */
 struct iwl_geo_tx_power_profiles_resp {
        __le32 profile_idx;
-} __packed; /* GEO_TX_POWER_LIMIT_RESP */
+} __packed; /* PER_CHAIN_LIMIT_OFFSET_RSP */
 
 /**
  * union iwl_ppag_table_cmd - union for all versions of PPAG command
index fc2fa49..a09081d 100644 (file)
@@ -184,6 +184,14 @@ struct iwl_tlc_update_notif {
        __le32 amsdu_enabled;
 } __packed; /* TLC_MNG_UPDATE_NTFY_API_S_VER_2 */
 
+
+#define IWL_MAX_MCS_DISPLAY_SIZE        12
+
+struct iwl_rate_mcs_info {
+       char    mbps[IWL_MAX_MCS_DISPLAY_SIZE];
+       char    mcs[IWL_MAX_MCS_DISPLAY_SIZE];
+};
+
 /*
  * These serve as indexes into
  * struct iwl_rate_info fw_rate_idx_to_plcp[IWL_RATE_COUNT];
@@ -226,6 +234,8 @@ enum {
        IWL_LAST_HE_RATE = IWL_RATE_MCS_11_INDEX,
        IWL_RATE_COUNT_LEGACY = IWL_LAST_NON_HT_RATE + 1,
        IWL_RATE_COUNT = IWL_LAST_HE_RATE + 1,
+       IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
+       IWL_RATE_INVALID = IWL_RATE_COUNT,
 };
 
 #define IWL_RATE_BIT_MSK(r) BIT(IWL_RATE_##r##M_INDEX)
@@ -248,7 +258,7 @@ enum {
 };
 
 /*
- * rate_n_flags bit fields
+ * rate_n_flags bit fields version 1
  *
  * The 32-bit value has different layouts in the low 8 bites depending on the
  * format. There are three formats, HT, VHT and legacy (11abg, with subformats
@@ -266,15 +276,15 @@ enum {
 
 /* Bit 8: (1) HT format, (0) legacy or VHT format */
 #define RATE_MCS_HT_POS 8
-#define RATE_MCS_HT_MSK (1 << RATE_MCS_HT_POS)
+#define RATE_MCS_HT_MSK_V1 BIT(RATE_MCS_HT_POS)
 
 /* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be "0" for this bit to be valid */
-#define RATE_MCS_CCK_POS 9
-#define RATE_MCS_CCK_MSK (1 << RATE_MCS_CCK_POS)
+#define RATE_MCS_CCK_POS_V1 9
+#define RATE_MCS_CCK_MSK_V1 BIT(RATE_MCS_CCK_POS_V1)
 
 /* Bit 26: (1) VHT format, (0) legacy format in bits 8:0 */
-#define RATE_MCS_VHT_POS 26
-#define RATE_MCS_VHT_MSK (1 << RATE_MCS_VHT_POS)
+#define RATE_MCS_VHT_POS_V1 26
+#define RATE_MCS_VHT_MSK_V1 BIT(RATE_MCS_VHT_POS_V1)
 
 
 /*
@@ -300,15 +310,16 @@ enum {
  * streams and 16-23 have three streams. We could also support MCS 32
  * which is the duplicate 20 MHz MCS (bit 5 set, all others zero.)
  */
-#define RATE_HT_MCS_RATE_CODE_MSK      0x7
-#define RATE_HT_MCS_NSS_POS             3
-#define RATE_HT_MCS_NSS_MSK             (3 << RATE_HT_MCS_NSS_POS)
+#define RATE_HT_MCS_RATE_CODE_MSK_V1   0x7
+#define RATE_HT_MCS_NSS_POS_V1          3
+#define RATE_HT_MCS_NSS_MSK_V1          (3 << RATE_HT_MCS_NSS_POS_V1)
+#define RATE_HT_MCS_MIMO2_MSK          BIT(RATE_HT_MCS_NSS_POS_V1)
 
 /* Bit 10: (1) Use Green Field preamble */
 #define RATE_HT_MCS_GF_POS             10
 #define RATE_HT_MCS_GF_MSK             (1 << RATE_HT_MCS_GF_POS)
 
-#define RATE_HT_MCS_INDEX_MSK          0x3f
+#define RATE_HT_MCS_INDEX_MSK_V1       0x3f
 
 /*
  * Very High-throughput (VHT) rate format for bits 7:0
@@ -324,6 +335,7 @@ enum {
 #define RATE_VHT_MCS_RATE_CODE_MSK     0xf
 #define RATE_VHT_MCS_NSS_POS           4
 #define RATE_VHT_MCS_NSS_MSK           (3 << RATE_VHT_MCS_NSS_POS)
+#define RATE_VHT_MCS_MIMO2_MSK         BIT(RATE_VHT_MCS_NSS_POS)
 
 /*
  * Legacy OFDM rate format for bits 7:0
@@ -347,37 +359,30 @@ enum {
  *        110)  11 Mbps
  * (bit 7 is 0)
  */
-#define RATE_LEGACY_RATE_MSK 0xff
+#define RATE_LEGACY_RATE_MSK_V1 0xff
 
 /* Bit 10 - OFDM HE */
-#define RATE_MCS_HE_POS                10
-#define RATE_MCS_HE_MSK                BIT(RATE_MCS_HE_POS)
+#define RATE_MCS_HE_POS_V1     10
+#define RATE_MCS_HE_MSK_V1     BIT(RATE_MCS_HE_POS_V1)
 
 /*
  * Bit 11-12: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz
  * 0 and 1 are valid for HT and VHT, 2 and 3 only for VHT
  */
 #define RATE_MCS_CHAN_WIDTH_POS                11
-#define RATE_MCS_CHAN_WIDTH_MSK                (3 << RATE_MCS_CHAN_WIDTH_POS)
-#define RATE_MCS_CHAN_WIDTH_20         (0 << RATE_MCS_CHAN_WIDTH_POS)
-#define RATE_MCS_CHAN_WIDTH_40         (1 << RATE_MCS_CHAN_WIDTH_POS)
-#define RATE_MCS_CHAN_WIDTH_80         (2 << RATE_MCS_CHAN_WIDTH_POS)
-#define RATE_MCS_CHAN_WIDTH_160                (3 << RATE_MCS_CHAN_WIDTH_POS)
+#define RATE_MCS_CHAN_WIDTH_MSK_V1     (3 << RATE_MCS_CHAN_WIDTH_POS)
 
 /* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
-#define RATE_MCS_SGI_POS               13
-#define RATE_MCS_SGI_MSK               (1 << RATE_MCS_SGI_POS)
+#define RATE_MCS_SGI_POS_V1            13
+#define RATE_MCS_SGI_MSK_V1            BIT(RATE_MCS_SGI_POS_V1)
 
 /* Bit 14-16: Antenna selection (1) Ant A, (2) Ant B, (4) Ant C */
 #define RATE_MCS_ANT_POS               14
 #define RATE_MCS_ANT_A_MSK             (1 << RATE_MCS_ANT_POS)
 #define RATE_MCS_ANT_B_MSK             (2 << RATE_MCS_ANT_POS)
-#define RATE_MCS_ANT_C_MSK             (4 << RATE_MCS_ANT_POS)
 #define RATE_MCS_ANT_AB_MSK            (RATE_MCS_ANT_A_MSK | \
                                         RATE_MCS_ANT_B_MSK)
-#define RATE_MCS_ANT_ABC_MSK           (RATE_MCS_ANT_AB_MSK | \
-                                        RATE_MCS_ANT_C_MSK)
-#define RATE_MCS_ANT_MSK               RATE_MCS_ANT_ABC_MSK
+#define RATE_MCS_ANT_MSK               RATE_MCS_ANT_AB_MSK
 
 /* Bit 17: (0) SS, (1) SS*2 */
 #define RATE_MCS_STBC_POS              17
@@ -411,27 +416,27 @@ enum {
  *     3                       (does not occur)
  */
 #define RATE_MCS_HE_GI_LTF_POS         20
-#define RATE_MCS_HE_GI_LTF_MSK         (3 << RATE_MCS_HE_GI_LTF_POS)
+#define RATE_MCS_HE_GI_LTF_MSK_V1              (3 << RATE_MCS_HE_GI_LTF_POS)
 
 /* Bit 22-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
-#define RATE_MCS_HE_TYPE_POS           22
-#define RATE_MCS_HE_TYPE_SU            (0 << RATE_MCS_HE_TYPE_POS)
-#define RATE_MCS_HE_TYPE_EXT_SU                (1 << RATE_MCS_HE_TYPE_POS)
-#define RATE_MCS_HE_TYPE_MU            (2 << RATE_MCS_HE_TYPE_POS)
-#define RATE_MCS_HE_TYPE_TRIG          (3 << RATE_MCS_HE_TYPE_POS)
-#define RATE_MCS_HE_TYPE_MSK           (3 << RATE_MCS_HE_TYPE_POS)
+#define RATE_MCS_HE_TYPE_POS_V1                22
+#define RATE_MCS_HE_TYPE_SU_V1         (0 << RATE_MCS_HE_TYPE_POS_V1)
+#define RATE_MCS_HE_TYPE_EXT_SU_V1             BIT(RATE_MCS_HE_TYPE_POS_V1)
+#define RATE_MCS_HE_TYPE_MU_V1         (2 << RATE_MCS_HE_TYPE_POS_V1)
+#define RATE_MCS_HE_TYPE_TRIG_V1       (3 << RATE_MCS_HE_TYPE_POS_V1)
+#define RATE_MCS_HE_TYPE_MSK_V1                (3 << RATE_MCS_HE_TYPE_POS_V1)
 
 /* Bit 24-25: (0) 20MHz (no dup), (1) 2x20MHz, (2) 4x20MHz, 3 8x20MHz */
-#define RATE_MCS_DUP_POS               24
-#define RATE_MCS_DUP_MSK               (3 << RATE_MCS_DUP_POS)
+#define RATE_MCS_DUP_POS_V1            24
+#define RATE_MCS_DUP_MSK_V1            (3 << RATE_MCS_DUP_POS_V1)
 
 /* Bit 27: (1) LDPC enabled, (0) LDPC disabled */
-#define RATE_MCS_LDPC_POS              27
-#define RATE_MCS_LDPC_MSK              (1 << RATE_MCS_LDPC_POS)
+#define RATE_MCS_LDPC_POS_V1           27
+#define RATE_MCS_LDPC_MSK_V1           BIT(RATE_MCS_LDPC_POS_V1)
 
 /* Bit 28: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */
-#define RATE_MCS_HE_106T_POS           28
-#define RATE_MCS_HE_106T_MSK           (1 << RATE_MCS_HE_106T_POS)
+#define RATE_MCS_HE_106T_POS_V1                28
+#define RATE_MCS_HE_106T_MSK_V1                BIT(RATE_MCS_HE_106T_POS_V1)
 
 /* Bit 30-31: (1) RTS, (2) CTS */
 #define RATE_MCS_RTS_REQUIRED_POS  (30)
@@ -440,6 +445,152 @@ enum {
 #define RATE_MCS_CTS_REQUIRED_POS  (31)
 #define RATE_MCS_CTS_REQUIRED_MSK  (0x1 << RATE_MCS_CTS_REQUIRED_POS)
 
+/* rate_n_flags bit field version 2
+ *
+ * The 32-bit value has different layouts in the low 8 bits depending on the
+ * format. There are three formats, HT, VHT and legacy (11abg, with subformats
+ * for CCK and OFDM).
+ *
+ */
+
+/* Bits 10-8: rate format
+ * (0) Legacy CCK (1) Legacy OFDM (2) High-throughput (HT)
+ * (3) Very High-throughput (VHT) (4) High-efficiency (HE)
+ * (5) Extremely High-throughput (EHT)
+ */
+#define RATE_MCS_MOD_TYPE_POS          8
+#define RATE_MCS_MOD_TYPE_MSK          (0x7 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_CCK_MSK               (0 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_LEGACY_OFDM_MSK       (1 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_HT_MSK                        (2 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_VHT_MSK               (3 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_HE_MSK                        (4 << RATE_MCS_MOD_TYPE_POS)
+#define RATE_MCS_EHT_MSK               (5 << RATE_MCS_MOD_TYPE_POS)
+
+/*
+ * Legacy CCK rate format for bits 0:3:
+ *
+ * (0) 0xa - 1 Mbps
+ * (1) 0x14 - 2 Mbps
+ * (2) 0x37 - 5.5 Mbps
+ * (3) 0x6e - 11 nbps
+ *
+ * Legacy OFDM rate format for bis 3:0:
+ *
+ * (0) 6 Mbps
+ * (1) 9 Mbps
+ * (2) 12 Mbps
+ * (3) 18 Mbps
+ * (4) 24 Mbps
+ * (5) 36 Mbps
+ * (6) 48 Mbps
+ * (7) 54 Mbps
+ *
+ */
+#define RATE_LEGACY_RATE_MSK           0x7
+
+/*
+ * HT, VHT, HE, EHT rate format for bits 3:0
+ * 3-0: MCS
+ *
+ */
+#define RATE_HT_MCS_CODE_MSK           0x7
+#define RATE_MCS_NSS_POS               4
+#define RATE_MCS_NSS_MSK               (1 << RATE_MCS_NSS_POS)
+#define RATE_MCS_CODE_MSK              0xf
+#define RATE_HT_MCS_INDEX(r)           ((((r) & RATE_MCS_NSS_MSK) >> 1) | \
+                                        ((r) & RATE_HT_MCS_CODE_MSK))
+
+/* Bits 7-5: reserved */
+
+/*
+ * Bits 13-11: (0) 20MHz, (1) 40MHz, (2) 80MHz, (3) 160MHz, (4) 320MHz
+ */
+#define RATE_MCS_CHAN_WIDTH_MSK                        (0x7 << RATE_MCS_CHAN_WIDTH_POS)
+#define RATE_MCS_CHAN_WIDTH_20                 (0 << RATE_MCS_CHAN_WIDTH_POS)
+#define RATE_MCS_CHAN_WIDTH_40                 (1 << RATE_MCS_CHAN_WIDTH_POS)
+#define RATE_MCS_CHAN_WIDTH_80                 (2 << RATE_MCS_CHAN_WIDTH_POS)
+#define RATE_MCS_CHAN_WIDTH_160                        (3 << RATE_MCS_CHAN_WIDTH_POS)
+#define RATE_MCS_CHAN_WIDTH_320                        (4 << RATE_MCS_CHAN_WIDTH_POS)
+
+/* Bit 15-14: Antenna selection:
+ * Bit 14: Ant A active
+ * Bit 15: Ant B active
+ *
+ * All relevant definitions are same as in v1
+ */
+
+/* Bit 16 (1) LDPC enables, (0) LDPC disabled */
+#define RATE_MCS_LDPC_POS      16
+#define RATE_MCS_LDPC_MSK      (1 << RATE_MCS_LDPC_POS)
+
+/* Bit 17: (0) SS, (1) SS*2 (same as v1) */
+
+/* Bit 18: OFDM-HE dual carrier mode (same as v1) */
+
+/* Bit 19: (0) Beamforming is off, (1) Beamforming is on (same as v1) */
+
+/*
+ * Bit 22-20: HE LTF type and guard interval
+ * CCK:
+ *     0                       long preamble
+ *     1                       short preamble
+ * HT/VHT:
+ *     0                       0.8us
+ *     1                       0.4us
+ * HE (ext) SU:
+ *     0                       1xLTF+0.8us
+ *     1                       2xLTF+0.8us
+ *     2                       2xLTF+1.6us
+ *     3                       4xLTF+3.2us
+ *     4                       4xLTF+0.8us
+ * HE MU:
+ *     0                       4xLTF+0.8us
+ *     1                       2xLTF+0.8us
+ *     2                       2xLTF+1.6us
+ *     3                       4xLTF+3.2us
+ * HE TRIG:
+ *     0                       1xLTF+1.6us
+ *     1                       2xLTF+1.6us
+ *     2                       4xLTF+3.2us
+ * */
+#define RATE_MCS_HE_GI_LTF_MSK         (0x7 << RATE_MCS_HE_GI_LTF_POS)
+#define RATE_MCS_SGI_POS               RATE_MCS_HE_GI_LTF_POS
+#define RATE_MCS_SGI_MSK               (1 << RATE_MCS_SGI_POS)
+#define RATE_MCS_HE_SU_4_LTF           3
+#define RATE_MCS_HE_SU_4_LTF_08_GI     4
+
+/* Bit 24-23: HE type. (0) SU, (1) SU_EXT, (2) MU, (3) trigger based */
+#define RATE_MCS_HE_TYPE_POS           23
+#define RATE_MCS_HE_TYPE_SU            (0 << RATE_MCS_HE_TYPE_POS)
+#define RATE_MCS_HE_TYPE_EXT_SU                (1 << RATE_MCS_HE_TYPE_POS)
+#define RATE_MCS_HE_TYPE_MU            (2 << RATE_MCS_HE_TYPE_POS)
+#define RATE_MCS_HE_TYPE_TRIG          (3 << RATE_MCS_HE_TYPE_POS)
+#define RATE_MCS_HE_TYPE_MSK           (3 << RATE_MCS_HE_TYPE_POS)
+
+/* Bit 25: duplicate channel enabled
+ *
+ * if this bit is set, duplicate is according to BW (bits 11-13):
+ *
+ * CCK:  2x 20MHz
+ * OFDM Legacy: N x 20Mhz, (N = BW \ 2 , either 2, 4, 8, 16)
+ * EHT: 2 x BW/2, (80 - 2x40, 160 - 2x80, 320 - 2x160)
+ * */
+#define RATE_MCS_DUP_POS               25
+#define RATE_MCS_DUP_MSK               (1 << RATE_MCS_DUP_POS)
+
+/* Bit 26: (1) 106-tone RX (8 MHz RU), (0) normal bandwidth */
+#define RATE_MCS_HE_106T_POS           26
+#define RATE_MCS_HE_106T_MSK           (1 << RATE_MCS_HE_106T_POS)
+
+/* Bit 27: EHT extra LTF:
+ * instead of 1 LTF for SISO use 2 LTFs,
+ * instead of 2 LTFs for NSTS=2 use 4 LTFs*/
+#define RATE_MCS_EHT_EXTRA_LTF_POS     27
+#define RATE_MCS_EHT_EXTRA_LTF_MSK     (1 << RATE_MCS_EHT_EXTRA_LTF_POS)
+
+/* Bit 31-28: reserved */
+
 /* Link Quality definitions */
 
 /* # entries in rate scale table to support Tx retries */
@@ -557,4 +708,13 @@ struct iwl_lq_cmd {
        __le32 ss_params;
 }; /* LINK_QUALITY_CMD_API_S_VER_1 */
 
+u8 iwl_fw_rate_idx_to_plcp(int idx);
+u32 iwl_new_rate_from_v1(u32 rate_v1);
+u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags);
+const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx);
+const char *iwl_rs_pretty_ant(u8 ant);
+const char *iwl_rs_pretty_bw(int bw);
+int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
+bool iwl_he_is_sgi(u32 rate_n_flags);
+
 #endif /* __iwl_fw_api_rs_h__ */
index 3f13b57..1989b27 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -13,7 +13,6 @@
 #define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
 #define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff
 #define IWL_RX_INFO_ENERGY_ANT_B_MSK 0x0000ff00
-#define IWL_RX_INFO_ENERGY_ANT_C_MSK 0x00ff0000
 #define IWL_RX_INFO_ENERGY_ANT_A_POS 0
 #define IWL_RX_INFO_ENERGY_ANT_B_POS 8
 #define IWL_RX_INFO_ENERGY_ANT_C_POS 16
@@ -126,14 +125,12 @@ enum iwl_rx_phy_flags {
  * @RX_MPDU_RES_STATUS_OVERRUN_OK: there was no RXE overflow
  * @RX_MPDU_RES_STATUS_SRC_STA_FOUND: station was found
  * @RX_MPDU_RES_STATUS_KEY_VALID: key was valid
- * @RX_MPDU_RES_STATUS_KEY_PARAM_OK: key parameters were usable
  * @RX_MPDU_RES_STATUS_ICV_OK: ICV is fine, if not, the packet is destroyed
  * @RX_MPDU_RES_STATUS_MIC_OK: used for CCM alg only. TKIP MIC is checked
  *     in the driver.
  * @RX_MPDU_RES_STATUS_TTAK_OK: TTAK is fine
  * @RX_MPDU_RES_STATUS_MNG_FRAME_REPLAY_ERR:  valid for alg = CCM_CMAC or
- *     alg = CCM only. Checks replay attack for 11w frames. Relevant only if
- *     %RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME is set.
+ *     alg = CCM only. Checks replay attack for 11w frames.
  * @RX_MPDU_RES_STATUS_SEC_NO_ENC: this frame is not encrypted
  * @RX_MPDU_RES_STATUS_SEC_WEP_ENC: this frame is encrypted using WEP
  * @RX_MPDU_RES_STATUS_SEC_CCM_ENC: this frame is encrypted using CCM
@@ -145,9 +142,6 @@ enum iwl_rx_phy_flags {
  * @RX_MPDU_RES_STATUS_SEC_ENC_ERR: this frame couldn't be decrypted
  * @RX_MPDU_RES_STATUS_SEC_ENC_MSK: bitmask of the encryption algorithm
  * @RX_MPDU_RES_STATUS_DEC_DONE: this frame has been successfully decrypted
- * @RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP: extended IV (set with TKIP)
- * @RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT: key ID comparison done
- * @RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME: this frame is an 11w management frame
  * @RX_MPDU_RES_STATUS_CSUM_DONE: checksum was done by the hw
  * @RX_MPDU_RES_STATUS_CSUM_OK: checksum found no errors
  * @RX_MPDU_RES_STATUS_STA_ID_MSK: station ID mask
@@ -158,7 +152,6 @@ enum iwl_mvm_rx_status {
        RX_MPDU_RES_STATUS_OVERRUN_OK                   = BIT(1),
        RX_MPDU_RES_STATUS_SRC_STA_FOUND                = BIT(2),
        RX_MPDU_RES_STATUS_KEY_VALID                    = BIT(3),
-       RX_MPDU_RES_STATUS_KEY_PARAM_OK                 = BIT(4),
        RX_MPDU_RES_STATUS_ICV_OK                       = BIT(5),
        RX_MPDU_RES_STATUS_MIC_OK                       = BIT(6),
        RX_MPDU_RES_STATUS_TTAK_OK                      = BIT(7),
@@ -172,9 +165,6 @@ enum iwl_mvm_rx_status {
        RX_MPDU_RES_STATUS_SEC_ENC_ERR                  = (7 << 8),
        RX_MPDU_RES_STATUS_SEC_ENC_MSK                  = (7 << 8),
        RX_MPDU_RES_STATUS_DEC_DONE                     = BIT(11),
-       RX_MPDU_RES_STATUS_EXT_IV_BIT_CMP               = BIT(13),
-       RX_MPDU_RES_STATUS_KEY_ID_CMP_BIT               = BIT(14),
-       RX_MPDU_RES_STATUS_ROBUST_MNG_FRAME             = BIT(15),
        RX_MPDU_RES_STATUS_CSUM_DONE                    = BIT(16),
        RX_MPDU_RES_STATUS_CSUM_OK                      = BIT(17),
        RX_MDPU_RES_STATUS_STA_ID_SHIFT                 = 24,
@@ -236,7 +226,6 @@ enum iwl_rx_mpdu_status {
        IWL_RX_MPDU_STATUS_OVERRUN_OK           = BIT(1),
        IWL_RX_MPDU_STATUS_SRC_STA_FOUND        = BIT(2),
        IWL_RX_MPDU_STATUS_KEY_VALID            = BIT(3),
-       IWL_RX_MPDU_STATUS_KEY_PARAM_OK         = BIT(4),
        IWL_RX_MPDU_STATUS_ICV_OK               = BIT(5),
        IWL_RX_MPDU_STATUS_MIC_OK               = BIT(6),
        IWL_RX_MPDU_RES_STATUS_TTAK_OK          = BIT(7),
@@ -251,12 +240,8 @@ enum iwl_rx_mpdu_status {
        IWL_RX_MPDU_STATUS_SEC_EXT_ENC          = 0x4 << 8,
        IWL_RX_MPDU_STATUS_SEC_GCM              = 0x5 << 8,
        IWL_RX_MPDU_STATUS_DECRYPTED            = BIT(11),
-       IWL_RX_MPDU_STATUS_WEP_MATCH            = BIT(12),
-       IWL_RX_MPDU_STATUS_EXT_IV_MATCH         = BIT(13),
-       IWL_RX_MPDU_STATUS_KEY_ID_MATCH         = BIT(14),
        IWL_RX_MPDU_STATUS_ROBUST_MNG_FRAME     = BIT(15),
 
-       IWL_RX_MPDU_STATUS_KEY                  = 0x3f0000,
        IWL_RX_MPDU_STATUS_DUPLICATE            = BIT(22),
 
        IWL_RX_MPDU_STATUS_STA_ID               = 0x1f000000,
@@ -460,7 +445,7 @@ struct iwl_rx_mpdu_desc_v1 {
                        __le32 phy_data1;
                };
        };
-} __packed;
+} __packed; /* RX_MPDU_RES_START_API_S_VER_4 */
 
 /**
  * struct iwl_rx_mpdu_desc_v3 - RX MPDU descriptor
@@ -560,7 +545,8 @@ struct iwl_rx_mpdu_desc_v3 {
         * @reserved: reserved
         */
        __le32 reserved[2];
-} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */
+} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
+              RX_MPDU_RES_START_API_S_VER_5 */
 
 /**
  * struct iwl_rx_mpdu_desc - RX MPDU descriptor
@@ -625,7 +611,9 @@ struct iwl_rx_mpdu_desc {
                struct iwl_rx_mpdu_desc_v1 v1;
                struct iwl_rx_mpdu_desc_v3 v3;
        };
-} __packed; /* RX_MPDU_RES_START_API_S_VER_3 */
+} __packed; /* RX_MPDU_RES_START_API_S_VER_3,
+              RX_MPDU_RES_START_API_S_VER_4,
+              RX_MPDU_RES_START_API_S_VER_5 */
 
 #define IWL_RX_DESC_SIZE_V1 offsetofend(struct iwl_rx_mpdu_desc, v1)
 
@@ -679,7 +667,8 @@ struct iwl_rx_no_data {
        __le32 rate;
        __le32 phy_info[2];
        __le32 rx_vec[2];
-} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1 */
+} __packed; /* RX_NO_DATA_NTFY_API_S_VER_1,
+              TX_NO_DATA_NTFY_API_S_VER_2 */
 
 struct iwl_frame_release {
        u8 baid;
index f1a3e14..5edbe27 100644 (file)
@@ -28,6 +28,8 @@
  * @STA_FLG_MAX_AGG_SIZE_256K: maximal size for A-MPDU (256k supported)
  * @STA_FLG_MAX_AGG_SIZE_512K: maximal size for A-MPDU (512k supported)
  * @STA_FLG_MAX_AGG_SIZE_1024K: maximal size for A-MPDU (1024k supported)
+ * @STA_FLG_MAX_AGG_SIZE_2M: maximal size for A-MPDU (2M supported)
+ * @STA_FLG_MAX_AGG_SIZE_4M: maximal size for A-MPDU (4M supported)
  * @STA_FLG_AGG_MPDU_DENS_MSK: maximal MPDU density for Tx aggregation
  * @STA_FLG_FAT_EN_MSK: support for channel width (for Tx). This flag is
  *     initialised by driver and can be updated by fw upon reception of
index 24e4a82..9b3bce8 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
 #ifndef __iwl_fw_api_tx_h__
@@ -81,6 +81,10 @@ enum iwl_tx_cmd_flags {
        IWL_TX_FLAGS_CMD_RATE           = BIT(0),
        IWL_TX_FLAGS_ENCRYPT_DIS        = BIT(1),
        IWL_TX_FLAGS_HIGH_PRI           = BIT(2),
+       /* Use these flags only from
+        * TX_FLAGS_BITS_API_S_VER_4 and above */
+       IWL_TX_FLAGS_RTS                = BIT(3),
+       IWL_TX_FLAGS_CTS                = BIT(4),
 }; /* TX_FLAGS_BITS_API_S_VER_3 */
 
 /**
@@ -267,7 +271,8 @@ struct iwl_tx_cmd_gen2 {
        struct iwl_dram_sec_info dram_info;
        __le32 rate_n_flags;
        struct ieee80211_hdr hdr[];
-} __packed; /* TX_CMD_API_S_VER_7 */
+} __packed; /* TX_CMD_API_S_VER_7,
+              TX_CMD_API_S_VER_9 */
 
 /**
  * struct iwl_tx_cmd_gen3 - TX command struct to FW for AX210+ devices
@@ -290,7 +295,8 @@ struct iwl_tx_cmd_gen3 {
        __le32 rate_n_flags;
        __le64 ttl;
        struct ieee80211_hdr hdr[];
-} __packed; /* TX_CMD_API_S_VER_8 */
+} __packed; /* TX_CMD_API_S_VER_8,
+              TX_CMD_API_S_VER_10 */
 
 /*
  * TX response related data
@@ -591,7 +597,8 @@ struct iwl_mvm_tx_resp {
        __le16 tx_queue;
        __le16 reserved2;
        struct agg_tx_status status;
-} __packed; /* TX_RSP_API_S_VER_6 */
+} __packed; /* TX_RSP_API_S_VER_6,
+              TX_RSP_API_S_VER_7 */
 
 /**
  * struct iwl_mvm_ba_notif - notifies about reception of BA
@@ -715,7 +722,8 @@ struct iwl_mvm_compressed_ba_notif {
        __le16 ra_tid_cnt;
        struct iwl_mvm_compressed_ba_ratid ra_tid[0];
        struct iwl_mvm_compressed_ba_tfd tfd[];
-} __packed; /* COMPRESSED_BA_RES_API_S_VER_4 */
+} __packed; /* COMPRESSED_BA_RES_API_S_VER_4,
+              COMPRESSED_BA_RES_API_S_VER_5 */
 
 /**
  * struct iwl_mac_beacon_cmd_v6 - beacon template command
@@ -755,12 +763,20 @@ struct iwl_mac_beacon_cmd_v7 {
        struct ieee80211_hdr frame[];
 } __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_7 */
 
+/* Bit flags for BEACON_TEMPLATE_CMD_API until version 10 */
+enum iwl_mac_beacon_flags_v1 {
+       IWL_MAC_BEACON_CCK_V1   = BIT(8),
+       IWL_MAC_BEACON_ANT_A_V1 = BIT(9),
+       IWL_MAC_BEACON_ANT_B_V1 = BIT(10),
+       IWL_MAC_BEACON_FILS_V1  = BIT(12),
+};
+
+/* Bit flags for BEACON_TEMPLATE_CMD_API version 11 and above */
 enum iwl_mac_beacon_flags {
-       IWL_MAC_BEACON_CCK      = BIT(8),
-       IWL_MAC_BEACON_ANT_A    = BIT(9),
-       IWL_MAC_BEACON_ANT_B    = BIT(10),
-       IWL_MAC_BEACON_ANT_C    = BIT(11),
-       IWL_MAC_BEACON_FILS     = BIT(12),
+       IWL_MAC_BEACON_CCK      = BIT(5),
+       IWL_MAC_BEACON_ANT_A    = BIT(6),
+       IWL_MAC_BEACON_ANT_B    = BIT(7),
+       IWL_MAC_BEACON_FILS     = BIT(8),
 };
 
 /**
@@ -788,7 +804,9 @@ struct iwl_mac_beacon_cmd {
        __le32 ecsa_offset;
        __le32 csa_offset;
        struct ieee80211_hdr frame[];
-} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10 */
+} __packed; /* BEACON_TEMPLATE_CMD_API_S_VER_10,
+              BEACON_TEMPLATE_CMD_API_S_VER_11,
+              BEACON_TEMPLATE_CMD_API_S_VER_12 */
 
 struct iwl_beacon_notif {
        struct iwl_mvm_tx_resp beacon_notify_hdr;
index 6dcafd0..a39013c 100644 (file)
@@ -159,11 +159,15 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
        iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);
 
        /* Read FIFO */
-       fifo_len /= sizeof(u32); /* Size in DWORDS */
-       for (i = 0; i < fifo_len; i++)
+       for (i = 0; i < fifo_len / sizeof(u32); i++)
                fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
                                                  TXF_READ_MODIFY_DATA +
                                                  offset);
+
+       if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
+               fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
+                                            fifo_data, fifo_len);
+
        *dump_data = iwl_fw_error_next_data(*dump_data);
 }
 
@@ -659,6 +663,10 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
        iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
        *dump_data = iwl_fw_error_next_data(*dump_data);
 
+       if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+               fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs,
+                                            dump_mem->data, len);
+
        IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
 }
 
@@ -752,6 +760,12 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
                                           PAGING_BLOCK_SIZE,
                                           DMA_BIDIRECTIONAL);
                (*data) = iwl_fw_error_next_data(*data);
+
+               if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+                       fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
+                                                    fwrt->fw_paging_db[i].fw_offs,
+                                                    paging->data,
+                                                    PAGING_BLOCK_SIZE);
        }
 }
 
@@ -980,6 +994,11 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
                                         dump_data->data + data_size,
                                         data_size);
 
+               if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+                       fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr,
+                                                    dump_data->data + data_size,
+                                                    data_size);
+
                dump_data = iwl_fw_error_next_data(dump_data);
        }
 
@@ -1146,6 +1165,13 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
        iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
                                 le32_to_cpu(reg->dev_addr.size));
 
+       if ((le32_to_cpu(reg->id) & IWL_FW_INI_REGION_V2_MASK) ==
+               IWL_FW_INI_HW_SMEM_REGION_ID &&
+           fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
+               fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
+                                            range->data,
+                                            le32_to_cpu(reg->dev_addr.size));
+
        return sizeof(*range) + le32_to_cpu(range->range_data_size);
 }
 
@@ -1338,6 +1364,10 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
        for (i = 0; i < iter->fifo_size; i += sizeof(*data))
                *data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));
 
+       if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
+               fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
+                                            reg_dump, iter->fifo_size);
+
 out:
        iwl_trans_release_nic_access(fwrt->trans);
 
@@ -2077,7 +2107,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt,
         */
        hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev);
        if (hw_type == IWL_AX210_HW_TYPE) {
-               u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR);
+               u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR_GEN2);
                u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT);
                u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT);
                u32 masked_bits = is_jacket | (is_cdb << 1);
@@ -2360,7 +2390,9 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
        if (dump_data->monitor_only)
                dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);
 
-       fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
+       fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask,
+                                                     fwrt->sanitize_ops,
+                                                     fwrt->sanitize_ctx);
        file_len = le32_to_cpu(dump_file->file_len);
        fw_error_dump.fwrt_len = file_len;
 
@@ -2788,6 +2820,12 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
        iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr,
                                 fwrt->dump.d3_debug_data,
                                 cfg->d3_debug_data_length);
+
+       if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
+               fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
+                                            cfg->d3_debug_data_base_addr,
+                                            fwrt->dump.d3_debug_data,
+                                            cfg->d3_debug_data_length);
 }
 IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);
 
index a184220..016b3a4 100644 (file)
@@ -214,7 +214,7 @@ static void iwl_fwrt_dump_lmac_error_log(struct iwl_fw_runtime *fwrt, u8 lmac_nu
                /* reset the device */
                iwl_trans_sw_reset(trans);
 
-               err = iwl_finish_nic_init(trans, trans->trans_cfg);
+               err = iwl_finish_nic_init(trans);
                if (err)
                        return;
        }
@@ -328,6 +328,13 @@ static void iwl_fwrt_dump_tcm_error_log(struct iwl_fw_runtime *fwrt)
        for (i = 0; i < ARRAY_SIZE(table.sw_status); i++)
                IWL_ERR(fwrt, "0x%08X | tcm SW status[%d]\n",
                        table.sw_status[i], i);
+
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+               u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
+
+               IWL_ERR(fwrt, "Function Scratch status:\n");
+               IWL_ERR(fwrt, "0x%08X | Func Scratch\n", scratch);
+       }
 }
 
 static void iwl_fwrt_dump_iml_error_log(struct iwl_fw_runtime *fwrt)
index 521ca2b..9036b32 100644 (file)
@@ -342,10 +342,6 @@ struct iwl_fw_ini_dump_cfg_name {
 #define IWL_AX210_HW_TYPE 0x42
 /* How many bits to roll when adding to the HW type of AX210 HW */
 #define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12
-/* This prph is used to tell apart HW_TYPE == 0x42 NICs */
-#define WFPM_OTP_CFG1_ADDR 0xd03098
-#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4)
-#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5)
 
 /* struct iwl_fw_ini_dump_info - ini dump information
  * @version: dump version
index 6c8e9f3..3d572f5 100644 (file)
@@ -100,6 +100,9 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_PNVM_SKU                  = 64,
        IWL_UCODE_TLV_TCM_DEBUG_ADDRS           = 65,
 
+       IWL_UCODE_TLV_SEC_TABLE_ADDR            = 66,
+       IWL_UCODE_TLV_D3_KEK_KCK_ADDR           = 67,
+
        IWL_UCODE_TLV_FW_NUM_STATIONS           = IWL_UCODE_TLV_CONST_BASE + 0,
 
        IWL_UCODE_TLV_TYPE_DEBUG_INFO           = IWL_UCODE_TLV_DEBUG_BASE + 0,
@@ -107,6 +110,7 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_TYPE_HCMD                 = IWL_UCODE_TLV_DEBUG_BASE + 2,
        IWL_UCODE_TLV_TYPE_REGIONS              = IWL_UCODE_TLV_DEBUG_BASE + 3,
        IWL_UCODE_TLV_TYPE_TRIGGERS             = IWL_UCODE_TLV_DEBUG_BASE + 4,
+       IWL_UCODE_TLV_TYPE_CONF_SET             = IWL_UCODE_TLV_DEBUG_BASE + 5,
        IWL_UCODE_TLV_DEBUG_MAX = IWL_UCODE_TLV_TYPE_TRIGGERS,
 
        /* TLVs 0x1000-0x2000 are for internal driver usage */
@@ -416,6 +420,8 @@ enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_PASSIVE_6GHZ_SCAN            = (__force iwl_ucode_tlv_capa_t)58,
        IWL_UCODE_TLV_CAPA_HIDDEN_6GHZ_SCAN             = (__force iwl_ucode_tlv_capa_t)59,
        IWL_UCODE_TLV_CAPA_BROADCAST_TWT                = (__force iwl_ucode_tlv_capa_t)60,
+       IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO               = (__force iwl_ucode_tlv_capa_t)61,
+       IWL_UCODE_TLV_CAPA_RFIM_SUPPORT                 = (__force iwl_ucode_tlv_capa_t)62,
 
        /* set 2 */
        IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE         = (__force iwl_ucode_tlv_capa_t)64,
@@ -449,7 +455,7 @@ enum iwl_ucode_tlv_capa {
        IWL_UCODE_TLV_CAPA_PSC_CHAN_SUPPORT             = (__force iwl_ucode_tlv_capa_t)98,
 
        IWL_UCODE_TLV_CAPA_BIGTK_SUPPORT                = (__force iwl_ucode_tlv_capa_t)100,
-       IWL_UCODE_TLV_CAPA_RFIM_SUPPORT                 = (__force iwl_ucode_tlv_capa_t)102,
+       IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT            = (__force iwl_ucode_tlv_capa_t)104,
 
 #ifdef __CHECKER__
        /* sparse says it cannot increment the previous enum member */
@@ -956,6 +962,10 @@ struct iwl_fw_tcm_error_addr {
        __le32 addr;
 }; /* FW_TLV_TCM_ERROR_INFO_ADDRS_S */
 
+struct iwl_fw_dump_exclude {
+       __le32 addr, size;
+};
+
 static inline size_t _iwl_tlv_array_len(const struct iwl_ucode_tlv *tlv,
                                        size_t fixed_size, size_t var_size)
 {
index c2a4e60..24a9666 100644 (file)
@@ -1,59 +1,7 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
  * Copyright(c) 2019 - 2020 Intel Corporation
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2019 - 2020 Intel Corporation
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *  * Neither the name Intel Corporation nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
+ */
 
 #include "img.h"
 
index 153a352..993bda1 100644 (file)
@@ -124,11 +124,13 @@ struct fw_img {
  * @fw_paging_phys: page phy pointer
  * @fw_paging_block: pointer to the allocated block
  * @fw_paging_size: page size
+ * @fw_offs: offset in the device
  */
 struct iwl_fw_paging {
        dma_addr_t fw_paging_phys;
        struct page *fw_paging_block;
        u32 fw_paging_size;
+       u32 fw_offs;
 };
 
 /**
@@ -174,6 +176,10 @@ struct iwl_fw_dbg {
        u32 dump_mask;
 };
 
+struct iwl_dump_exclude {
+       u32 addr, size;
+};
+
 /**
  * struct iwl_fw - variables associated with the firmware
  *
@@ -194,6 +200,10 @@ struct iwl_fw_dbg {
  * @cipher_scheme: optional external cipher scheme.
  * @human_readable: human readable version
  *     we get the ALIVE from the uCode
+ * @phy_integration_ver: PHY integration version string
+ * @phy_integration_ver_len: length of @phy_integration_ver
+ * @dump_excl: image dump exclusion areas for RT image
+ * @dump_excl_wowlan: image dump exclusion areas for WoWLAN image
  */
 struct iwl_fw {
        u32 ucode_ver;
@@ -225,6 +235,8 @@ struct iwl_fw {
 
        u8 *phy_integration_ver;
        u32 phy_integration_ver_len;
+
+       struct iwl_dump_exclude dump_excl[2], dump_excl_wowlan[2];
 };
 
 static inline const char *get_fw_dbg_mode_string(int mode)
index 2ecec00..566957a 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
  * Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2020 Intel Corporation
+ * Copyright (C) 2019-2021 Intel Corporation
  */
 #include "iwl-drv.h"
 #include "runtime.h"
@@ -16,6 +16,8 @@
 void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
                        const struct iwl_fw *fw,
                        const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
+                       const struct iwl_dump_sanitize_ops *sanitize_ops,
+                       void *sanitize_ctx,
                        struct dentry *dbgfs_dir)
 {
        int i;
@@ -26,6 +28,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
        fwrt->dev = trans->dev;
        fwrt->dump.conf = FW_DBG_INVALID;
        fwrt->ops = ops;
+       fwrt->sanitize_ops = sanitize_ops;
+       fwrt->sanitize_ctx = sanitize_ctx;
        fwrt->ops_ctx = ops_ctx;
        for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
                fwrt->dump.wks[i].idx = i;
index 4a8fe96..58ca384 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -152,6 +152,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
        memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block),
               image->sec[sec_idx].data,
               image->sec[sec_idx].len);
+       fwrt->fw_paging_db[0].fw_offs = image->sec[sec_idx].offset;
        dma_sync_single_for_device(fwrt->trans->dev,
                                   fwrt->fw_paging_db[0].fw_paging_phys,
                                   fwrt->fw_paging_db[0].fw_paging_size,
@@ -197,6 +198,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
 
                memcpy(page_address(block->fw_paging_block),
                       image->sec[sec_idx].data + offset, len);
+               block->fw_offs = image->sec[sec_idx].offset + offset;
                dma_sync_single_for_device(fwrt->trans->dev,
                                           block->fw_paging_phys,
                                           block->fw_paging_size,
index 069fcbc..7d4aa39 100644 (file)
@@ -162,7 +162,7 @@ done:
                goto out;
        }
 
-       IWL_INFO(trans, "loaded PNVM version 0x%0x\n", sha1);
+       IWL_INFO(trans, "loaded PNVM version %08x\n", sha1);
 
        ret = iwl_trans_set_pnvm(trans, pnvm_data, size);
 out:
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/rs.c b/drivers/net/wireless/intel/iwlwifi/fw/rs.c
new file mode 100644 (file)
index 0000000..a21c3be
--- /dev/null
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/*
+ * Copyright (C) 2021 Intel Corporation
+ */
+
+#include <net/mac80211.h>
+#include "fw/api/rs.h"
+#include "iwl-drv.h"
+#include "iwl-config.h"
+
+#define IWL_DECLARE_RATE_INFO(r) \
+       [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP
+
+/*
+ * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP
+ * */
+static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {
+       IWL_DECLARE_RATE_INFO(1),
+       IWL_DECLARE_RATE_INFO(2),
+       IWL_DECLARE_RATE_INFO(5),
+       IWL_DECLARE_RATE_INFO(11),
+       IWL_DECLARE_RATE_INFO(6),
+       IWL_DECLARE_RATE_INFO(9),
+       IWL_DECLARE_RATE_INFO(12),
+       IWL_DECLARE_RATE_INFO(18),
+       IWL_DECLARE_RATE_INFO(24),
+       IWL_DECLARE_RATE_INFO(36),
+       IWL_DECLARE_RATE_INFO(48),
+       IWL_DECLARE_RATE_INFO(54),
+};
+
+/* mbps, mcs */
+static const struct iwl_rate_mcs_info rate_mcs[IWL_RATE_COUNT] = {
+       {  "1", "BPSK DSSS"},
+       {  "2", "QPSK DSSS"},
+       {"5.5", "BPSK CCK"},
+       { "11", "QPSK CCK"},
+       {  "6", "BPSK 1/2"},
+       {  "9", "BPSK 1/2"},
+       { "12", "QPSK 1/2"},
+       { "18", "QPSK 3/4"},
+       { "24", "16QAM 1/2"},
+       { "36", "16QAM 3/4"},
+       { "48", "64QAM 2/3"},
+       { "54", "64QAM 3/4"},
+       { "60", "64QAM 5/6"},
+};
+
+static const char * const ant_name[] = {
+       [ANT_NONE] = "None",
+       [ANT_A]    = "A",
+       [ANT_B]    = "B",
+       [ANT_AB]   = "AB",
+};
+
+static const char * const pretty_bw[] = {
+       "20Mhz",
+       "40Mhz",
+       "80Mhz",
+       "160 Mhz",
+       "320Mhz",
+};
+
+u8 iwl_fw_rate_idx_to_plcp(int idx)
+{
+       return fw_rate_idx_to_plcp[idx];
+}
+IWL_EXPORT_SYMBOL(iwl_fw_rate_idx_to_plcp);
+
+const struct iwl_rate_mcs_info *iwl_rate_mcs(int idx)
+{
+       return &rate_mcs[idx];
+}
+IWL_EXPORT_SYMBOL(iwl_rate_mcs);
+
+const char *iwl_rs_pretty_ant(u8 ant)
+{
+       if (ant >= ARRAY_SIZE(ant_name))
+               return "UNKNOWN";
+
+       return ant_name[ant];
+}
+IWL_EXPORT_SYMBOL(iwl_rs_pretty_ant);
+
+const char *iwl_rs_pretty_bw(int bw)
+{
+       if (bw >= ARRAY_SIZE(pretty_bw))
+               return "unknown bw";
+
+       return pretty_bw[bw];
+}
+IWL_EXPORT_SYMBOL(iwl_rs_pretty_bw);
+
+u32 iwl_new_rate_from_v1(u32 rate_v1)
+{
+       u32 rate_v2 = 0;
+       u32 dup = 0;
+
+       if (rate_v1 == 0)
+               return rate_v1;
+       /* convert rate */
+       if (rate_v1 & RATE_MCS_HT_MSK_V1) {
+               u32 nss = 0;
+
+               rate_v2 |= RATE_MCS_HT_MSK;
+               rate_v2 |=
+                       rate_v1 & RATE_HT_MCS_RATE_CODE_MSK_V1;
+               nss = (rate_v1 & RATE_HT_MCS_MIMO2_MSK) >>
+                       RATE_HT_MCS_NSS_POS_V1;
+               rate_v2 |= nss << RATE_MCS_NSS_POS;
+       } else if (rate_v1 & RATE_MCS_VHT_MSK_V1 ||
+                  rate_v1 & RATE_MCS_HE_MSK_V1) {
+               rate_v2 |= rate_v1 & RATE_VHT_MCS_RATE_CODE_MSK;
+
+               rate_v2 |= rate_v1 & RATE_VHT_MCS_MIMO2_MSK;
+
+               if (rate_v1 & RATE_MCS_HE_MSK_V1) {
+                       u32 he_type_bits = rate_v1 & RATE_MCS_HE_TYPE_MSK_V1;
+                       u32 he_type = he_type_bits >> RATE_MCS_HE_TYPE_POS_V1;
+                       u32 he_106t = (rate_v1 & RATE_MCS_HE_106T_MSK_V1) >>
+                               RATE_MCS_HE_106T_POS_V1;
+                       u32 he_gi_ltf = (rate_v1 & RATE_MCS_HE_GI_LTF_MSK_V1) >>
+                               RATE_MCS_HE_GI_LTF_POS;
+
+                       if ((he_type_bits == RATE_MCS_HE_TYPE_SU ||
+                            he_type_bits == RATE_MCS_HE_TYPE_EXT_SU) &&
+                           he_gi_ltf == RATE_MCS_HE_SU_4_LTF)
+                               /* the new rate have an additional bit to
+                                * represent the value 4 rather then using SGI
+                                * bit for this purpose - as it was done in the old
+                                * rate */
+                               he_gi_ltf += (rate_v1 & RATE_MCS_SGI_MSK_V1) >>
+                                       RATE_MCS_SGI_POS_V1;
+
+                       rate_v2 |= he_gi_ltf << RATE_MCS_HE_GI_LTF_POS;
+                       rate_v2 |= he_type << RATE_MCS_HE_TYPE_POS;
+                       rate_v2 |= he_106t << RATE_MCS_HE_106T_POS;
+                       rate_v2 |= rate_v1 & RATE_HE_DUAL_CARRIER_MODE_MSK;
+                       rate_v2 |= RATE_MCS_HE_MSK;
+               } else {
+                       rate_v2 |= RATE_MCS_VHT_MSK;
+               }
+       /* if legacy format */
+       } else {
+               u32 legacy_rate = iwl_legacy_rate_to_fw_idx(rate_v1);
+
+               WARN_ON(legacy_rate < 0);
+               rate_v2 |= legacy_rate;
+               if (!(rate_v1 & RATE_MCS_CCK_MSK_V1))
+                       rate_v2 |= RATE_MCS_LEGACY_OFDM_MSK;
+       }
+
+       /* convert flags */
+       if (rate_v1 & RATE_MCS_LDPC_MSK_V1)
+               rate_v2 |= RATE_MCS_LDPC_MSK;
+       rate_v2 |= (rate_v1 & RATE_MCS_CHAN_WIDTH_MSK_V1) |
+               (rate_v1 & RATE_MCS_ANT_AB_MSK) |
+               (rate_v1 & RATE_MCS_STBC_MSK) |
+               (rate_v1 & RATE_MCS_BF_MSK);
+
+       dup = (rate_v1 & RATE_MCS_DUP_MSK_V1) >> RATE_MCS_DUP_POS_V1;
+       if (dup) {
+               rate_v2 |= RATE_MCS_DUP_MSK;
+               rate_v2 |= dup << RATE_MCS_CHAN_WIDTH_POS;
+       }
+
+       if ((!(rate_v1 & RATE_MCS_HE_MSK_V1)) &&
+           (rate_v1 & RATE_MCS_SGI_MSK_V1))
+               rate_v2 |= RATE_MCS_SGI_MSK;
+
+       return rate_v2;
+}
+IWL_EXPORT_SYMBOL(iwl_new_rate_from_v1);
+
+u32 iwl_legacy_rate_to_fw_idx(u32 rate_n_flags)
+{
+       int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
+       int idx;
+       bool ofdm = !(rate_n_flags & RATE_MCS_CCK_MSK_V1);
+       int offset = ofdm ? IWL_FIRST_OFDM_RATE : 0;
+       int last = ofdm ? IWL_RATE_COUNT_LEGACY : IWL_FIRST_OFDM_RATE;
+
+       for (idx = offset; idx < last; idx++)
+               if (iwl_fw_rate_idx_to_plcp(idx) == rate)
+                       return idx - offset;
+       return -1;
+}
+
+int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
+{
+       char *type;
+       u8 mcs = 0, nss = 0;
+       u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
+       u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK) >>
+               RATE_MCS_CHAN_WIDTH_POS;
+       u32 format = rate & RATE_MCS_MOD_TYPE_MSK;
+       bool sgi;
+
+       if (format == RATE_MCS_CCK_MSK ||
+           format == RATE_MCS_LEGACY_OFDM_MSK) {
+               int legacy_rate = rate & RATE_LEGACY_RATE_MSK;
+               int index = format == RATE_MCS_CCK_MSK ?
+                       legacy_rate :
+                       legacy_rate + IWL_FIRST_OFDM_RATE;
+
+               return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
+                                iwl_rs_pretty_ant(ant),
+                                index == IWL_RATE_INVALID ? "BAD" :
+                                iwl_rate_mcs(index)->mbps);
+       }
+
+       if (format ==  RATE_MCS_VHT_MSK)
+               type = "VHT";
+       else if (format ==  RATE_MCS_HT_MSK)
+               type = "HT";
+       else if (format == RATE_MCS_HE_MSK)
+               type = "HE";
+       else
+               type = "Unknown"; /* shouldn't happen */
+
+       mcs = format == RATE_MCS_HT_MSK ?
+               RATE_HT_MCS_INDEX(rate) :
+               rate & RATE_MCS_CODE_MSK;
+       nss = ((rate & RATE_MCS_NSS_MSK)
+              >> RATE_MCS_NSS_POS) + 1;
+       sgi = format == RATE_MCS_HE_MSK ?
+               iwl_he_is_sgi(rate) :
+               rate & RATE_MCS_SGI_MSK;
+
+       return scnprintf(buf, bufsz,
+                        "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
+                        rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
+                        (sgi) ? "SGI " : "NGI ",
+                        (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
+                        (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
+                        (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
+                        (rate & RATE_MCS_BF_MSK) ? "BF " : "");
+}
+IWL_EXPORT_SYMBOL(rs_pretty_print_rate);
+
+bool iwl_he_is_sgi(u32 rate_n_flags)
+{
+       u32 type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
+       u32 ltf_gi = rate_n_flags & RATE_MCS_HE_GI_LTF_MSK;
+
+       if (type == RATE_MCS_HE_TYPE_SU ||
+           type == RATE_MCS_HE_TYPE_EXT_SU)
+               return ltf_gi == RATE_MCS_HE_SU_4_LTF_08_GI;
+       return false;
+}
+IWL_EXPORT_SYMBOL(iwl_he_is_sgi);
+
index 35af85a..69799f1 100644 (file)
@@ -105,6 +105,9 @@ struct iwl_fw_runtime {
        const struct iwl_fw_runtime_ops *ops;
        void *ops_ctx;
 
+       const struct iwl_dump_sanitize_ops *sanitize_ops;
+       void *sanitize_ctx;
+
        /* Paging */
        struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS];
        u16 num_of_paging_blk;
@@ -151,7 +154,7 @@ struct iwl_fw_runtime {
        struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
        u8 sar_chain_a_profile;
        u8 sar_chain_b_profile;
-       struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
+       struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES_REV3];
        u32 geo_rev;
        union iwl_ppag_table_cmd ppag_table;
        u32 ppag_ver;
@@ -161,6 +164,8 @@ struct iwl_fw_runtime {
 void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
                        const struct iwl_fw *fw,
                        const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
+                       const struct iwl_dump_sanitize_ops *sanitize_ops,
+                       void *sanitize_ctx,
                        struct dentry *dbgfs_dir);
 
 static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)
index 45d0b36..d552c65 100644 (file)
@@ -2,7 +2,8 @@
 /*
  * Copyright(c) 2021 Intel Corporation
  */
-
+#ifndef __iwl_fw_uefi__
+#define __iwl_fw_uefi__
 
 #define IWL_UEFI_OEM_PNVM_NAME         L"UefiCnvWlanOemSignedPnvm"
 #define IWL_UEFI_REDUCED_POWER_NAME    L"UefiCnvWlanReducedPower"
@@ -40,3 +41,5 @@ void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len)
        return ERR_PTR(-EOPNOTSUPP);
 }
 #endif /* CONFIG_EFI */
+
+#endif /* __iwl_fw_uefi__ */
index 7eb534d..665167a 100644 (file)
@@ -95,7 +95,6 @@ enum iwl_nvm_type {
 #define        ANT_AC          (ANT_A | ANT_C)
 #define ANT_BC         (ANT_B | ANT_C)
 #define ANT_ABC                (ANT_A | ANT_B | ANT_C)
-#define MAX_ANT_NUM 3
 
 
 static inline u8 num_of_ant(u8 mask)
@@ -420,6 +419,7 @@ struct iwl_cfg {
 #define IWL_CFG_MAC_TYPE_SOF           0x43
 #define IWL_CFG_MAC_TYPE_MA            0x44
 #define IWL_CFG_MAC_TYPE_BZ            0x46
+#define IWL_CFG_MAC_TYPE_GL            0x47
 
 #define IWL_CFG_RF_TYPE_TH             0x105
 #define IWL_CFG_RF_TYPE_TH1            0x108
@@ -511,6 +511,10 @@ extern const char iwl_ax210_killer_1675w_name[];
 extern const char iwl_ax210_killer_1675x_name[];
 extern const char iwl9560_killer_1550i_160_name[];
 extern const char iwl9560_killer_1550s_160_name[];
+extern const char iwl_ax211_killer_1675s_name[];
+extern const char iwl_ax211_killer_1675i_name[];
+extern const char iwl_ax411_killer_1690s_name[];
+extern const char iwl_ax411_killer_1690i_name[];
 extern const char iwl_ax211_name[];
 extern const char iwl_ax221_name[];
 extern const char iwl_ax231_name[];
@@ -628,6 +632,8 @@ extern const struct iwl_cfg iwl_cfg_bz_a0_hr_b0;
 extern const struct iwl_cfg iwl_cfg_bz_a0_gf_a0;
 extern const struct iwl_cfg iwl_cfg_bz_a0_gf4_a0;
 extern const struct iwl_cfg iwl_cfg_bz_a0_mr_a0;
+extern const struct iwl_cfg iwl_cfg_bz_a0_fm_a0;
+extern const struct iwl_cfg iwl_cfg_gl_a0_fm_a0;
 #endif /* CONFIG_IWLMVM */
 
 #endif /* __IWL_CONFIG_H__ */
index e1fec23..5adf485 100644 (file)
@@ -109,12 +109,12 @@ struct iwl_prph_scratch_pnvm_cfg {
  * struct iwl_prph_scratch_hwm_cfg - hwm config
  * @hwm_base_addr: hwm start address
  * @hwm_size: hwm size in DWs
- * @reserved: reserved
+ * @debug_token_config: debug preset
  */
 struct iwl_prph_scratch_hwm_cfg {
        __le64 hwm_base_addr;
        __le32 hwm_size;
-       __le32 reserved;
+       __le32 debug_token_config;
 } __packed; /* PERIPH_SCRATCH_HWM_CFG_S */
 
 /*
index cf79640..ff79a2e 100644 (file)
@@ -34,6 +34,7 @@
 #define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
 #define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
 #define CSR_GP_CNTRL            (CSR_BASE+0x024)
+#define CSR_FUNC_SCRATCH        (CSR_BASE+0x02c) /* Scratch register - used for FW dbg */
 
 /* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
 #define CSR_INT_PERIODIC_REG   (CSR_BASE+0x005)
 #define CSR_DBG_HPET_MEM_REG           (CSR_BASE+0x240)
 #define CSR_DBG_LINK_PWR_MGMT_REG      (CSR_BASE+0x250)
 
+/*
+ * Scratch register initial configuration - this is set on init, and read
+ * during a error FW error.
+ */
+#define CSR_FUNC_SCRATCH_INIT_VALUE            (0x01010101)
+
 /* Bits for CSR_HW_IF_CONFIG_REG */
 #define CSR_HW_IF_CONFIG_REG_MSK_MAC_DASH      (0x00000003)
 #define CSR_HW_IF_CONFIG_REG_MSK_MAC_STEP      (0x0000000C)
@@ -598,6 +605,7 @@ enum msix_hw_int_causes {
        MSIX_HW_INT_CAUSES_REG_WAKEUP           = BIT(1),
        MSIX_HW_INT_CAUSES_REG_IML              = BIT(1),
        MSIX_HW_INT_CAUSES_REG_RESET_DONE       = BIT(2),
+       MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ        = BIT(5),
        MSIX_HW_INT_CAUSES_REG_CT_KILL          = BIT(6),
        MSIX_HW_INT_CAUSES_REG_RF_KILL          = BIT(7),
        MSIX_HW_INT_CAUSES_REG_PERIODIC         = BIT(8),
index 125479b..7ab98b4 100644 (file)
@@ -16,6 +16,7 @@
  * @IWL_DBG_TLV_TYPE_HCMD: host command TLV
  * @IWL_DBG_TLV_TYPE_REGION: region TLV
  * @IWL_DBG_TLV_TYPE_TRIGGER: trigger TLV
+ * @IWL_DBG_TLV_TYPE_CONF_SET: conf set TLV
  * @IWL_DBG_TLV_TYPE_NUM: number of debug TLVs
  */
 enum iwl_dbg_tlv_type {
@@ -25,6 +26,7 @@ enum iwl_dbg_tlv_type {
        IWL_DBG_TLV_TYPE_HCMD,
        IWL_DBG_TLV_TYPE_REGION,
        IWL_DBG_TLV_TYPE_TRIGGER,
+       IWL_DBG_TLV_TYPE_CONF_SET,
        IWL_DBG_TLV_TYPE_NUM,
 };
 
@@ -59,6 +61,7 @@ dbg_ver_table[IWL_DBG_TLV_TYPE_NUM] = {
        [IWL_DBG_TLV_TYPE_HCMD]         = {.min_ver = 1, .max_ver = 1,},
        [IWL_DBG_TLV_TYPE_REGION]       = {.min_ver = 1, .max_ver = 2,},
        [IWL_DBG_TLV_TYPE_TRIGGER]      = {.min_ver = 1, .max_ver = 1,},
+       [IWL_DBG_TLV_TYPE_CONF_SET]     = {.min_ver = 1, .max_ver = 1,},
 };
 
 static int iwl_dbg_tlv_add(const struct iwl_ucode_tlv *tlv,
@@ -260,6 +263,30 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans,
        return ret;
 }
 
+static int iwl_dbg_tlv_config_set(struct iwl_trans *trans,
+                                 const struct iwl_ucode_tlv *tlv)
+{
+       struct iwl_fw_ini_conf_set_tlv *conf_set = (void *)tlv->data;
+       u32 tp = le32_to_cpu(conf_set->time_point);
+       u32 type = le32_to_cpu(conf_set->set_type);
+
+       if (tp <= IWL_FW_INI_TIME_POINT_INVALID ||
+           tp >= IWL_FW_INI_TIME_POINT_NUM) {
+               IWL_DEBUG_FW(trans,
+                            "WRT: Invalid time point %u for config set TLV\n", tp);
+               return -EINVAL;
+       }
+
+       if (type <= IWL_FW_INI_CONFIG_SET_TYPE_INVALID ||
+           type >= IWL_FW_INI_CONFIG_SET_TYPE_MAX_NUM) {
+               IWL_DEBUG_FW(trans,
+                            "WRT: Invalid config set type %u for config set TLV\n", type);
+               return -EINVAL;
+       }
+
+       return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].config_list);
+}
+
 static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,
                              const struct iwl_ucode_tlv *tlv) = {
        [IWL_DBG_TLV_TYPE_DEBUG_INFO]   = iwl_dbg_tlv_alloc_debug_info,
@@ -267,6 +294,7 @@ static int (*dbg_tlv_alloc[])(struct iwl_trans *trans,
        [IWL_DBG_TLV_TYPE_HCMD]         = iwl_dbg_tlv_alloc_hcmd,
        [IWL_DBG_TLV_TYPE_REGION]       = iwl_dbg_tlv_alloc_region,
        [IWL_DBG_TLV_TYPE_TRIGGER]      = iwl_dbg_tlv_alloc_trigger,
+       [IWL_DBG_TLV_TYPE_CONF_SET]     = iwl_dbg_tlv_config_set,
 };
 
 void iwl_dbg_tlv_alloc(struct iwl_trans *trans, const struct iwl_ucode_tlv *tlv,
@@ -399,6 +427,13 @@ void iwl_dbg_tlv_free(struct iwl_trans *trans)
                        list_del(&tlv_node->list);
                        kfree(tlv_node);
                }
+
+               list_for_each_entry_safe(tlv_node, tlv_node_tmp,
+                                        &tp->config_list, list) {
+                       list_del(&tlv_node->list);
+                       kfree(tlv_node);
+               }
+
        }
 
        for (i = 0; i < ARRAY_SIZE(trans->dbg.fw_mon_ini); i++)
@@ -466,6 +501,7 @@ void iwl_dbg_tlv_init(struct iwl_trans *trans)
                INIT_LIST_HEAD(&tp->trig_list);
                INIT_LIST_HEAD(&tp->hcmd_list);
                INIT_LIST_HEAD(&tp->active_trig_list);
+               INIT_LIST_HEAD(&tp->config_list);
        }
 }
 
@@ -649,6 +685,10 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)
 {
        int ret, i;
 
+       if (fw_has_capa(&fwrt->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))
+               return;
+
        for (i = 0; i < IWL_FW_INI_ALLOCATION_NUM; i++) {
                ret = iwl_dbg_tlv_apply_buffer(fwrt, i);
                if (ret)
@@ -658,6 +698,87 @@ static void iwl_dbg_tlv_apply_buffers(struct iwl_fw_runtime *fwrt)
        }
 }
 
+static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt,
+                                  enum iwl_fw_ini_allocation_id alloc_id,
+                                  struct iwl_dram_info *dram_info)
+{
+       struct iwl_fw_mon *fw_mon;
+       u32 remain_frags, num_frags;
+       int j, fw_mon_idx = 0;
+       struct iwl_buf_alloc_cmd *data;
+
+       if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) !=
+                       IWL_FW_INI_LOCATION_DRAM_PATH) {
+               IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id);
+               return -1;
+       }
+
+       fw_mon = &fwrt->trans->dbg.fw_mon_ini[alloc_id];
+
+       /* the first fragment of DBGC1 is given to the FW via register
+        * or context info
+        */
+       if (alloc_id == IWL_FW_INI_ALLOCATION_ID_DBGC1)
+               fw_mon_idx++;
+
+       remain_frags = fw_mon->num_frags - fw_mon_idx;
+       if (!remain_frags)
+               return -1;
+
+       num_frags = min_t(u32, remain_frags, BUF_ALLOC_MAX_NUM_FRAGS);
+       data = &dram_info->dram_frags[alloc_id - 1];
+       data->alloc_id = cpu_to_le32(alloc_id);
+       data->num_frags = cpu_to_le32(num_frags);
+       data->buf_location = cpu_to_le32(IWL_FW_INI_LOCATION_DRAM_PATH);
+
+       IWL_DEBUG_FW(fwrt, "WRT: DRAM buffer details alloc_id=%u, num_frags=%u\n",
+                    cpu_to_le32(alloc_id), cpu_to_le32(num_frags));
+
+       for (j = 0; j < num_frags; j++) {
+               struct iwl_buf_alloc_frag *frag = &data->frags[j];
+               struct iwl_dram_data *fw_mon_frag = &fw_mon->frags[fw_mon_idx++];
+
+               frag->addr = cpu_to_le64(fw_mon_frag->physical);
+               frag->size = cpu_to_le32(fw_mon_frag->size);
+               IWL_DEBUG_FW(fwrt, "WRT: DRAM fragment details\n");
+               IWL_DEBUG_FW(fwrt, "frag=%u, addr=0x%016llx, size=0x%x)\n",
+                            j, cpu_to_le64(fw_mon_frag->physical),
+                            cpu_to_le32(fw_mon_frag->size));
+       }
+       return 0;
+}
+
+static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt)
+{
+       int ret, i, dram_alloc = 0;
+       struct iwl_dram_info dram_info;
+       struct iwl_dram_data *frags =
+               &fwrt->trans->dbg.fw_mon_ini[IWL_FW_INI_ALLOCATION_ID_DBGC1].frags[0];
+
+       if (!fw_has_capa(&fwrt->fw->ucode_capa,
+                        IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))
+               return;
+
+       dram_info.first_word = cpu_to_le32(DRAM_INFO_FIRST_MAGIC_WORD);
+       dram_info.second_word = cpu_to_le32(DRAM_INFO_SECOND_MAGIC_WORD);
+
+       for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1;
+            i <= IWL_FW_INI_ALLOCATION_ID_DBGC3; i++) {
+               ret = iwl_dbg_tlv_update_dram(fwrt, i, &dram_info);
+               if (!ret)
+                       dram_alloc++;
+               else
+                       IWL_WARN(fwrt,
+                                "WRT: Failed to set DRAM buffer for alloc id %d, ret=%d\n",
+                                i, ret);
+       }
+       if (dram_alloc) {
+               memcpy(frags->block, &dram_info, sizeof(dram_info));
+               IWL_DEBUG_FW(fwrt, "block data after  %016x\n",
+                            *((int *)fwrt->trans->dbg.fw_mon_ini[1].frags[0].block));
+       }
+}
+
 static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
                                   struct list_head *hcmd_list)
 {
@@ -677,6 +798,97 @@ static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
        }
 }
 
+static void iwl_dbg_tlv_apply_config(struct iwl_fw_runtime *fwrt,
+                                    struct list_head *config_list)
+{
+       struct iwl_dbg_tlv_node *node;
+
+       list_for_each_entry(node, config_list, list) {
+               struct iwl_fw_ini_conf_set_tlv *config_list = (void *)node->tlv.data;
+               u32 count, address, value;
+               u32 len = (le32_to_cpu(node->tlv.length) - sizeof(*config_list)) / 8;
+               u32 type = le32_to_cpu(config_list->set_type);
+               u32 offset = le32_to_cpu(config_list->addr_offset);
+
+               switch (type) {
+               case IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_PERIPHERY_MAC: {
+                       if (!iwl_trans_grab_nic_access(fwrt->trans)) {
+                               IWL_DEBUG_FW(fwrt, "WRT: failed to get nic access\n");
+                               IWL_DEBUG_FW(fwrt, "WRT: skipping MAC PERIPHERY config\n");
+                               continue;
+                       }
+                       IWL_DEBUG_FW(fwrt, "WRT:  MAC PERIPHERY config len: len %u\n", len);
+                       for (count = 0; count < len; count++) {
+                               address = le32_to_cpu(config_list->addr_val[count].address);
+                               value = le32_to_cpu(config_list->addr_val[count].value);
+                               iwl_trans_write_prph(fwrt->trans, address + offset, value);
+                       }
+                       iwl_trans_release_nic_access(fwrt->trans);
+               break;
+               }
+               case IWL_FW_INI_CONFIG_SET_TYPE_DEVICE_MEMORY: {
+                       for (count = 0; count < len; count++) {
+                               address = le32_to_cpu(config_list->addr_val[count].address);
+                               value = le32_to_cpu(config_list->addr_val[count].value);
+                               iwl_trans_write_mem32(fwrt->trans, address + offset, value);
+                               IWL_DEBUG_FW(fwrt, "WRT: DEV_MEM: count %u, add: %u val: %u\n",
+                                            count, address, value);
+                       }
+               break;
+               }
+               case IWL_FW_INI_CONFIG_SET_TYPE_CSR: {
+                       for (count = 0; count < len; count++) {
+                               address = le32_to_cpu(config_list->addr_val[count].address);
+                               value = le32_to_cpu(config_list->addr_val[count].value);
+                               iwl_write32(fwrt->trans, address + offset, value);
+                               IWL_DEBUG_FW(fwrt, "WRT: CSR: count %u, add: %u val: %u\n",
+                                            count, address, value);
+                       }
+               break;
+               }
+               case IWL_FW_INI_CONFIG_SET_TYPE_DBGC_DRAM_ADDR: {
+                       struct iwl_dbgc1_info dram_info = {};
+                       struct iwl_dram_data *frags = &fwrt->trans->dbg.fw_mon_ini[1].frags[0];
+                       __le64 dram_base_addr = cpu_to_le64(frags->physical);
+                       __le32 dram_size = cpu_to_le32(frags->size);
+                       u64  dram_addr = le64_to_cpu(dram_base_addr);
+                       u32 ret;
+
+                       IWL_DEBUG_FW(fwrt, "WRT: dram_base_addr 0x%016llx, dram_size 0x%x\n",
+                                    dram_base_addr, dram_size);
+                       IWL_DEBUG_FW(fwrt, "WRT: config_list->addr_offset: %u\n",
+                                    le32_to_cpu(config_list->addr_offset));
+                       for (count = 0; count < len; count++) {
+                               address = le32_to_cpu(config_list->addr_val[count].address);
+                               dram_info.dbgc1_add_lsb =
+                                       cpu_to_le32((dram_addr & 0x00000000FFFFFFFFULL) + 0x400);
+                               dram_info.dbgc1_add_msb =
+                                       cpu_to_le32((dram_addr & 0xFFFFFFFF00000000ULL) >> 32);
+                               dram_info.dbgc1_size = cpu_to_le32(le32_to_cpu(dram_size) - 0x400);
+                               ret = iwl_trans_write_mem(fwrt->trans,
+                                                         address + offset, &dram_info, 4);
+                               if (ret) {
+                                       IWL_ERR(fwrt, "Failed to write dram_info to HW_SMEM\n");
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               case IWL_FW_INI_CONFIG_SET_TYPE_PERIPH_SCRATCH_HWM: {
+                       u32 debug_token_config =
+                               le32_to_cpu(config_list->addr_val[0].value);
+
+                       IWL_DEBUG_FW(fwrt, "WRT: Setting HWM debug token config: %u\n",
+                                    debug_token_config);
+                       fwrt->trans->dbg.ucode_preset = debug_token_config;
+                       break;
+               }
+               default:
+                       break;
+               }
+       }
+}
+
 static void iwl_dbg_tlv_periodic_trig_handler(struct timer_list *t)
 {
        struct iwl_dbg_tlv_timer_node *timer_node =
@@ -996,8 +1208,10 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
                        &fwrt->trans->dbg.fw_mon_cfg[i];
                u32 dest = le32_to_cpu(fw_mon_cfg->buf_location);
 
-               if (dest == IWL_FW_INI_LOCATION_INVALID)
+               if (dest == IWL_FW_INI_LOCATION_INVALID) {
+                       failed_alloc |= BIT(i);
                        continue;
+               }
 
                if (*ini_dest == IWL_FW_INI_LOCATION_INVALID)
                        *ini_dest = dest;
@@ -1024,8 +1238,10 @@ static void iwl_dbg_tlv_init_cfg(struct iwl_fw_runtime *fwrt)
                        &fwrt->trans->dbg.active_regions[i];
                u32 reg_type;
 
-               if (!*active_reg)
+               if (!*active_reg) {
+                       fwrt->trans->dbg.unsupported_region_msk |= BIT(i);
                        continue;
+               }
 
                reg = (void *)(*active_reg)->data;
                reg_type = le32_to_cpu(reg->type);
@@ -1051,7 +1267,7 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
                             union iwl_dbg_tlv_tp_data *tp_data,
                             bool sync)
 {
-       struct list_head *hcmd_list, *trig_list;
+       struct list_head *hcmd_list, *trig_list, *conf_list;
 
        if (!iwl_trans_dbg_ini_valid(fwrt->trans) ||
            tp_id == IWL_FW_INI_TIME_POINT_INVALID ||
@@ -1060,15 +1276,19 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
 
        hcmd_list = &fwrt->trans->dbg.time_point[tp_id].hcmd_list;
        trig_list = &fwrt->trans->dbg.time_point[tp_id].active_trig_list;
+       conf_list = &fwrt->trans->dbg.time_point[tp_id].config_list;
 
        switch (tp_id) {
        case IWL_FW_INI_TIME_POINT_EARLY:
                iwl_dbg_tlv_init_cfg(fwrt);
+               iwl_dbg_tlv_apply_config(fwrt, conf_list);
+               iwl_dbg_tlv_update_drams(fwrt);
                iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
                break;
        case IWL_FW_INI_TIME_POINT_AFTER_ALIVE:
                iwl_dbg_tlv_apply_buffers(fwrt);
                iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
+               iwl_dbg_tlv_apply_config(fwrt, conf_list);
                iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
                break;
        case IWL_FW_INI_TIME_POINT_PERIODIC:
@@ -1079,11 +1299,13 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,
        case IWL_FW_INI_TIME_POINT_MISSED_BEACONS:
        case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION:
                iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
+               iwl_dbg_tlv_apply_config(fwrt, conf_list);
                iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data,
                                       iwl_dbg_tlv_check_fw_pkt);
                break;
        default:
                iwl_dbg_tlv_send_hcmds(fwrt, hcmd_list);
+               iwl_dbg_tlv_apply_config(fwrt, conf_list);
                iwl_dbg_tlv_tp_trigger(fwrt, sync, trig_list, tp_data, NULL);
                break;
        }
index c12b1fd..7928770 100644 (file)
@@ -33,11 +33,13 @@ union iwl_dbg_tlv_tp_data {
  * @trig_list: list of triggers
  * @active_trig_list: list of active triggers
  * @hcmd_list: list of host commands
+ * @config_list: list of configuration
  */
 struct iwl_dbg_tlv_time_point_data {
        struct list_head trig_list;
        struct list_head active_trig_list;
        struct list_head hcmd_list;
+       struct list_head config_list;
 };
 
 struct iwl_trans;
index f6ca2fc..ae4c2a3 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2005-2011 Intel Corporation
+ * Copyright (C) 2005-2011, 2021 Intel Corporation
  */
 #include <linux/device.h>
 #include <linux/interrupt.h>
@@ -31,21 +31,31 @@ IWL_EXPORT_SYMBOL(__iwl_info);
 __iwl_fn(crit)
 IWL_EXPORT_SYMBOL(__iwl_crit);
 
-void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
-               const char *fmt, ...)
+void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...)
 {
        struct va_format vaf = {
                .fmt = fmt,
        };
-       va_list args;
+       va_list args, args2;
 
        va_start(args, fmt);
-       vaf.va = &args;
-       if (!trace_only) {
-               if (rfkill_prefix)
+       switch (mode) {
+       case IWL_ERR_MODE_RATELIMIT:
+               if (net_ratelimit())
+                       break;
+               fallthrough;
+       case IWL_ERR_MODE_REGULAR:
+       case IWL_ERR_MODE_RFKILL:
+               va_copy(args2, args);
+               vaf.va = &args2;
+               if (mode == IWL_ERR_MODE_RFKILL)
                        dev_err(dev, "(RFKILL) %pV", &vaf);
                else
                        dev_err(dev, "%pV", &vaf);
+               va_end(args2);
+               break;
+       default:
+               break;
        }
        trace_iwlwifi_err(&vaf);
        va_end(args);
index 528eba4..1b9f16a 100644 (file)
@@ -2,14 +2,9 @@
 /******************************************************************************
  *
  * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2018 - 2020 Intel Corporation
+ * Copyright(c) 2018 - 2021 Intel Corporation
  *
  * Portions of this file are derived from the ipw3945 project.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #ifndef __iwl_debug_h__
@@ -27,9 +22,16 @@ static inline bool iwl_have_debug_level(u32 level)
 #endif
 }
 
+enum iwl_err_mode {
+       IWL_ERR_MODE_REGULAR,
+       IWL_ERR_MODE_RFKILL,
+       IWL_ERR_MODE_TRACE_ONLY,
+       IWL_ERR_MODE_RATELIMIT,
+};
+
 struct device;
-void __iwl_err(struct device *dev, bool rfkill_prefix, bool only_trace,
-               const char *fmt, ...) __printf(4, 5);
+void __iwl_err(struct device *dev, enum iwl_err_mode mode, const char *fmt, ...)
+       __printf(3, 4);
 void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3);
 void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3);
 void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3);
@@ -38,13 +40,17 @@ void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3);
 #define CHECK_FOR_NEWLINE(f) BUILD_BUG_ON(f[sizeof(f) - 2] != '\n')
 
 /* No matter what is m (priv, bus, trans), this will work */
-#define IWL_ERR_DEV(d, f, a...)                                                \
+#define __IWL_ERR_DEV(d, mode, f, a...)                                        \
        do {                                                            \
                CHECK_FOR_NEWLINE(f);                                   \
-               __iwl_err((d), false, false, f, ## a);                  \
+               __iwl_err((d), mode, f, ## a);                          \
        } while (0)
+#define IWL_ERR_DEV(d, f, a...)                                                \
+       __IWL_ERR_DEV(d, IWL_ERR_MODE_REGULAR, f, ## a)
 #define IWL_ERR(m, f, a...)                                            \
        IWL_ERR_DEV((m)->dev, f, ## a)
+#define IWL_ERR_LIMIT(m, f, a...)                                      \
+       __IWL_ERR_DEV((m)->dev, IWL_ERR_MODE_RATELIMIT, f, ## a)
 #define IWL_WARN(m, f, a...)                                           \
        do {                                                            \
                CHECK_FOR_NEWLINE(f);                                   \
index 1bc6ecc..347fd95 100644 (file)
@@ -4,11 +4,6 @@
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2015        Intel Deutschland GmbH
  * Copyright(c) 2018 - 2019 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE_DATA) || defined(TRACE_HEADER_MULTI_READ)
index a570192..0af9d83 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2016-2017 Intel Deutschland GmbH
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE_IO) || defined(TRACE_HEADER_MULTI_READ)
index 72ca882..46ed723 100644 (file)
@@ -5,11 +5,6 @@
  * Copyright(c) 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  * Copyright(c) 2018        Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE_IWLWIFI) || defined(TRACE_HEADER_MULTI_READ)
index d0467da..7dd7001 100644 (file)
@@ -2,11 +2,6 @@
 /******************************************************************************
  *
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE_MSG) || defined(TRACE_HEADER_MULTI_READ)
index 2228fae..3ec0205 100644 (file)
@@ -2,11 +2,6 @@
 /******************************************************************************
  *
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #if !defined(__IWLWIFI_DEVICE_TRACE_UCODE) || defined(TRACE_HEADER_MULTI_READ)
index b5037db..999b7c6 100644 (file)
@@ -3,11 +3,6 @@
  *
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
  * Copyright (C) 2018 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #include <linux/module.h>
index fc8bc21..1455b57 100644 (file)
@@ -4,11 +4,6 @@
  * Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
  * Copyright(C) 2016        Intel Deutschland GmbH
  * Copyright(c) 2018        Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #ifndef __IWLWIFI_DEVICE_TRACE
index 77124b8..36196e0 100644 (file)
@@ -31,7 +31,6 @@
 
 #define DRV_DESCRIPTION        "Intel(R) Wireless WiFi driver for Linux"
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -550,6 +549,43 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
        return 0;
 }
 
+static void iwl_drv_set_dump_exclude(struct iwl_drv *drv,
+                                    enum iwl_ucode_tlv_type tlv_type,
+                                    const void *tlv_data, u32 tlv_len)
+{
+       const struct iwl_fw_dump_exclude *fw = tlv_data;
+       struct iwl_dump_exclude *excl;
+
+       if (tlv_len < sizeof(*fw))
+               return;
+
+       if (tlv_type == IWL_UCODE_TLV_SEC_TABLE_ADDR) {
+               excl = &drv->fw.dump_excl[0];
+
+               /* second time we find this, it's for WoWLAN */
+               if (excl->addr)
+                       excl = &drv->fw.dump_excl_wowlan[0];
+       } else if (fw_has_capa(&drv->fw.ucode_capa,
+                              IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG)) {
+               /* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is regular image */
+               excl = &drv->fw.dump_excl[0];
+       } else {
+               /* IWL_UCODE_TLV_D3_KEK_KCK_ADDR is WoWLAN image */
+               excl = &drv->fw.dump_excl_wowlan[0];
+       }
+
+       if (excl->addr)
+               excl++;
+
+       if (excl->addr) {
+               IWL_DEBUG_FW_INFO(drv, "found too many excludes in fw file\n");
+               return;
+       }
+
+       excl->addr = le32_to_cpu(fw->addr) & ~FW_ADDR_CACHE_CONTROL;
+       excl->size = le32_to_cpu(fw->size);
+}
+
 static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                                const struct firmware *ucode_raw,
                                struct iwl_firmware_pieces *pieces,
@@ -1133,6 +1169,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                case IWL_UCODE_TLV_TYPE_HCMD:
                case IWL_UCODE_TLV_TYPE_REGIONS:
                case IWL_UCODE_TLV_TYPE_TRIGGERS:
+               case IWL_UCODE_TLV_TYPE_CONF_SET:
                        if (iwlwifi_mod_params.enable_ini)
                                iwl_dbg_tlv_alloc(drv->trans, tlv, false);
                        break;
@@ -1166,6 +1203,11 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                                return -ENOMEM;
                        drv->fw.phy_integration_ver_len = tlv_len;
                        break;
+               case IWL_UCODE_TLV_SEC_TABLE_ADDR:
+               case IWL_UCODE_TLV_D3_KEK_KCK_ADDR:
+                       iwl_drv_set_dump_exclude(drv, tlv_type,
+                                                tlv_data, tlv_len);
+                       break;
                default:
                        IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
                        break;
index b6442df..2e2d60a 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2005-2014, 2020 Intel Corporation
+ * Copyright (C) 2005-2014, 2020-2021 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  */
 #ifndef __iwl_drv_h__
@@ -9,7 +9,6 @@
 
 /* for all modules */
 #define DRV_NAME        "iwlwifi"
-#define DRV_AUTHOR     "Intel Corporation <linuxwifi@intel.com>"
 
 /* radio config bits (actual values from NVM definition) */
 #define NVM_RF_CFG_DASH_MSK(x)   (x & 0x3)         /* bits 0-1   */
index dbab2f1..b9e86bf 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2005-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2019, 2021 Intel Corporation
  */
 #include <linux/types.h>
 #include <linux/slab.h>
@@ -139,7 +139,7 @@ static int iwl_init_otp_access(struct iwl_trans *trans)
 {
        int ret;
 
-       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       ret = iwl_finish_nic_init(trans);
        if (ret)
                return ret;
 
index 2517c4a..46917b4 100644 (file)
@@ -398,9 +398,50 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf)
        return 0;
 }
 
-int iwl_finish_nic_init(struct iwl_trans *trans,
-                       const struct iwl_cfg_trans_params *cfg_trans)
+#define IWL_HOST_MON_BLOCK_PEMON       0x00
+#define IWL_HOST_MON_BLOCK_HIPM                0x22
+
+#define IWL_HOST_MON_BLOCK_PEMON_VEC0  0x00
+#define IWL_HOST_MON_BLOCK_PEMON_VEC1  0x01
+#define IWL_HOST_MON_BLOCK_PEMON_WFPM  0x06
+
+static void iwl_dump_host_monitor_block(struct iwl_trans *trans,
+                                       u32 block, u32 vec, u32 iter)
+{
+       int i;
+
+       IWL_ERR(trans, "Host monitor block 0x%x vector 0x%x\n", block, vec);
+       iwl_write32(trans, CSR_MONITOR_CFG_REG, (block << 8) | vec);
+       for (i = 0; i < iter; i++)
+               IWL_ERR(trans, "    value [iter %d]: 0x%08x\n",
+                       i, iwl_read32(trans, CSR_MONITOR_STATUS_REG));
+}
+
+static void iwl_dump_host_monitor(struct iwl_trans *trans)
 {
+       switch (trans->trans_cfg->device_family) {
+       case IWL_DEVICE_FAMILY_22000:
+       case IWL_DEVICE_FAMILY_AX210:
+               IWL_ERR(trans, "CSR_RESET = 0x%x\n",
+                       iwl_read32(trans, CSR_RESET));
+               iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
+                                           IWL_HOST_MON_BLOCK_PEMON_VEC0, 15);
+               iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
+                                           IWL_HOST_MON_BLOCK_PEMON_VEC1, 15);
+               iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_PEMON,
+                                           IWL_HOST_MON_BLOCK_PEMON_WFPM, 15);
+               iwl_dump_host_monitor_block(trans, IWL_HOST_MON_BLOCK_HIPM,
+                                           IWL_HOST_MON_BLOCK_PEMON_VEC0, 1);
+               break;
+       default:
+               /* not supported yet */
+               return;
+       }
+}
+
+int iwl_finish_nic_init(struct iwl_trans *trans)
+{
+       const struct iwl_cfg_trans_params *cfg_trans = trans->trans_cfg;
        u32 poll_ready;
        int err;
 
@@ -433,9 +474,12 @@ int iwl_finish_nic_init(struct iwl_trans *trans,
         * and accesses to uCode SRAM.
         */
        err = iwl_poll_bit(trans, CSR_GP_CNTRL, poll_ready, poll_ready, 25000);
-       if (err < 0)
+       if (err < 0) {
                IWL_DEBUG_INFO(trans, "Failed to wake NIC\n");
 
+               iwl_dump_host_monitor(trans);
+       }
+
        if (cfg_trans->bisr_workaround) {
                /* ensure BISR shift has finished */
                udelay(200);
index 3c21c0e..37b3bd6 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
  */
 #ifndef __iwl_io_h__
 #define __iwl_io_h__
@@ -52,8 +52,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
 void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
 void iwl_force_nmi(struct iwl_trans *trans);
 
-int iwl_finish_nic_init(struct iwl_trans *trans,
-                       const struct iwl_cfg_trans_params *cfg_trans);
+int iwl_finish_nic_init(struct iwl_trans *trans);
 
 /* Error handling */
 int iwl_dump_fh(struct iwl_trans *trans, char **buf);
index 475f951..f470f9a 100644 (file)
@@ -534,6 +534,17 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans,
                cpu_to_le16(IEEE80211_VHT_EXT_NSS_BW_CAPABLE);
 }
 
+static const u8 iwl_vendor_caps[] = {
+       0xdd,                   /* vendor element */
+       0x06,                   /* length */
+       0x00, 0x17, 0x35,       /* Intel OUI */
+       0x08,                   /* type (Intel Capabilities) */
+       /* followed by 16 bits of capabilities */
+#define IWL_VENDOR_CAP_IMPROVED_BF_FDBK_HE     BIT(0)
+       IWL_VENDOR_CAP_IMPROVED_BF_FDBK_HE,
+       0x00
+};
+
 static const struct ieee80211_sband_iftype_data iwl_he_capa[] = {
        {
                .types_mask = BIT(NL80211_IFTYPE_STATION),
@@ -781,6 +792,12 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans,
        if (fw_has_capa(&fw->ucode_capa, IWL_UCODE_TLV_CAPA_BROADCAST_TWT))
                iftype_data->he_cap.he_cap_elem.mac_cap_info[2] |=
                        IEEE80211_HE_MAC_CAP2_BCAST_TWT;
+
+       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+           !is_ap) {
+               iftype_data->vendor_elems.data = iwl_vendor_caps;
+               iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps);
+       }
 }
 
 static void iwl_init_he_hw_capab(struct iwl_trans *trans,
index d0a7d58..a84ab02 100644 (file)
 #define RADIO_REG_SYS_MANUAL_DFT_0     0xAD4078
 #define RFIC_REG_RD                    0xAD0470
 #define WFPM_CTRL_REG                  0xA03030
+#define WFPM_CTRL_REG_GEN2             0xd03030
+#define WFPM_OTP_CFG1_ADDR             0x00a03098
+#define WFPM_OTP_CFG1_ADDR_GEN2                0x00d03098
+#define WFPM_OTP_CFG1_IS_JACKET_BIT    BIT(4)
+#define WFPM_OTP_CFG1_IS_CDB_BIT       BIT(5)
+
 #define WFPM_GP2                       0xA030B4
 
 /* DBGI SRAM Register details */
@@ -399,10 +405,40 @@ enum {
        LMPM_PAGE_PASS_NOTIF_POS = BIT(20),
 };
 
+/*
+ * CRF ID register
+ *
+ * type: bits 0-11
+ * reserved: bits 12-18
+ * slave_exist: bit 19
+ * dash: bits 20-23
+ * step: bits 24-26
+ * flavor: bits 27-31
+ */
+#define REG_CRF_ID_TYPE(val)           (((val) & 0x00000FFF) >> 0)
+#define REG_CRF_ID_SLAVE(val)          (((val) & 0x00080000) >> 19)
+#define REG_CRF_ID_DASH(val)           (((val) & 0x00F00000) >> 20)
+#define REG_CRF_ID_STEP(val)           (((val) & 0x07000000) >> 24)
+#define REG_CRF_ID_FLAVOR(val)         (((val) & 0xF8000000) >> 27)
+
 #define UREG_CHICK             (0xA05C00)
 #define UREG_CHICK_MSI_ENABLE  BIT(24)
 #define UREG_CHICK_MSIX_ENABLE BIT(25)
 
+#define SD_REG_VER             0xa29600
+#define SD_REG_VER_GEN2                0x00a2b800
+
+#define REG_CRF_ID_TYPE_JF_1                   0x201
+#define REG_CRF_ID_TYPE_JF_2                   0x202
+#define REG_CRF_ID_TYPE_HR_CDB                 0x503
+#define REG_CRF_ID_TYPE_HR_NONE_CDB            0x504
+#define REG_CRF_ID_TYPE_HR_NONE_CDB_1X1        0x501
+#define REG_CRF_ID_TYPE_HR_NONE_CDB_CCP        0x532
+#define REG_CRF_ID_TYPE_GF                     0x410
+#define REG_CRF_ID_TYPE_GF_TC                  0xF08
+#define REG_CRF_ID_TYPE_MR                     0x810
+#define REG_CRF_ID_TYPE_FM                     0x910
+
 #define HPM_DEBUG                      0xA03440
 #define PERSISTENCE_BIT                        BIT(12)
 #define PREG_WFPM_ACCESS               BIT(12)
index 8f0ff54..4ebb187 100644 (file)
@@ -363,6 +363,20 @@ struct iwl_hcmd_arr {
        { .arr = x, .size = ARRAY_SIZE(x) }
 
 /**
+ * struct iwl_dump_sanitize_ops - dump sanitization operations
+ * @frob_txf: Scrub the TX FIFO data
+ * @frob_hcmd: Scrub a host command, the %hcmd pointer is to the header
+ *     but that might be short or long (&struct iwl_cmd_header or
+ *     &struct iwl_cmd_header_wide)
+ * @frob_mem: Scrub memory data
+ */
+struct iwl_dump_sanitize_ops {
+       void (*frob_txf)(void *ctx, void *buf, size_t buflen);
+       void (*frob_hcmd)(void *ctx, void *hcmd, size_t buflen);
+       void (*frob_mem)(void *ctx, u32 mem_addr, void *mem, size_t buflen);
+};
+
+/**
  * struct iwl_trans_config - transport configuration
  *
  * @op_mode: pointer to the upper layer.
@@ -586,7 +600,9 @@ struct iwl_trans_ops {
                              u32 value);
 
        struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans,
-                                                u32 dump_mask);
+                                                u32 dump_mask,
+                                                const struct iwl_dump_sanitize_ops *sanitize_ops,
+                                                void *sanitize_ctx);
        void (*debugfs_cleanup)(struct iwl_trans *trans);
        void (*sync_nmi)(struct iwl_trans *trans);
        int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len);
@@ -723,8 +739,8 @@ struct iwl_self_init_dram {
  * @debug_info_tlv_list: list of debug info TLVs
  * @time_point: array of debug time points
  * @periodic_trig_list: periodic triggers list
- * @domains_bitmap: bitmap of active domains other than
- *     &IWL_FW_INI_DOMAIN_ALWAYS_ON
+ * @domains_bitmap: bitmap of active domains other than &IWL_FW_INI_DOMAIN_ALWAYS_ON
+ * @ucode_preset: preset based on ucode
  */
 struct iwl_trans_debug {
        u8 n_dest_reg;
@@ -758,6 +774,7 @@ struct iwl_trans_debug {
        struct list_head periodic_trig_list;
 
        u32 domains_bitmap;
+       u32 ucode_preset;
 };
 
 struct iwl_dma_ptr {
@@ -1086,11 +1103,14 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
 }
 
 static inline struct iwl_trans_dump_data *
-iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask)
+iwl_trans_dump_data(struct iwl_trans *trans, u32 dump_mask,
+                   const struct iwl_dump_sanitize_ops *sanitize_ops,
+                   void *sanitize_ctx)
 {
        if (!trans->ops->dump_data)
                return NULL;
-       return trans->ops->dump_data(trans, dump_mask);
+       return trans->ops->dump_data(trans, dump_mask,
+                                    sanitize_ops, sanitize_ctx);
 }
 
 static inline struct iwl_device_tx_cmd *
index d3013a5..a19f646 100644 (file)
@@ -1379,12 +1379,49 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 
 /* converted data from the different status responses */
 struct iwl_wowlan_status_data {
-       u16 pattern_number;
-       u16 qos_seq_ctr[8];
+       u64 replay_ctr;
+       u32 num_of_gtk_rekeys;
+       u32 received_beacons;
        u32 wakeup_reasons;
        u32 wake_packet_length;
        u32 wake_packet_bufsize;
-       const u8 *wake_packet;
+       u16 pattern_number;
+       u16 non_qos_seq_ctr;
+       u16 qos_seq_ctr[8];
+       u8 tid_tear_down;
+
+       struct {
+               /*
+                * We store both the TKIP and AES representations
+                * coming from the firmware because we decode the
+                * data from there before we iterate the keys and
+                * know which one we need.
+                */
+               struct {
+                       struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];
+               } tkip, aes;
+               /* including RX MIC key for TKIP */
+               u8 key[WOWLAN_KEY_MAX_SIZE];
+               u8 len;
+               u8 flags;
+       } gtk;
+
+       struct {
+               /* Same as above */
+               struct {
+                       struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];
+                       u64 tx_pn;
+               } tkip, aes;
+       } ptk;
+
+       struct {
+               u64 ipn;
+               u8 key[WOWLAN_KEY_MAX_SIZE];
+               u8 len;
+               u8 flags;
+       } igtk;
+
+       u8 wake_packet[];
 };
 
 static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,
@@ -1540,77 +1577,90 @@ static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc,
        seq->tkip.iv16 = le16_to_cpu(sc->iv16);
 }
 
-static void iwl_mvm_set_aes_rx_seq(struct iwl_mvm *mvm, struct aes_sc *scs,
-                                  struct ieee80211_sta *sta,
-                                  struct ieee80211_key_conf *key)
+static void iwl_mvm_set_key_rx_seq_tids(struct ieee80211_key_conf *key,
+                                       struct ieee80211_key_seq *seq)
 {
        int tid;
 
-       BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS);
+       for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+               ieee80211_set_key_rx_seq(key, tid, &seq[tid]);
+}
 
-       if (sta && iwl_mvm_has_new_rx_api(mvm)) {
-               struct iwl_mvm_sta *mvmsta;
-               struct iwl_mvm_key_pn *ptk_pn;
+static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm,
+                                      struct iwl_wowlan_status_data *status,
+                                      struct ieee80211_sta *sta,
+                                      struct ieee80211_key_conf *key)
+{
+       struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       struct iwl_mvm_key_pn *ptk_pn;
+       int tid;
 
-               mvmsta = iwl_mvm_sta_from_mac80211(sta);
+       iwl_mvm_set_key_rx_seq_tids(key, status->ptk.aes.seq);
 
-               rcu_read_lock();
-               ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
-               if (WARN_ON(!ptk_pn)) {
-                       rcu_read_unlock();
-                       return;
-               }
+       if (!iwl_mvm_has_new_rx_api(mvm))
+               return;
 
-               for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
-                       struct ieee80211_key_seq seq = {};
-                       int i;
 
-                       iwl_mvm_aes_sc_to_seq(&scs[tid], &seq);
-                       ieee80211_set_key_rx_seq(key, tid, &seq);
-                       for (i = 1; i < mvm->trans->num_rx_queues; i++)
-                               memcpy(ptk_pn->q[i].pn[tid],
-                                      seq.ccmp.pn, IEEE80211_CCMP_PN_LEN);
-               }
+       rcu_read_lock();
+       ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);
+       if (WARN_ON(!ptk_pn)) {
                rcu_read_unlock();
-       } else {
-               for (tid = 0; tid < IWL_NUM_RSC; tid++) {
-                       struct ieee80211_key_seq seq = {};
+               return;
+       }
 
-                       iwl_mvm_aes_sc_to_seq(&scs[tid], &seq);
-                       ieee80211_set_key_rx_seq(key, tid, &seq);
-               }
+       for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
+               int i;
+
+               for (i = 1; i < mvm->trans->num_rx_queues; i++)
+                       memcpy(ptk_pn->q[i].pn[tid],
+                              status->ptk.aes.seq[tid].ccmp.pn,
+                              IEEE80211_CCMP_PN_LEN);
        }
+       rcu_read_unlock();
 }
 
-static void iwl_mvm_set_tkip_rx_seq(struct tkip_sc *scs,
-                                   struct ieee80211_key_conf *key)
+static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,
+                                        union iwl_all_tsc_rsc *sc)
 {
-       int tid;
+       int i;
 
-       BUILD_BUG_ON(IWL_NUM_RSC != IEEE80211_NUM_TIDS);
+       BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT);
+       BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC);
 
-       for (tid = 0; tid < IWL_NUM_RSC; tid++) {
-               struct ieee80211_key_seq seq = {};
+       /* GTK RX counters */
+       for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
+               iwl_mvm_tkip_sc_to_seq(&sc->tkip.multicast_rsc[i],
+                                      &status->gtk.tkip.seq[i]);
+               iwl_mvm_aes_sc_to_seq(&sc->aes.multicast_rsc[i],
+                                     &status->gtk.aes.seq[i]);
+       }
 
-               iwl_mvm_tkip_sc_to_seq(&scs[tid], &seq);
-               ieee80211_set_key_rx_seq(key, tid, &seq);
+       /* PTK TX counter */
+       status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |
+                                ((u64)le32_to_cpu(sc->tkip.tsc.iv32) << 16);
+       status->ptk.aes.tx_pn = le64_to_cpu(sc->aes.tsc.pn);
+
+       /* PTK RX counters */
+       for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
+               iwl_mvm_tkip_sc_to_seq(&sc->tkip.unicast_rsc[i],
+                                      &status->ptk.tkip.seq[i]);
+               iwl_mvm_aes_sc_to_seq(&sc->aes.unicast_rsc[i],
+                                     &status->ptk.aes.seq[i]);
        }
 }
 
 static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,
                                   struct ieee80211_key_conf *key,
-                                  struct iwl_wowlan_status *status)
+                                  struct iwl_wowlan_status_data *status)
 {
-       union iwl_all_tsc_rsc *rsc = &status->gtk[0].rsc.all_tsc_rsc;
-
        switch (key->cipher) {
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
-               iwl_mvm_set_aes_rx_seq(mvm, rsc->aes.multicast_rsc, NULL, key);
+               iwl_mvm_set_key_rx_seq_tids(key, status->gtk.aes.seq);
                break;
        case WLAN_CIPHER_SUITE_TKIP:
-               iwl_mvm_set_tkip_rx_seq(rsc->tkip.multicast_rsc, key);
+               iwl_mvm_set_key_rx_seq_tids(key, status->gtk.tkip.seq);
                break;
        default:
                WARN_ON(1);
@@ -1619,7 +1669,7 @@ static void iwl_mvm_set_key_rx_seq(struct iwl_mvm *mvm,
 
 struct iwl_mvm_d3_gtk_iter_data {
        struct iwl_mvm *mvm;
-       struct iwl_wowlan_status *status;
+       struct iwl_wowlan_status_data *status;
        void *last_gtk;
        u32 cipher;
        bool find_phase, unhandled_cipher;
@@ -1633,6 +1683,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
                                   void *_data)
 {
        struct iwl_mvm_d3_gtk_iter_data *data = _data;
+       struct iwl_wowlan_status_data *status = data->status;
 
        if (data->unhandled_cipher)
                return;
@@ -1661,10 +1712,6 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
         * note that this assumes no TDLS sessions are active
         */
        if (sta) {
-               struct ieee80211_key_seq seq = {};
-               union iwl_all_tsc_rsc *sc =
-                       &data->status->gtk[0].rsc.all_tsc_rsc;
-
                if (data->find_phase)
                        return;
 
@@ -1672,16 +1719,12 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
                case WLAN_CIPHER_SUITE_CCMP:
                case WLAN_CIPHER_SUITE_GCMP:
                case WLAN_CIPHER_SUITE_GCMP_256:
-                       iwl_mvm_set_aes_rx_seq(data->mvm, sc->aes.unicast_rsc,
-                                              sta, key);
-                       atomic64_set(&key->tx_pn, le64_to_cpu(sc->aes.tsc.pn));
+                       atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn);
+                       iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);
                        break;
                case WLAN_CIPHER_SUITE_TKIP:
-                       iwl_mvm_tkip_sc_to_seq(&sc->tkip.tsc, &seq);
-                       iwl_mvm_set_tkip_rx_seq(sc->tkip.unicast_rsc, key);
-                       atomic64_set(&key->tx_pn,
-                                    (u64)seq.tkip.iv16 |
-                                    ((u64)seq.tkip.iv32 << 16));
+                       atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn);
+                       iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);
                        break;
                }
 
@@ -1703,7 +1746,7 @@ static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,
 
 static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                                          struct ieee80211_vif *vif,
-                                         struct iwl_wowlan_status *status)
+                                         struct iwl_wowlan_status_data *status)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
        struct iwl_mvm_d3_gtk_iter_data gtkdata = {
@@ -1717,7 +1760,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
        if (!status || !vif->bss_conf.bssid)
                return false;
 
-       if (le32_to_cpu(status->wakeup_reasons) & disconnection_reasons)
+       if (status->wakeup_reasons & disconnection_reasons)
                return false;
 
        /* find last GTK that we used initially, if any */
@@ -1741,7 +1784,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                            iwl_mvm_d3_update_keys, &gtkdata);
 
        IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",
-                        le32_to_cpu(status->num_of_gtk_rekeys));
+                        status->num_of_gtk_rekeys);
        if (status->num_of_gtk_rekeys) {
                struct ieee80211_key_conf *key;
                struct {
@@ -1750,36 +1793,32 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                } conf = {
                        .conf.cipher = gtkdata.cipher,
                        .conf.keyidx =
-                               iwlmvm_wowlan_gtk_idx(&status->gtk[0]),
+                               status->gtk.flags & IWL_WOWLAN_GTK_IDX_MASK,
                };
                __be64 replay_ctr;
 
                IWL_DEBUG_WOWLAN(mvm,
                                 "Received from FW GTK cipher %d, key index %d\n",
                                 conf.conf.cipher, conf.conf.keyidx);
+
+               BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
+               BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
+               BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
+               BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
+               BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk.key));
+
+               memcpy(conf.conf.key, status->gtk.key, sizeof(status->gtk.key));
+
                switch (gtkdata.cipher) {
                case WLAN_CIPHER_SUITE_CCMP:
                case WLAN_CIPHER_SUITE_GCMP:
-                       BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);
-                       BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);
                        conf.conf.keylen = WLAN_KEY_LEN_CCMP;
-                       memcpy(conf.conf.key, status->gtk[0].key,
-                              WLAN_KEY_LEN_CCMP);
                        break;
                case WLAN_CIPHER_SUITE_GCMP_256:
-                       BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);
                        conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;
-                       memcpy(conf.conf.key, status->gtk[0].key,
-                              WLAN_KEY_LEN_GCMP_256);
                        break;
                case WLAN_CIPHER_SUITE_TKIP:
-                       BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);
                        conf.conf.keylen = WLAN_KEY_LEN_TKIP;
-                       memcpy(conf.conf.key, status->gtk[0].key, 16);
-                       /* leave TX MIC key zeroed, we don't use it anyway */
-                       memcpy(conf.conf.key +
-                              NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
-                              status->gtk[0].tkip_mic_key, 8);
                        break;
                }
 
@@ -1788,8 +1827,7 @@ static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,
                        return false;
                iwl_mvm_set_key_rx_seq(mvm, key, status);
 
-               replay_ctr =
-                       cpu_to_be64(le64_to_cpu(status->replay_ctr));
+               replay_ctr = cpu_to_be64(status->replay_ctr);
 
                ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,
                                           (void *)&replay_ctr, GFP_KERNEL);
@@ -1800,7 +1838,7 @@ out:
                                    WOWLAN_GET_STATUSES, 0) < 10) {
                mvmvif->seqno_valid = true;
                /* +0x10 because the set API expects next-to-use, not last-used */
-               mvmvif->seqno = le16_to_cpu(status->non_qos_seq_ctr) + 0x10;
+               mvmvif->seqno = status->non_qos_seq_ctr + 0x10;
        }
 
        return true;
@@ -1808,13 +1846,13 @@ out:
 
 /* Occasionally, templates would be nice. This is one of those times ... */
 #define iwl_mvm_parse_wowlan_status_common(_ver)                       \
-static struct iwl_wowlan_status *                                      \
+static struct iwl_wowlan_status_data *                                 \
 iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm,       \
-                                           void *_data, int len)       \
+                                           struct iwl_wowlan_status_ ##_ver *data,\
+                                           int len)                    \
 {                                                                      \
-       struct iwl_wowlan_status *status;                               \
-       struct iwl_wowlan_status_ ##_ver *data = _data;                 \
-       int data_size;                                                  \
+       struct iwl_wowlan_status_data *status;                          \
+       int data_size, i;                                               \
                                                                        \
        if (len < sizeof(*data)) {                                      \
                IWL_ERR(mvm, "Invalid WoWLAN status response!\n");      \
@@ -1832,18 +1870,22 @@ iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm,        \
                return ERR_PTR(-ENOMEM);                                \
                                                                        \
        /* copy all the common fields */                                \
-       status->replay_ctr = data->replay_ctr;                          \
-       status->pattern_number = data->pattern_number;                  \
-       status->non_qos_seq_ctr = data->non_qos_seq_ctr;                \
-       memcpy(status->qos_seq_ctr, data->qos_seq_ctr,                  \
-              sizeof(status->qos_seq_ctr));                            \
-       status->wakeup_reasons = data->wakeup_reasons;                  \
-       status->num_of_gtk_rekeys = data->num_of_gtk_rekeys;            \
-       status->received_beacons = data->received_beacons;              \
-       status->wake_packet_length = data->wake_packet_length;          \
-       status->wake_packet_bufsize = data->wake_packet_bufsize;        \
+       status->replay_ctr = le64_to_cpu(data->replay_ctr);             \
+       status->pattern_number = le16_to_cpu(data->pattern_number);     \
+       status->non_qos_seq_ctr = le16_to_cpu(data->non_qos_seq_ctr);   \
+       for (i = 0; i < 8; i++)                                         \
+               status->qos_seq_ctr[i] =                                \
+                       le16_to_cpu(data->qos_seq_ctr[i]);              \
+       status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);     \
+       status->num_of_gtk_rekeys =                                     \
+               le32_to_cpu(data->num_of_gtk_rekeys);                   \
+       status->received_beacons = le32_to_cpu(data->received_beacons); \
+       status->wake_packet_length =                                    \
+               le32_to_cpu(data->wake_packet_length);                  \
+       status->wake_packet_bufsize =                                   \
+               le32_to_cpu(data->wake_packet_bufsize);                 \
        memcpy(status->wake_packet, data->wake_packet,                  \
-              le32_to_cpu(status->wake_packet_bufsize));               \
+              status->wake_packet_bufsize);                            \
                                                                        \
        return status;                                                  \
 }
@@ -1852,10 +1894,49 @@ iwl_mvm_parse_wowlan_status_common(v6)
 iwl_mvm_parse_wowlan_status_common(v7)
 iwl_mvm_parse_wowlan_status_common(v9)
 
-static struct iwl_wowlan_status *
+static void iwl_mvm_convert_gtk(struct iwl_wowlan_status_data *status,
+                               struct iwl_wowlan_gtk_status *data)
+{
+       BUILD_BUG_ON(sizeof(status->gtk.key) < sizeof(data->key));
+       BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
+                    sizeof(data->tkip_mic_key) >
+                    sizeof(status->gtk.key));
+
+       status->gtk.len = data->key_len;
+       status->gtk.flags = data->key_flags;
+
+       memcpy(status->gtk.key, data->key, sizeof(data->key));
+
+       /* if it's as long as the TKIP encryption key, copy MIC key */
+       if (status->gtk.len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
+               memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+                      data->tkip_mic_key, sizeof(data->tkip_mic_key));
+}
+
+static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
+                                struct iwl_wowlan_igtk_status *data)
+{
+       const u8 *ipn = data->ipn;
+
+       BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key));
+
+       status->igtk.len = data->key_len;
+       status->igtk.flags = data->key_flags;
+
+       memcpy(status->igtk.key, data->key, sizeof(data->key));
+
+       status->igtk.ipn = ((u64)ipn[5] <<  0) |
+                          ((u64)ipn[4] <<  8) |
+                          ((u64)ipn[3] << 16) |
+                          ((u64)ipn[2] << 24) |
+                          ((u64)ipn[1] << 32) |
+                          ((u64)ipn[0] << 40);
+}
+
+static struct iwl_wowlan_status_data *
 iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
 {
-       struct iwl_wowlan_status *status;
+       struct iwl_wowlan_status_data *status;
        struct iwl_wowlan_get_status_cmd get_status_cmd = {
                .sta_id = cpu_to_le32(sta_id),
        };
@@ -1895,59 +1976,57 @@ iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)
                        IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL)) {
                struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;
 
-               status = iwl_mvm_parse_wowlan_status_common_v6(mvm,
-                                                              cmd.resp_pkt->data,
-                                                              len);
+               status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);
                if (IS_ERR(status))
                        goto out_free_resp;
 
                BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >
-                            sizeof(status->gtk[0].key));
-               BUILD_BUG_ON(sizeof(v6->gtk.tkip_mic_key) >
-                            sizeof(status->gtk[0].tkip_mic_key));
+                            sizeof(status->gtk.key));
+               BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +
+                            sizeof(v6->gtk.tkip_mic_key) >
+                            sizeof(status->gtk.key));
 
                /* copy GTK info to the right place */
-               memcpy(status->gtk[0].key, v6->gtk.decrypt_key,
+               memcpy(status->gtk.key, v6->gtk.decrypt_key,
                       sizeof(v6->gtk.decrypt_key));
-               memcpy(status->gtk[0].tkip_mic_key, v6->gtk.tkip_mic_key,
+               memcpy(status->gtk.key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
+                      v6->gtk.tkip_mic_key,
                       sizeof(v6->gtk.tkip_mic_key));
-               memcpy(&status->gtk[0].rsc, &v6->gtk.rsc,
-                      sizeof(status->gtk[0].rsc));
+
+               iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);
 
                /* hardcode the key length to 16 since v6 only supports 16 */
-               status->gtk[0].key_len = 16;
+               status->gtk.len = 16;
 
                /*
                 * The key index only uses 2 bits (values 0 to 3) and
                 * we always set bit 7 which means this is the
                 * currently used key.
                 */
-               status->gtk[0].key_flags = v6->gtk.key_index | BIT(7);
+               status->gtk.flags = v6->gtk.key_index | BIT(7);
        } else if (notif_ver == 7) {
                struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;
 
-               status = iwl_mvm_parse_wowlan_status_common_v7(mvm,
-                                                              cmd.resp_pkt->data,
-                                                              len);
+               status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len);
                if (IS_ERR(status))
                        goto out_free_resp;
 
-               status->gtk[0] = v7->gtk[0];
-               status->igtk[0] = v7->igtk[0];
+               iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);
+               iwl_mvm_convert_gtk(status, &v7->gtk[0]);
+               iwl_mvm_convert_igtk(status, &v7->igtk[0]);
        } else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {
                struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;
 
                /* these three command versions have same layout and size, the
                 * difference is only in a few not used (reserved) fields.
                 */
-               status = iwl_mvm_parse_wowlan_status_common_v9(mvm,
-                                                              cmd.resp_pkt->data,
-                                                              len);
+               status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);
                if (IS_ERR(status))
                        goto out_free_resp;
 
-               status->gtk[0] = v9->gtk[0];
-               status->igtk[0] = v9->igtk[0];
+               iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);
+               iwl_mvm_convert_gtk(status, &v9->gtk[0]);
+               iwl_mvm_convert_igtk(status, &v9->igtk[0]);
 
                status->tid_tear_down = v9->tid_tear_down;
        } else {
@@ -1962,7 +2041,7 @@ out_free_resp:
        return status;
 }
 
-static struct iwl_wowlan_status *
+static struct iwl_wowlan_status_data *
 iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, u8 sta_id)
 {
        u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
@@ -1987,29 +2066,17 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
                                         struct ieee80211_vif *vif)
 {
        struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-       struct iwl_wowlan_status_data status;
-       struct iwl_wowlan_status *fw_status;
+       struct iwl_wowlan_status_data *status;
        int i;
        bool keep;
        struct iwl_mvm_sta *mvm_ap_sta;
 
-       fw_status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id);
-       if (IS_ERR_OR_NULL(fw_status))
+       status = iwl_mvm_get_wakeup_status(mvm, mvmvif->ap_sta_id);
+       if (IS_ERR(status))
                goto out_unlock;
 
        IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",
-                        le32_to_cpu(fw_status->wakeup_reasons));
-
-       status.pattern_number = le16_to_cpu(fw_status->pattern_number);
-       for (i = 0; i < 8; i++)
-               status.qos_seq_ctr[i] =
-                       le16_to_cpu(fw_status->qos_seq_ctr[i]);
-       status.wakeup_reasons = le32_to_cpu(fw_status->wakeup_reasons);
-       status.wake_packet_length =
-               le32_to_cpu(fw_status->wake_packet_length);
-       status.wake_packet_bufsize =
-               le32_to_cpu(fw_status->wake_packet_bufsize);
-       status.wake_packet = fw_status->wake_packet;
+                        status->wakeup_reasons);
 
        /* still at hard-coded place 0 for D3 image */
        mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, 0);
@@ -2017,7 +2084,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
                goto out_free;
 
        for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
-               u16 seq = status.qos_seq_ctr[i];
+               u16 seq = status->qos_seq_ctr[i];
                /* firmware stores last-used value, we store next value */
                seq += 0x10;
                mvm_ap_sta->tid_data[i].seq_number = seq;
@@ -2033,15 +2100,15 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
        /* now we have all the data we need, unlock to avoid mac80211 issues */
        mutex_unlock(&mvm->mutex);
 
-       iwl_mvm_report_wakeup_reasons(mvm, vif, &status);
+       iwl_mvm_report_wakeup_reasons(mvm, vif, status);
 
-       keep = iwl_mvm_setup_connection_keep(mvm, vif, fw_status);
+       keep = iwl_mvm_setup_connection_keep(mvm, vif, status);
 
-       kfree(fw_status);
+       kfree(status);
        return keep;
 
 out_free:
-       kfree(fw_status);
+       kfree(status);
 out_unlock:
        mutex_unlock(&mvm->mutex);
        return false;
@@ -2165,16 +2232,16 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
                .pattern_idx = -1,
        };
        struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
+       struct iwl_wowlan_status_data *status;
        struct iwl_mvm_nd_query_results query;
-       struct iwl_wowlan_status *fw_status;
        unsigned long matched_profiles;
        u32 reasons = 0;
        int i, n_matches, ret;
 
-       fw_status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA);
-       if (!IS_ERR_OR_NULL(fw_status)) {
-               reasons = le32_to_cpu(fw_status->wakeup_reasons);
-               kfree(fw_status);
+       status = iwl_mvm_get_wakeup_status(mvm, IWL_MVM_INVALID_STA);
+       if (!IS_ERR(status)) {
+               reasons = status->wakeup_reasons;
+               kfree(status);
        }
 
        if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
index 5dc39fb..ff66001 100644 (file)
@@ -395,10 +395,9 @@ static ssize_t iwl_dbgfs_rs_data_read(struct file *file, char __user *user_buf,
                          "A-MPDU size limit %d\n",
                          lq_sta->pers.dbg_agg_frame_count_lim);
        desc += scnprintf(buff + desc, bufsz - desc,
-                         "valid_tx_ant %s%s%s\n",
+                         "valid_tx_ant %s%s\n",
                (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
-               (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "",
-               (iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : "");
+               (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");
        desc += scnprintf(buff + desc, bufsz - desc,
                          "last tx rate=0x%X ",
                          lq_sta->last_rate_n_flags);
@@ -986,8 +985,8 @@ static ssize_t iwl_dbgfs_frame_stats_read(struct iwl_mvm *mvm,
                        continue;
                pos += scnprintf(pos, endpos - pos, "Rate[%d]: ",
                                 (int)(ARRAY_SIZE(stats->last_rates) - i));
-               pos += rs_pretty_print_rate(pos, endpos - pos,
-                                           stats->last_rates[idx]);
+               pos += rs_pretty_print_rate_v1(pos, endpos - pos,
+                                              stats->last_rates[idx]);
                if (pos < endpos - 1)
                        *pos++ = '\n';
        }
@@ -1060,8 +1059,6 @@ iwl_dbgfs_scan_ant_rxchain_read(struct file *file,
                pos += scnprintf(buf + pos, bufsz - pos, "A");
        if (mvm->scan_rx_ant & ANT_B)
                pos += scnprintf(buf + pos, bufsz - pos, "B");
-       if (mvm->scan_rx_ant & ANT_C)
-               pos += scnprintf(buf + pos, bufsz - pos, "C");
        pos += scnprintf(buf + pos, bufsz - pos, " (%hhx)\n", mvm->scan_rx_ant);
 
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
@@ -1196,7 +1193,6 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
        struct ieee80211_tx_info *info;
        struct iwl_mac_beacon_cmd beacon_cmd = {};
        u8 rate;
-       u16 flags;
        int i;
 
        len /= 2;
@@ -1243,12 +1239,9 @@ static int _iwl_dbgfs_inject_beacon_ie(struct iwl_mvm *mvm, char *bin, int len)
        mvmvif = iwl_mvm_vif_from_mac80211(vif);
        info = IEEE80211_SKB_CB(beacon);
        rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
-       flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
 
-       if (rate == IWL_FIRST_CCK_RATE)
-               flags |= IWL_MAC_BEACON_CCK;
-
-       beacon_cmd.flags = cpu_to_le16(flags);
+       beacon_cmd.flags =
+               cpu_to_le16(iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate));
        beacon_cmd.byte_cnt = cpu_to_le16((u16)beacon->len);
        beacon_cmd.template_id = cpu_to_le32((u32)mvmvif->id);
 
index 03e5bf5..949fb79 100644 (file)
@@ -324,6 +324,7 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm,
                              u8 *ctrl_ch_position)
 {
        u32 freq = peer->chandef.chan->center_freq;
+       u8 cmd_ver;
 
        *channel = ieee80211_frequency_to_channel(freq);
 
@@ -344,6 +345,17 @@ iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm,
                *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT;
                *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
                break;
+       case NL80211_CHAN_WIDTH_160:
+               cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP,
+                                               TOF_RANGE_REQ_CMD,
+                                               IWL_FW_CMD_VER_UNKNOWN);
+
+               if (cmd_ver >= 13) {
+                       *format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
+                       *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
+                       break;
+               }
+               fallthrough;
        default:
                IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n",
                        peer->chandef.width);
@@ -1142,6 +1154,7 @@ static u8 iwl_mvm_ftm_get_range_resp_ver(struct iwl_mvm *mvm)
 static bool iwl_mvm_ftm_resp_size_validation(u8 ver, unsigned int pkt_len)
 {
        switch (ver) {
+       case 9:
        case 8:
                return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v8);
        case 7:
@@ -1205,7 +1218,7 @@ void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb)
                int peer_idx;
 
                if (new_api) {
-                       if (notif_ver == 8) {
+                       if (notif_ver >= 8) {
                                fw_ap = &fw_resp_v8->ap[i];
                                iwl_mvm_ftm_pasn_update_pn(mvm, fw_ap);
                        } else if (notif_ver == 7) {
index eba5433..bda6da7 100644 (file)
@@ -46,8 +46,8 @@ static int iwl_mvm_ftm_responder_set_bw_v1(struct cfg80211_chan_def *chandef,
 }
 
 static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
-                                          u8 *format_bw,
-                                          u8 *ctrl_ch_position)
+                                          u8 *format_bw, u8 *ctrl_ch_position,
+                                          u8 cmd_ver)
 {
        switch (chandef->width) {
        case NL80211_CHAN_WIDTH_20_NOHT:
@@ -68,6 +68,14 @@ static int iwl_mvm_ftm_responder_set_bw_v2(struct cfg80211_chan_def *chandef,
                *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS;
                *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
                break;
+       case NL80211_CHAN_WIDTH_160:
+               if (cmd_ver >= 9) {
+                       *format_bw = IWL_LOCATION_FRAME_FORMAT_HE;
+                       *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS;
+                       *ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
+                       break;
+               }
+               fallthrough;
        default:
                return -ENOTSUPP;
        }
@@ -140,7 +148,8 @@ iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
 
        if (cmd_ver >= 7)
                err = iwl_mvm_ftm_responder_set_bw_v2(chandef, &cmd.format_bw,
-                                                     &cmd.ctrl_ch_position);
+                                                     &cmd.ctrl_ch_position,
+                                                     cmd_ver);
        else
                err = iwl_mvm_ftm_responder_set_bw_v1(chandef, &cmd.format_bw,
                                                      &cmd.ctrl_ch_position);
index 74404c9..863fec1 100644 (file)
@@ -295,6 +295,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
        if (ret) {
                struct iwl_trans *trans = mvm->trans;
 
+               /* SecBoot info */
                if (trans->trans_cfg->device_family >=
                                        IWL_DEVICE_FAMILY_22000) {
                        IWL_ERR(mvm,
@@ -302,6 +303,17 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
                                iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS),
                                iwl_read_umac_prph(trans,
                                                   UMAG_SB_CPU_2_STATUS));
+               } else if (trans->trans_cfg->device_family >=
+                          IWL_DEVICE_FAMILY_8000) {
+                       IWL_ERR(mvm,
+                               "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
+                               iwl_read_prph(trans, SB_CPU_1_STATUS),
+                               iwl_read_prph(trans, SB_CPU_2_STATUS));
+               }
+
+               /* LMAC/UMAC PC info */
+               if (trans->trans_cfg->device_family >=
+                                       IWL_DEVICE_FAMILY_9000) {
                        IWL_ERR(mvm, "UMAC PC: 0x%x\n",
                                iwl_read_umac_prph(trans,
                                                   UREG_UMAC_CURRENT_PC));
@@ -312,12 +324,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
                                IWL_ERR(mvm, "LMAC2 PC: 0x%x\n",
                                        iwl_read_umac_prph(trans,
                                                UREG_LMAC2_CURRENT_PC));
-               } else if (trans->trans_cfg->device_family >=
-                          IWL_DEVICE_FAMILY_8000) {
-                       IWL_ERR(mvm,
-                               "SecBoot CPU1 Status: 0x%x, CPU2 Status: 0x%x\n",
-                               iwl_read_prph(trans, SB_CPU_1_STATUS),
-                               iwl_read_prph(trans, SB_CPU_2_STATUS));
                }
 
                if (ret == -ETIMEDOUT)
@@ -763,14 +769,18 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
        int ret;
        struct iwl_host_cmd cmd;
        u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
-                                          GEO_TX_POWER_LIMIT,
+                                          PER_CHAIN_LIMIT_OFFSET_CMD,
                                           IWL_FW_CMD_VER_UNKNOWN);
 
        /* the ops field is at the same spot for all versions, so set in v1 */
        geo_tx_cmd.v1.ops =
                cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
 
-       if (cmd_ver == 3)
+       if (cmd_ver == 5)
+               len = sizeof(geo_tx_cmd.v5);
+       else if (cmd_ver == 4)
+               len = sizeof(geo_tx_cmd.v4);
+       else if (cmd_ver == 3)
                len = sizeof(geo_tx_cmd.v3);
        else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
                            IWL_UCODE_TLV_API_SAR_TABLE_VER))
@@ -782,7 +792,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
                return -EOPNOTSUPP;
 
        cmd = (struct iwl_host_cmd){
-               .id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
+               .id =  WIDE_ID(PHY_OPS_GROUP, PER_CHAIN_LIMIT_OFFSET_CMD),
                .len = { len, },
                .flags = CMD_WANT_SKB,
                .data = { &geo_tx_cmd },
@@ -797,7 +807,7 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
        resp = (void *)cmd.resp_pkt->data;
        ret = le32_to_cpu(resp->profile_idx);
 
-       if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES))
+       if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES_REV3))
                ret = -EIO;
 
        iwl_free_resp(&cmd);
@@ -809,36 +819,58 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
        union iwl_geo_tx_power_profiles_cmd cmd;
        u16 len;
        u32 n_bands;
+       u32 n_profiles;
        int ret;
        u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
-                                          GEO_TX_POWER_LIMIT,
+                                          PER_CHAIN_LIMIT_OFFSET_CMD,
                                           IWL_FW_CMD_VER_UNKNOWN);
 
        BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, ops) !=
                     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) ||
                     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, ops) !=
-                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops));
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops) ||
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, ops) !=
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) ||
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, ops) !=
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, ops));
+
        /* the ops field is at the same spot for all versions, so set in v1 */
        cmd.v1.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
 
-       if (cmd_ver == 3) {
+       if (cmd_ver == 5) {
+               len = sizeof(cmd.v5);
+               n_bands = ARRAY_SIZE(cmd.v5.table[0]);
+               n_profiles = ACPI_NUM_GEO_PROFILES_REV3;
+       } else if (cmd_ver == 4) {
+               len = sizeof(cmd.v4);
+               n_bands = ARRAY_SIZE(cmd.v4.table[0]);
+               n_profiles = ACPI_NUM_GEO_PROFILES_REV3;
+       } else if (cmd_ver == 3) {
                len = sizeof(cmd.v3);
                n_bands = ARRAY_SIZE(cmd.v3.table[0]);
+               n_profiles = ACPI_NUM_GEO_PROFILES;
        } else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
                              IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
                len = sizeof(cmd.v2);
                n_bands = ARRAY_SIZE(cmd.v2.table[0]);
+               n_profiles = ACPI_NUM_GEO_PROFILES;
        } else {
                len = sizeof(cmd.v1);
                n_bands = ARRAY_SIZE(cmd.v1.table[0]);
+               n_profiles = ACPI_NUM_GEO_PROFILES;
        }
 
        BUILD_BUG_ON(offsetof(struct iwl_geo_tx_power_profiles_cmd_v1, table) !=
                     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) ||
                     offsetof(struct iwl_geo_tx_power_profiles_cmd_v2, table) !=
-                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table));
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table) ||
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v3, table) !=
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) ||
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v4, table) !=
+                    offsetof(struct iwl_geo_tx_power_profiles_cmd_v5, table));
        /* the table is at the same position for all versions, so set use v1 */
-       ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0], n_bands);
+       ret = iwl_sar_geo_init(&mvm->fwrt, &cmd.v1.table[0][0],
+                              n_bands, n_profiles);
 
        /*
         * It is a valid scenario to not support SAR, or miss wgds table,
@@ -851,14 +883,19 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
         * Set the revision on versions that contain it.
         * This must be done after calling iwl_sar_geo_init().
         */
-       if (cmd_ver == 3)
+       if (cmd_ver == 5)
+               cmd.v5.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
+       else if (cmd_ver == 4)
+               cmd.v4.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
+       else if (cmd_ver == 3)
                cmd.v3.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
        else if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
                            IWL_UCODE_TLV_API_SAR_TABLE_VER))
                cmd.v2.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
 
        return iwl_mvm_send_cmd_pdu(mvm,
-                                   WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
+                                   WIDE_ID(PHY_OPS_GROUP,
+                                           PER_CHAIN_LIMIT_OFFSET_CMD),
                                    0, len, &cmd);
 }
 
@@ -1108,7 +1145,7 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm)
 static u8 iwl_mvm_eval_dsm_rfi(struct iwl_mvm *mvm)
 {
        u8 value;
-       int ret = iwl_acpi_get_dsm_u8((&mvm->fwrt)->dev, 0, DSM_RFI_FUNC_ENABLE,
+       int ret = iwl_acpi_get_dsm_u8(mvm->fwrt.dev, 0, DSM_RFI_FUNC_ENABLE,
                                      &iwl_rfi_guid, &value);
 
        if (ret < 0) {
@@ -1133,30 +1170,45 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
 {
        int ret;
        u32 value;
-       struct iwl_lari_config_change_cmd_v4 cmd = {};
+       struct iwl_lari_config_change_cmd_v5 cmd = {};
 
        cmd.config_bitmap = iwl_acpi_get_lari_config_bitmap(&mvm->fwrt);
 
-       ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0, DSM_FUNC_11AX_ENABLEMENT,
+       ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0, DSM_FUNC_11AX_ENABLEMENT,
                                   &iwl_guid, &value);
        if (!ret)
                cmd.oem_11ax_allow_bitmap = cpu_to_le32(value);
-       /* apply more config masks here */
 
-       ret = iwl_acpi_get_dsm_u32((&mvm->fwrt)->dev, 0,
+       ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
                                   DSM_FUNC_ENABLE_UNII4_CHAN,
                                   &iwl_guid, &value);
        if (!ret)
                cmd.oem_unii4_allow_bitmap = cpu_to_le32(value);
 
+       ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
+                                  DSM_FUNC_ACTIVATE_CHANNEL,
+                                  &iwl_guid, &value);
+       if (!ret)
+               cmd.chan_state_active_bitmap = cpu_to_le32(value);
+
+       ret = iwl_acpi_get_dsm_u32(mvm->fwrt.dev, 0,
+                                  DSM_FUNC_ENABLE_6E,
+                                  &iwl_guid, &value);
+       if (!ret)
+               cmd.oem_uhb_allow_bitmap = cpu_to_le32(value);
+
        if (cmd.config_bitmap ||
+           cmd.oem_uhb_allow_bitmap ||
            cmd.oem_11ax_allow_bitmap ||
-           cmd.oem_unii4_allow_bitmap) {
+           cmd.oem_unii4_allow_bitmap ||
+           cmd.chan_state_active_bitmap) {
                size_t cmd_size;
                u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,
                                                   REGULATORY_AND_NVM_GROUP,
                                                   LARI_CONFIG_CHANGE, 1);
-               if (cmd_ver == 4)
+               if (cmd_ver == 5)
+                       cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5);
+               else if (cmd_ver == 4)
                        cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4);
                else if (cmd_ver == 3)
                        cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3);
@@ -1170,9 +1222,13 @@ static void iwl_mvm_lari_cfg(struct iwl_mvm *mvm)
                                le32_to_cpu(cmd.config_bitmap),
                                le32_to_cpu(cmd.oem_11ax_allow_bitmap));
                IWL_DEBUG_RADIO(mvm,
-                               "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, cmd_ver=%d\n",
+                               "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n",
                                le32_to_cpu(cmd.oem_unii4_allow_bitmap),
+                               le32_to_cpu(cmd.chan_state_active_bitmap),
                                cmd_ver);
+               IWL_DEBUG_RADIO(mvm,
+                               "sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x\n",
+                               le32_to_cpu(cmd.oem_uhb_allow_bitmap));
                ret = iwl_mvm_send_cmd_pdu(mvm,
                                           WIDE_ID(REGULATORY_AND_NVM_GROUP,
                                                   LARI_CONFIG_CHANGE),
index fd352b2..fd7d4ab 100644 (file)
@@ -604,6 +604,12 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
 
                ctxt_sta->is_assoc = cpu_to_le32(1);
 
+               if (!mvmvif->authorized &&
+                   fw_has_capa(&mvm->fw->ucode_capa,
+                               IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO))
+                       ctxt_sta->data_policy |=
+                               cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE);
+
                /*
                 * allow multicast data frames only as long as the station is
                 * authorized, i.e., GTK keys are already installed (if needed)
@@ -812,6 +818,21 @@ u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
        return rate;
 }
 
+u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw, u8 rate_idx)
+{
+       u16 flags = iwl_mvm_mac80211_idx_to_hwrate(fw, rate_idx);
+       bool is_new_rate = iwl_fw_lookup_cmd_ver(fw,
+                                                LONG_GROUP,
+                                                BEACON_TEMPLATE_CMD,
+                                                0) > 10;
+
+       if (rate_idx <= IWL_FIRST_CCK_RATE)
+               flags |= is_new_rate ? IWL_MAC_BEACON_CCK
+                         : IWL_MAC_BEACON_CCK_V1;
+
+       return flags;
+}
+
 static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
                                    struct ieee80211_vif *vif,
                                    struct sk_buff *beacon,
@@ -844,9 +865,10 @@ static void iwl_mvm_mac_ctxt_set_tx(struct iwl_mvm *mvm,
 
        rate = iwl_mvm_mac_ctxt_get_lowest_rate(info, vif);
 
-       tx->rate_n_flags |= cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(rate));
+       tx->rate_n_flags |=
+               cpu_to_le32(iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate));
        if (rate == IWL_FIRST_CCK_RATE)
-               tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK);
+               tx->rate_n_flags |= cpu_to_le32(RATE_MCS_CCK_MSK_V1);
 
 }
 
@@ -929,11 +951,7 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
        u16 flags;
        struct ieee80211_chanctx_conf *ctx;
        int channel;
-
-       flags = iwl_mvm_mac80211_idx_to_hwrate(rate);
-
-       if (rate == IWL_FIRST_CCK_RATE)
-               flags |= IWL_MAC_BEACON_CCK;
+       flags = iwl_mvm_mac_ctxt_get_beacon_flags(mvm->fw, rate);
 
        /* Enable FILS on PSC channels only */
        rcu_read_lock();
@@ -942,7 +960,11 @@ static int iwl_mvm_mac_ctxt_send_beacon_v9(struct iwl_mvm *mvm,
        WARN_ON(channel == 0);
        if (cfg80211_channel_is_psc(ctx->def.chan) &&
            !IWL_MVM_DISABLE_AP_FILS) {
-               flags |= IWL_MAC_BEACON_FILS;
+               flags |= iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP,
+                                              BEACON_TEMPLATE_CMD,
+                                              0) > 10 ?
+                       IWL_MAC_BEACON_FILS :
+                       IWL_MAC_BEACON_FILS_V1;
                beacon_cmd.short_ssid =
                        cpu_to_le32(~crc32_le(~0, vif->bss_conf.ssid,
                                              vif->bss_conf.ssid_len));
@@ -1535,11 +1557,11 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
                ieee80211_beacon_set_cntdwn(vif, notif->csa_counter);
 }
 
-void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
-                                     struct iwl_rx_cmd_buffer *rxb)
+void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
+                                       struct iwl_rx_cmd_buffer *rxb)
 {
        struct iwl_rx_packet *pkt = rxb_addr(rxb);
-       struct iwl_channel_switch_noa_notif *notif = (void *)pkt->data;
+       struct iwl_channel_switch_start_notif *notif = (void *)pkt->data;
        struct ieee80211_vif *csa_vif, *vif;
        struct iwl_mvm_vif *mvmvif;
        u32 id_n_color, csa_id, mac_id;
index 3a45852..9fb9c7d 100644 (file)
@@ -145,7 +145,8 @@ static const struct cfg80211_pmsr_capabilities iwl_mvm_pmsr_capa = {
                .bandwidths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
                              BIT(NL80211_CHAN_WIDTH_20) |
                              BIT(NL80211_CHAN_WIDTH_40) |
-                             BIT(NL80211_CHAN_WIDTH_80),
+                             BIT(NL80211_CHAN_WIDTH_80) |
+                             BIT(NL80211_CHAN_WIDTH_160),
                .preambles = BIT(NL80211_PREAMBLE_LEGACY) |
                             BIT(NL80211_PREAMBLE_HT) |
                             BIT(NL80211_PREAMBLE_VHT) |
@@ -2022,7 +2023,8 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
        }
 
        sband = mvm->hw->wiphy->bands[chanctx_conf->def.chan->band];
-       own_he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);
+       own_he_cap = ieee80211_get_he_iftype_cap(sband,
+                                                ieee80211_vif_type_p2p(vif));
 
        sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_ctxt_cmd.sta_id]);
        if (IS_ERR_OR_NULL(sta)) {
@@ -2234,6 +2236,34 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm,
                IWL_ERR(mvm, "Failed to config FW to work HE!\n");
 }
 
+static void iwl_mvm_protect_assoc(struct iwl_mvm *mvm,
+                                 struct ieee80211_vif *vif,
+                                 u32 duration_override)
+{
+       u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
+       u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
+
+       if (duration_override > duration)
+               duration = duration_override;
+
+       /* Try really hard to protect the session and hear a beacon
+        * The new session protection command allows us to protect the
+        * session for a much longer time since the firmware will internally
+        * create two events: a 300TU one with a very high priority that
+        * won't be fragmented which should be enough for 99% of the cases,
+        * and another one (which we configure here to be 900TU long) which
+        * will have a slightly lower priority, but more importantly, can be
+        * fragmented so that it'll allow other activities to run.
+        */
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
+               iwl_mvm_schedule_session_protection(mvm, vif, 900,
+                                                   min_duration, false);
+       else
+               iwl_mvm_protect_session(mvm, vif, duration,
+                                       min_duration, 500, false);
+}
+
 static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                             struct ieee80211_vif *vif,
                                             struct ieee80211_bss_conf *bss_conf,
@@ -2317,6 +2347,20 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
                                u32 dur = (11 * vif->bss_conf.beacon_int) / 10;
                                iwl_mvm_protect_session(mvm, vif, dur, dur,
                                                        5 * dur, false);
+                       } else if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
+                                            &mvm->status) &&
+                                  !vif->bss_conf.dtim_period) {
+                               /*
+                                * If we're not restarting and still haven't
+                                * heard a beacon (dtim period unknown) then
+                                * make sure we still have enough minimum time
+                                * remaining in the time event, since the auth
+                                * might actually have taken quite a while
+                                * (especially for SAE) and so the remaining
+                                * time could be small without us having heard
+                                * a beacon yet.
+                                */
+                               iwl_mvm_protect_assoc(mvm, vif, 0);
                        }
 
                        iwl_mvm_sf_update(mvm, vif, false);
@@ -3192,38 +3236,52 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
                if (iwl_mvm_phy_ctx_count(mvm) > 1)
                        iwl_mvm_teardown_tdls_peers(mvm);
 
-               if (sta->tdls)
+               if (sta->tdls) {
                        iwl_mvm_tdls_check_trigger(mvm, vif, sta->addr,
                                                   NL80211_TDLS_ENABLE_LINK);
+               } else {
+                       /* enable beacon filtering */
+                       WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
 
-               /* enable beacon filtering */
-               WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
+                       mvmvif->authorized = 1;
 
-               /*
-                * Now that the station is authorized, i.e., keys were already
-                * installed, need to indicate to the FW that
-                * multicast data frames can be forwarded to the driver
-                */
-               iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+                       /*
+                        * Now that the station is authorized, i.e., keys were already
+                        * installed, need to indicate to the FW that
+                        * multicast data frames can be forwarded to the driver
+                        */
+                       iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+               }
 
                iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
                                     true);
        } else if (old_state == IEEE80211_STA_AUTHORIZED &&
                   new_state == IEEE80211_STA_ASSOC) {
-               /* Multicast data frames are no longer allowed */
-               iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+               if (!sta->tdls) {
+                       /* Multicast data frames are no longer allowed */
+                       iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+
+                       /*
+                        * Set this after the above iwl_mvm_mac_ctxt_changed()
+                        * to avoid sending high prio again for a little time.
+                        */
+                       mvmvif->authorized = 0;
 
-               /* disable beacon filtering */
-               ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
-               WARN_ON(ret &&
-                       !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
-                                 &mvm->status));
+                       /* disable beacon filtering */
+                       ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
+                       WARN_ON(ret &&
+                               !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED,
+                                         &mvm->status));
+               }
                ret = 0;
        } else if (old_state == IEEE80211_STA_ASSOC &&
                   new_state == IEEE80211_STA_AUTH) {
                if (vif->type == NL80211_IFTYPE_AP) {
                        mvmvif->ap_assoc_sta_count--;
                        iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
+               } else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
+                       /* remove session protection if still running */
+                       iwl_mvm_stop_session_protection(mvm, vif);
                }
                ret = 0;
        } else if (old_state == IEEE80211_STA_AUTH &&
@@ -3316,29 +3374,24 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
                                       struct ieee80211_prep_tx_info *info)
 {
        struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-       u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS;
-       u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS;
 
-       if (info->duration > duration)
-               duration = info->duration;
+       mutex_lock(&mvm->mutex);
+       iwl_mvm_protect_assoc(mvm, vif, info->duration);
+       mutex_unlock(&mvm->mutex);
+}
+
+static void iwl_mvm_mac_mgd_complete_tx(struct ieee80211_hw *hw,
+                                       struct ieee80211_vif *vif,
+                                       struct ieee80211_prep_tx_info *info)
+{
+       struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+       /* for successful cases (auth/assoc), don't cancel session protection */
+       if (info->success)
+               return;
 
        mutex_lock(&mvm->mutex);
-       /* Try really hard to protect the session and hear a beacon
-        * The new session protection command allows us to protect the
-        * session for a much longer time since the firmware will internally
-        * create two events: a 300TU one with a very high priority that
-        * won't be fragmented which should be enough for 99% of the cases,
-        * and another one (which we configure here to be 900TU long) which
-        * will have a slightly lower priority, but more importantly, can be
-        * fragmented so that it'll allow other activities to run.
-        */
-       if (fw_has_capa(&mvm->fw->ucode_capa,
-                       IWL_UCODE_TLV_CAPA_SESSION_PROT_CMD))
-               iwl_mvm_schedule_session_protection(mvm, vif, 900,
-                                                   min_duration, false);
-       else
-               iwl_mvm_protect_session(mvm, vif, duration,
-                                       min_duration, 500, false);
+       iwl_mvm_stop_session_protection(mvm, vif);
        mutex_unlock(&mvm->mutex);
 }
 
@@ -4704,6 +4757,9 @@ static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
        if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_CS_MODIFY))
                return;
 
+       IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d count = %d (old %d) mode = %d\n",
+                          mvmvif->id, chsw->count, mvmvif->csa_count, chsw->block_tx);
+
        if (chsw->count >= mvmvif->csa_count && chsw->block_tx) {
                if (mvmvif->csa_misbehave) {
                        /* Second time, give up on this AP*/
@@ -4720,8 +4776,6 @@ static void iwl_mvm_channel_switch_rx_beacon(struct ieee80211_hw *hw,
        if (mvmvif->csa_failed)
                goto out_unlock;
 
-       IWL_DEBUG_MAC80211(mvm, "Modify CSA on mac %d count = %d mode = %d\n",
-                          mvmvif->id, chsw->count, chsw->block_tx);
        WARN_ON(iwl_mvm_send_cmd_pdu(mvm,
                                     WIDE_ID(MAC_CONF_GROUP,
                                             CHANNEL_SWITCH_TIME_EVENT_CMD),
@@ -4873,6 +4927,8 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx,
 
 static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
 {
+       u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
+
        switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
        case RATE_MCS_CHAN_WIDTH_20:
                rinfo->bw = RATE_INFO_BW_20;
@@ -4888,30 +4944,65 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
                break;
        }
 
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               rinfo->flags |= RATE_INFO_FLAGS_MCS;
-               rinfo->mcs = u32_get_bits(rate_n_flags, RATE_HT_MCS_INDEX_MSK);
-               rinfo->nss = u32_get_bits(rate_n_flags,
-                                         RATE_HT_MCS_NSS_MSK) + 1;
-               if (rate_n_flags & RATE_MCS_SGI_MSK)
-                       rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
-               rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
-               rinfo->mcs = u32_get_bits(rate_n_flags,
-                                         RATE_VHT_MCS_RATE_CODE_MSK);
-               rinfo->nss = u32_get_bits(rate_n_flags,
-                                         RATE_VHT_MCS_NSS_MSK) + 1;
-               if (rate_n_flags & RATE_MCS_SGI_MSK)
-                       rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
-       } else if (rate_n_flags & RATE_MCS_HE_MSK) {
+       if (format == RATE_MCS_CCK_MSK ||
+           format == RATE_MCS_LEGACY_OFDM_MSK) {
+               int rate = u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK);
+
+               /* add the offset needed to get to the legacy ofdm indices */
+               if (format == RATE_MCS_LEGACY_OFDM_MSK)
+                       rate += IWL_FIRST_OFDM_RATE;
+
+               switch (rate) {
+               case IWL_RATE_1M_INDEX:
+                       rinfo->legacy = 10;
+                       break;
+               case IWL_RATE_2M_INDEX:
+                       rinfo->legacy = 20;
+                       break;
+               case IWL_RATE_5M_INDEX:
+                       rinfo->legacy = 55;
+                       break;
+               case IWL_RATE_11M_INDEX:
+                       rinfo->legacy = 110;
+                       break;
+               case IWL_RATE_6M_INDEX:
+                       rinfo->legacy = 60;
+                       break;
+               case IWL_RATE_9M_INDEX:
+                       rinfo->legacy = 90;
+                       break;
+               case IWL_RATE_12M_INDEX:
+                       rinfo->legacy = 120;
+                       break;
+               case IWL_RATE_18M_INDEX:
+                       rinfo->legacy = 180;
+                       break;
+               case IWL_RATE_24M_INDEX:
+                       rinfo->legacy = 240;
+                       break;
+               case IWL_RATE_36M_INDEX:
+                       rinfo->legacy = 360;
+                       break;
+               case IWL_RATE_48M_INDEX:
+                       rinfo->legacy = 480;
+                       break;
+               case IWL_RATE_54M_INDEX:
+                       rinfo->legacy = 540;
+               }
+               return;
+       }
+
+       rinfo->nss = u32_get_bits(rate_n_flags,
+                                 RATE_MCS_NSS_MSK) + 1;
+       rinfo->mcs = format == RATE_MCS_HT_MSK ?
+               RATE_HT_MCS_INDEX(rate_n_flags) :
+               u32_get_bits(rate_n_flags, RATE_MCS_CODE_MSK);
+
+       if (format == RATE_MCS_HE_MSK) {
                u32 gi_ltf = u32_get_bits(rate_n_flags,
                                          RATE_MCS_HE_GI_LTF_MSK);
 
                rinfo->flags |= RATE_INFO_FLAGS_HE_MCS;
-               rinfo->mcs = u32_get_bits(rate_n_flags,
-                                         RATE_VHT_MCS_RATE_CODE_MSK);
-               rinfo->nss = u32_get_bits(rate_n_flags,
-                                         RATE_VHT_MCS_NSS_MSK) + 1;
 
                if (rate_n_flags & RATE_MCS_HE_106T_MSK) {
                        rinfo->bw = RATE_INFO_BW_HE_RU;
@@ -4925,10 +5016,10 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
                                rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
                        else if (gi_ltf == 2)
                                rinfo->he_gi = NL80211_RATE_INFO_HE_GI_1_6;
-                       else if (rate_n_flags & RATE_MCS_SGI_MSK)
-                               rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
-                       else
+                       else if (gi_ltf == 3)
                                rinfo->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
+                       else
+                               rinfo->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
                        break;
                case RATE_MCS_HE_TYPE_MU:
                        if (gi_ltf == 0 || gi_ltf == 1)
@@ -4948,46 +5039,19 @@ static void iwl_mvm_set_sta_rate(u32 rate_n_flags, struct rate_info *rinfo)
 
                if (rate_n_flags & RATE_HE_DUAL_CARRIER_MODE_MSK)
                        rinfo->he_dcm = 1;
-       } else {
-               switch (u32_get_bits(rate_n_flags, RATE_LEGACY_RATE_MSK)) {
-               case IWL_RATE_1M_PLCP:
-                       rinfo->legacy = 10;
-                       break;
-               case IWL_RATE_2M_PLCP:
-                       rinfo->legacy = 20;
-                       break;
-               case IWL_RATE_5M_PLCP:
-                       rinfo->legacy = 55;
-                       break;
-               case IWL_RATE_11M_PLCP:
-                       rinfo->legacy = 110;
-                       break;
-               case IWL_RATE_6M_PLCP:
-                       rinfo->legacy = 60;
-                       break;
-               case IWL_RATE_9M_PLCP:
-                       rinfo->legacy = 90;
-                       break;
-               case IWL_RATE_12M_PLCP:
-                       rinfo->legacy = 120;
-                       break;
-               case IWL_RATE_18M_PLCP:
-                       rinfo->legacy = 180;
-                       break;
-               case IWL_RATE_24M_PLCP:
-                       rinfo->legacy = 240;
-                       break;
-               case IWL_RATE_36M_PLCP:
-                       rinfo->legacy = 360;
-                       break;
-               case IWL_RATE_48M_PLCP:
-                       rinfo->legacy = 480;
-                       break;
-               case IWL_RATE_54M_PLCP:
-                       rinfo->legacy = 540;
-                       break;
-               }
+               return;
+       }
+
+       if (rate_n_flags & RATE_MCS_SGI_MSK)
+               rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+       if (format == RATE_MCS_HT_MSK) {
+               rinfo->flags |= RATE_INFO_FLAGS_MCS;
+
+       } else if (format == RATE_MCS_VHT_MSK) {
+               rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
        }
+
 }
 
 static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,
@@ -5332,6 +5396,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
        .sta_rc_update = iwl_mvm_sta_rc_update,
        .conf_tx = iwl_mvm_mac_conf_tx,
        .mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
+       .mgd_complete_tx = iwl_mvm_mac_mgd_complete_tx,
        .mgd_protect_tdls_discover = iwl_mvm_mac_mgd_protect_tdls_discover,
        .flush = iwl_mvm_mac_flush,
        .sched_scan_start = iwl_mvm_mac_sched_scan_start,
index f877d86..2b1dcd6 100644 (file)
@@ -297,6 +297,7 @@ struct iwl_probe_resp_data {
  *     see enum &iwl_mvm_low_latency_cause for causes.
  * @low_latency_actual: boolean, indicates low latency is set,
  *     as a result from low_latency bit flags and takes force into account.
+ * @authorized: indicates the AP station was set to authorized
  * @ps_disabled: indicates that this interface requires PS to be disabled
  * @queue_params: QoS params for this MAC
  * @bcast_sta: station used for broadcast packets. Used by the following
@@ -330,6 +331,7 @@ struct iwl_mvm_vif {
        bool monitor_active;
        u8 low_latency: 6;
        u8 low_latency_actual: 1;
+       u8 authorized:1;
        bool ps_disabled;
        struct iwl_mvm_vif_bf_data bf_data;
 
@@ -1443,12 +1445,17 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm);
 int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm);
 
 /* Utils */
+int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
+                                         enum nl80211_band band);
 int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
                                        enum nl80211_band band);
 void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
                               enum nl80211_band band,
                               struct ieee80211_tx_rate *r);
-u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx);
+void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
+                                 enum nl80211_band band,
+                                 struct ieee80211_tx_rate *r);
+u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx);
 u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
 
 static inline void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
@@ -1629,6 +1636,8 @@ int iwl_mvm_mac_ctxt_send_beacon_cmd(struct iwl_mvm *mvm,
                                     void *data, int len);
 u8 iwl_mvm_mac_ctxt_get_lowest_rate(struct ieee80211_tx_info *info,
                                    struct ieee80211_vif *vif);
+u16 iwl_mvm_mac_ctxt_get_beacon_flags(const struct iwl_fw *fw,
+                                     u8 rate_idx);
 void iwl_mvm_mac_ctxt_set_tim(struct iwl_mvm *mvm,
                              __le32 *tim_index, __le32 *tim_size,
                              u8 *beacon, u32 frame_size);
@@ -1649,8 +1658,8 @@ void iwl_mvm_probe_resp_data_notif(struct iwl_mvm *mvm,
                                   struct iwl_rx_cmd_buffer *rxb);
 void iwl_mvm_rx_missed_vap_notif(struct iwl_mvm *mvm,
                                 struct iwl_rx_cmd_buffer *rxb);
-void iwl_mvm_channel_switch_noa_notif(struct iwl_mvm *mvm,
-                                     struct iwl_rx_cmd_buffer *rxb);
+void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm,
+                                       struct iwl_rx_cmd_buffer *rxb);
 /* Bindings */
 int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
 int iwl_mvm_binding_remove_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -1732,7 +1741,7 @@ iwl_mvm_vif_dbgfs_clean(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 /* rate scaling */
 int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq);
 void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg);
-int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate);
+int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate);
 void rs_update_last_rssi(struct iwl_mvm *mvm,
                         struct iwl_mvm_sta *mvmsta,
                         struct ieee80211_rx_status *rx_status);
index da705fc..6d18a1f 100644 (file)
@@ -583,8 +583,9 @@ void iwl_mvm_rx_chub_update_mcc(struct iwl_mvm *mvm,
                return;
 
        wgds_tbl_idx = iwl_mvm_get_sar_geo_profile(mvm);
-       if (wgds_tbl_idx < 0)
-               IWL_DEBUG_INFO(mvm, "SAR WGDS is disabled (%d)\n",
+       if (wgds_tbl_idx < 1)
+               IWL_DEBUG_INFO(mvm,
+                              "SAR WGDS is disabled or error received (%d)\n",
                               wgds_tbl_idx);
        else
                IWL_DEBUG_INFO(mvm, "SAR WGDS: geo profile %d is configured\n",
index 77ea2d0..232ad53 100644 (file)
@@ -29,7 +29,6 @@
 
 #define DRV_DESCRIPTION        "The new Intel(R) wireless AGN driver for Linux"
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_AUTHOR(DRV_AUTHOR);
 MODULE_LICENSE("GPL");
 
 static const struct iwl_op_mode_ops iwl_mvm_ops;
@@ -384,9 +383,9 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
                       iwl_mvm_probe_resp_data_notif,
                       RX_HANDLER_ASYNC_LOCKED,
                       struct iwl_probe_resp_data_notif),
-       RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_NOA_NOTIF,
-                      iwl_mvm_channel_switch_noa_notif,
-                      RX_HANDLER_SYNC, struct iwl_channel_switch_noa_notif),
+       RX_HANDLER_GRP(MAC_CONF_GROUP, CHANNEL_SWITCH_START_NOTIF,
+                      iwl_mvm_channel_switch_start_notif,
+                      RX_HANDLER_SYNC, struct iwl_channel_switch_start_notif),
        RX_HANDLER_GRP(DATA_PATH_GROUP, MONITOR_NOTIF,
                       iwl_mvm_rx_monitor_notif, RX_HANDLER_ASYNC_LOCKED,
                       struct iwl_datapath_monitor_notif),
@@ -512,7 +511,7 @@ static const struct iwl_hcmd_names iwl_mvm_mac_conf_names[] = {
        HCMD_NAME(CHANNEL_SWITCH_TIME_EVENT_CMD),
        HCMD_NAME(SESSION_PROTECTION_CMD),
        HCMD_NAME(SESSION_PROTECTION_NOTIF),
-       HCMD_NAME(CHANNEL_SWITCH_NOA_NOTIF),
+       HCMD_NAME(CHANNEL_SWITCH_START_NOTIF),
 };
 
 /* Please keep this array *SORTED* by hex value.
@@ -522,7 +521,7 @@ static const struct iwl_hcmd_names iwl_mvm_phy_names[] = {
        HCMD_NAME(CMD_DTS_MEASUREMENT_TRIGGER_WIDE),
        HCMD_NAME(CTDP_CONFIG_CMD),
        HCMD_NAME(TEMP_REPORTING_THRESHOLDS_CMD),
-       HCMD_NAME(GEO_TX_POWER_LIMIT),
+       HCMD_NAME(PER_CHAIN_LIMIT_OFFSET_CMD),
        HCMD_NAME(CT_KILL_NOTIFICATION),
        HCMD_NAME(DTS_MEASUREMENT_NOTIF_WIDE),
 };
@@ -726,6 +725,183 @@ static int iwl_mvm_start_post_nvm(struct iwl_mvm *mvm)
        return 0;
 }
 
+struct iwl_mvm_frob_txf_data {
+       u8 *buf;
+       size_t buflen;
+};
+
+static void iwl_mvm_frob_txf_key_iter(struct ieee80211_hw *hw,
+                                     struct ieee80211_vif *vif,
+                                     struct ieee80211_sta *sta,
+                                     struct ieee80211_key_conf *key,
+                                     void *data)
+{
+       struct iwl_mvm_frob_txf_data *txf = data;
+       u8 keylen, match, matchend;
+       u8 *keydata;
+       size_t i;
+
+       switch (key->cipher) {
+       case WLAN_CIPHER_SUITE_CCMP:
+               keydata = key->key;
+               keylen = key->keylen;
+               break;
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+       case WLAN_CIPHER_SUITE_TKIP:
+               /*
+                * WEP has short keys which might show up in the payload,
+                * and then you can deduce the key, so in this case just
+                * remove all FIFO data.
+                * For TKIP, we don't know the phase 2 keys here, so same.
+                */
+               memset(txf->buf, 0xBB, txf->buflen);
+               return;
+       default:
+               return;
+       }
+
+       /* scan for key material and clear it out */
+       match = 0;
+       for (i = 0; i < txf->buflen; i++) {
+               if (txf->buf[i] != keydata[match]) {
+                       match = 0;
+                       continue;
+               }
+               match++;
+               if (match == keylen) {
+                       memset(txf->buf + i - keylen, 0xAA, keylen);
+                       match = 0;
+               }
+       }
+
+       /* we're dealing with a FIFO, so check wrapped around data */
+       matchend = match;
+       for (i = 0; match && i < keylen - match; i++) {
+               if (txf->buf[i] != keydata[match])
+                       break;
+               match++;
+               if (match == keylen) {
+                       memset(txf->buf, 0xAA, i + 1);
+                       memset(txf->buf + txf->buflen - matchend, 0xAA,
+                              matchend);
+                       break;
+               }
+       }
+}
+
+static void iwl_mvm_frob_txf(void *ctx, void *buf, size_t buflen)
+{
+       struct iwl_mvm_frob_txf_data txf = {
+               .buf = buf,
+               .buflen = buflen,
+       };
+       struct iwl_mvm *mvm = ctx;
+
+       /* embedded key material exists only on old API */
+       if (iwl_mvm_has_new_tx_api(mvm))
+               return;
+
+       rcu_read_lock();
+       ieee80211_iter_keys_rcu(mvm->hw, NULL, iwl_mvm_frob_txf_key_iter, &txf);
+       rcu_read_unlock();
+}
+
+static void iwl_mvm_frob_hcmd(void *ctx, void *hcmd, size_t len)
+{
+       /* we only use wide headers for commands */
+       struct iwl_cmd_header_wide *hdr = hcmd;
+       unsigned int frob_start = sizeof(*hdr), frob_end = 0;
+
+       if (len < sizeof(hdr))
+               return;
+
+       /* all the commands we care about are in LONG_GROUP */
+       if (hdr->group_id != LONG_GROUP)
+               return;
+
+       switch (hdr->cmd) {
+       case WEP_KEY:
+       case WOWLAN_TKIP_PARAM:
+       case WOWLAN_KEK_KCK_MATERIAL:
+       case ADD_STA_KEY:
+               /*
+                * blank out everything here, easier than dealing
+                * with the various versions of the command
+                */
+               frob_end = INT_MAX;
+               break;
+       case MGMT_MCAST_KEY:
+               frob_start = offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk);
+               BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) !=
+                            offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk));
+
+               frob_end = offsetofend(struct iwl_mvm_mgmt_mcast_key_cmd, igtk);
+               BUILD_BUG_ON(offsetof(struct iwl_mvm_mgmt_mcast_key_cmd, igtk) <
+                            offsetof(struct iwl_mvm_mgmt_mcast_key_cmd_v1, igtk));
+               break;
+       }
+
+       if (frob_start >= frob_end)
+               return;
+
+       if (frob_end > len)
+               frob_end = len;
+
+       memset((u8 *)hcmd + frob_start, 0xAA, frob_end - frob_start);
+}
+
+static void iwl_mvm_frob_mem(void *ctx, u32 mem_addr, void *mem, size_t buflen)
+{
+       const struct iwl_dump_exclude *excl;
+       struct iwl_mvm *mvm = ctx;
+       int i;
+
+       switch (mvm->fwrt.cur_fw_img) {
+       case IWL_UCODE_INIT:
+       default:
+               /* not relevant */
+               return;
+       case IWL_UCODE_REGULAR:
+       case IWL_UCODE_REGULAR_USNIFFER:
+               excl = mvm->fw->dump_excl;
+               break;
+       case IWL_UCODE_WOWLAN:
+               excl = mvm->fw->dump_excl_wowlan;
+               break;
+       }
+
+       BUILD_BUG_ON(sizeof(mvm->fw->dump_excl) !=
+                    sizeof(mvm->fw->dump_excl_wowlan));
+
+       for (i = 0; i < ARRAY_SIZE(mvm->fw->dump_excl); i++) {
+               u32 start, end;
+
+               if (!excl[i].addr || !excl[i].size)
+                       continue;
+
+               start = excl[i].addr;
+               end = start + excl[i].size;
+
+               if (end <= mem_addr || start >= mem_addr + buflen)
+                       continue;
+
+               if (start < mem_addr)
+                       start = mem_addr;
+
+               if (end > mem_addr + buflen)
+                       end = mem_addr + buflen;
+
+               memset((u8 *)mem + start - mem_addr, 0xAA, end - start);
+       }
+}
+
+static const struct iwl_dump_sanitize_ops iwl_mvm_sanitize_ops = {
+       .frob_txf = iwl_mvm_frob_txf,
+       .frob_hcmd = iwl_mvm_frob_hcmd,
+       .frob_mem = iwl_mvm_frob_mem,
+};
+
 static struct iwl_op_mode *
 iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
                      const struct iwl_fw *fw, struct dentry *dbgfs_dir)
@@ -775,7 +951,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        mvm->hw = hw;
 
        iwl_fw_runtime_init(&mvm->fwrt, trans, fw, &iwl_mvm_fwrt_ops, mvm,
-                           dbgfs_dir);
+                           &iwl_mvm_sanitize_ops, mvm, dbgfs_dir);
 
        iwl_mvm_get_acpi_tables(mvm);
 
@@ -868,8 +1044,8 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
        mvm->cmd_ver.range_resp =
                iwl_fw_lookup_notif_ver(mvm->fw, LOCATION_GROUP,
                                        TOF_RANGE_RESPONSE_NOTIF, 5);
-       /* we only support up to version 8 */
-       if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 8))
+       /* we only support up to version 9 */
+       if (WARN_ON_ONCE(mvm->cmd_ver.range_resp > 9))
                goto out_free;
 
        /*
index f2b090b..b2ea2fc 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
  * Copyright (C) 2013-2014 Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
@@ -128,6 +128,19 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
        enum ieee80211_ac_numbers ac;
        bool tid_found = false;
 
+       if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ||
+           cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
+               cmd->rx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
+               cmd->tx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
+       } else {
+               cmd->rx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
+               cmd->tx_data_timeout_uapsd =
+                       cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
+       }
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
        /* set advanced pm flag with no uapsd ACs to enable ps-poll */
        if (mvmvif->dbgfs_pm.use_ps_poll) {
@@ -182,19 +195,6 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
 
        cmd->uapsd_max_sp = mvm->hw->uapsd_max_sp_len;
 
-       if (test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status) ||
-           cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
-               cmd->rx_data_timeout_uapsd =
-                       cpu_to_le32(IWL_MVM_WOWLAN_PS_RX_DATA_TIMEOUT);
-               cmd->tx_data_timeout_uapsd =
-                       cpu_to_le32(IWL_MVM_WOWLAN_PS_TX_DATA_TIMEOUT);
-       } else {
-               cmd->rx_data_timeout_uapsd =
-                       cpu_to_le32(IWL_MVM_UAPSD_RX_DATA_TIMEOUT);
-               cmd->tx_data_timeout_uapsd =
-                       cpu_to_le32(IWL_MVM_UAPSD_TX_DATA_TIMEOUT);
-       }
-
        if (cmd->flags & cpu_to_le16(POWER_FLAGS_SNOOZE_ENA_MSK)) {
                cmd->heavy_tx_thld_packets =
                        IWL_MVM_PS_SNOOZE_HEAVY_TX_THLD_PACKETS;
index 2d58cb9..9587024 100644 (file)
@@ -32,10 +32,6 @@ static u8 rs_fw_set_active_chains(u8 chains)
                fw_chains |= IWL_TLC_MNG_CHAIN_A_MSK;
        if (chains & ANT_B)
                fw_chains |= IWL_TLC_MNG_CHAIN_B_MSK;
-       if (chains & ANT_C)
-               WARN(false,
-                    "tlc offload doesn't support antenna C. chains: 0x%x\n",
-                    chains);
 
        return fw_chains;
 }
@@ -314,7 +310,19 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm,
 
        if (flags & IWL_TLC_NOTIF_FLAG_RATE) {
                char pretty_rate[100];
+
+       if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
+                                   TLC_MNG_UPDATE_NOTIF, 0) < 3) {
+               rs_pretty_print_rate_v1(pretty_rate, sizeof(pretty_rate),
+                                       le32_to_cpu(notif->rate));
+               IWL_DEBUG_RATE(mvm,
+                              "Got rate in old format. Rate: %s. Converting.\n",
+                              pretty_rate);
+               lq_sta->last_rate_n_flags =
+                       iwl_new_rate_from_v1(le32_to_cpu(notif->rate));
+       } else {
                lq_sta->last_rate_n_flags = le32_to_cpu(notif->rate);
+       }
                rs_pretty_print_rate(pretty_rate, sizeof(pretty_rate),
                                     lq_sta->last_rate_n_flags);
                IWL_DEBUG_RATE(mvm, "new rate: %s\n", pretty_rate);
index b97708c..f4d02f9 100644 (file)
@@ -4,11 +4,6 @@
  * Copyright(c) 2005 - 2014, 2018 - 2021 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 #include <linux/kernel.h>
 #include <linux/skbuff.h>
@@ -335,15 +330,15 @@ static const struct rs_tx_column rs_tx_columns[] = {
 static inline u8 rs_extract_rate(u32 rate_n_flags)
 {
        /* also works for HT because bits 7:6 are zero there */
-       return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK);
+       return (u8)(rate_n_flags & RATE_LEGACY_RATE_MSK_V1);
 }
 
 static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
 {
        int idx = 0;
 
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK;
+       if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
+               idx = rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1;
                idx += IWL_RATE_MCS_0_INDEX;
 
                /* skip 9M not supported in HT*/
@@ -351,8 +346,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
                        idx += 1;
                if ((idx >= IWL_FIRST_HT_RATE) && (idx <= IWL_LAST_HT_RATE))
                        return idx;
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK ||
-                  rate_n_flags & RATE_MCS_HE_MSK) {
+       } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1 ||
+                  rate_n_flags & RATE_MCS_HE_MSK_V1) {
                idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
                idx += IWL_RATE_MCS_0_INDEX;
 
@@ -361,8 +356,8 @@ static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
                        idx++;
                if ((idx >= IWL_FIRST_VHT_RATE) && (idx <= IWL_LAST_VHT_RATE))
                        return idx;
-               if ((rate_n_flags & RATE_MCS_HE_MSK) &&
-                   (idx <= IWL_LAST_HE_RATE))
+               if ((rate_n_flags & RATE_MCS_HE_MSK_V1) &&
+                   idx <= IWL_LAST_HE_RATE)
                        return idx;
        } else {
                /* legacy rate format, search for match in table */
@@ -459,44 +454,8 @@ static const u16 expected_tpt_mimo2_160MHz[4][IWL_RATE_COUNT] = {
        {0, 0, 0, 0, 971, 0, 1925, 2861, 3779, 5574, 7304, 8147, 8976, 10592, 11640},
 };
 
-/* mbps, mcs */
-static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
-       {  "1", "BPSK DSSS"},
-       {  "2", "QPSK DSSS"},
-       {"5.5", "BPSK CCK"},
-       { "11", "QPSK CCK"},
-       {  "6", "BPSK 1/2"},
-       {  "9", "BPSK 1/2"},
-       { "12", "QPSK 1/2"},
-       { "18", "QPSK 3/4"},
-       { "24", "16QAM 1/2"},
-       { "36", "16QAM 3/4"},
-       { "48", "64QAM 2/3"},
-       { "54", "64QAM 3/4"},
-       { "60", "64QAM 5/6"},
-};
-
 #define MCS_INDEX_PER_STREAM   (8)
 
-static const char *rs_pretty_ant(u8 ant)
-{
-       static const char * const ant_name[] = {
-               [ANT_NONE] = "None",
-               [ANT_A]    = "A",
-               [ANT_B]    = "B",
-               [ANT_AB]   = "AB",
-               [ANT_C]    = "C",
-               [ANT_AC]   = "AC",
-               [ANT_BC]   = "BC",
-               [ANT_ABC]  = "ABC",
-       };
-
-       if (ant > ANT_ABC)
-               return "UNKNOWN";
-
-       return ant_name[ant];
-}
-
 static const char *rs_pretty_lq_type(enum iwl_table_type type)
 {
        static const char * const lq_types[] = {
@@ -558,7 +517,7 @@ static char *rs_pretty_rate(const struct rs_rate *rate)
                rate_str = "BAD_RATE";
 
        sprintf(buf, "(%s|%s|%s)", rs_pretty_lq_type(rate->type),
-               rs_pretty_ant(rate->ant), rate_str);
+               iwl_rs_pretty_ant(rate->ant), rate_str);
        return buf;
 }
 
@@ -654,8 +613,7 @@ static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
 static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
 {
        return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) +
-              !!(rate_n_flags & RATE_MCS_ANT_B_MSK) +
-              !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
+              !!(rate_n_flags & RATE_MCS_ANT_B_MSK);
 }
 
 /*
@@ -820,12 +778,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
        int index = rate->index;
 
        ucode_rate |= ((rate->ant << RATE_MCS_ANT_POS) &
-                        RATE_MCS_ANT_ABC_MSK);
+                        RATE_MCS_ANT_AB_MSK);
 
        if (is_legacy(rate)) {
                ucode_rate |= iwl_rates[index].plcp;
                if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
-                       ucode_rate |= RATE_MCS_CCK_MSK;
+                       ucode_rate |= RATE_MCS_CCK_MSK_V1;
                return ucode_rate;
        }
 
@@ -840,7 +798,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
                        IWL_ERR(mvm, "Invalid HT rate index %d\n", index);
                        index = IWL_LAST_HT_RATE;
                }
-               ucode_rate |= RATE_MCS_HT_MSK;
+               ucode_rate |= RATE_MCS_HT_MSK_V1;
 
                if (is_ht_siso(rate))
                        ucode_rate |= iwl_rates[index].plcp_ht_siso;
@@ -853,7 +811,7 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
                        IWL_ERR(mvm, "Invalid VHT rate index %d\n", index);
                        index = IWL_LAST_VHT_RATE;
                }
-               ucode_rate |= RATE_MCS_VHT_MSK;
+               ucode_rate |= RATE_MCS_VHT_MSK_V1;
                if (is_vht_siso(rate))
                        ucode_rate |= iwl_rates[index].plcp_vht_siso;
                else if (is_vht_mimo2(rate))
@@ -873,9 +831,9 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
 
        ucode_rate |= rate->bw;
        if (rate->sgi)
-               ucode_rate |= RATE_MCS_SGI_MSK;
+               ucode_rate |= RATE_MCS_SGI_MSK_V1;
        if (rate->ldpc)
-               ucode_rate |= RATE_MCS_LDPC_MSK;
+               ucode_rate |= RATE_MCS_LDPC_MSK_V1;
 
        return ucode_rate;
 }
@@ -885,7 +843,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
                                   enum nl80211_band band,
                                   struct rs_rate *rate)
 {
-       u32 ant_msk = ucode_rate & RATE_MCS_ANT_ABC_MSK;
+       u32 ant_msk = ucode_rate & RATE_MCS_ANT_AB_MSK;
        u8 num_of_ant = get_num_of_ant_from_rate(ucode_rate);
        u8 nss;
 
@@ -898,9 +856,9 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
        rate->ant = (ant_msk >> RATE_MCS_ANT_POS);
 
        /* Legacy */
-       if (!(ucode_rate & RATE_MCS_HT_MSK) &&
-           !(ucode_rate & RATE_MCS_VHT_MSK) &&
-           !(ucode_rate & RATE_MCS_HE_MSK)) {
+       if (!(ucode_rate & RATE_MCS_HT_MSK_V1) &&
+           !(ucode_rate & RATE_MCS_VHT_MSK_V1) &&
+           !(ucode_rate & RATE_MCS_HE_MSK_V1)) {
                if (num_of_ant == 1) {
                        if (band == NL80211_BAND_5GHZ)
                                rate->type = LQ_LEGACY_A;
@@ -912,20 +870,20 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
        }
 
        /* HT, VHT or HE */
-       if (ucode_rate & RATE_MCS_SGI_MSK)
+       if (ucode_rate & RATE_MCS_SGI_MSK_V1)
                rate->sgi = true;
-       if (ucode_rate & RATE_MCS_LDPC_MSK)
+       if (ucode_rate & RATE_MCS_LDPC_MSK_V1)
                rate->ldpc = true;
        if (ucode_rate & RATE_MCS_STBC_MSK)
                rate->stbc = true;
        if (ucode_rate & RATE_MCS_BF_MSK)
                rate->bfer = true;
 
-       rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
+       rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK_V1;
 
-       if (ucode_rate & RATE_MCS_HT_MSK) {
-               nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK) >>
-                      RATE_HT_MCS_NSS_POS) + 1;
+       if (ucode_rate & RATE_MCS_HT_MSK_V1) {
+               nss = ((ucode_rate & RATE_HT_MCS_NSS_MSK_V1) >>
+                      RATE_HT_MCS_NSS_POS_V1) + 1;
 
                if (nss == 1) {
                        rate->type = LQ_HT_SISO;
@@ -938,7 +896,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
                } else {
                        WARN_ON_ONCE(1);
                }
-       } else if (ucode_rate & RATE_MCS_VHT_MSK) {
+       } else if (ucode_rate & RATE_MCS_VHT_MSK_V1) {
                nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>
                       RATE_VHT_MCS_NSS_POS) + 1;
 
@@ -953,7 +911,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
                } else {
                        WARN_ON_ONCE(1);
                }
-       } else if (ucode_rate & RATE_MCS_HE_MSK) {
+       } else if (ucode_rate & RATE_MCS_HE_MSK_V1) {
                nss = ((ucode_rate & RATE_VHT_MCS_NSS_MSK) >>
                      RATE_VHT_MCS_NSS_POS) + 1;
 
@@ -981,9 +939,6 @@ static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate)
 {
        u8 new_ant_type;
 
-       if (!rate->ant || WARN_ON_ONCE(rate->ant & ANT_C))
-               return 0;
-
        if (!rs_is_valid_ant(valid_ant, rate->ant))
                return 0;
 
@@ -2552,7 +2507,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
        }
 
        IWL_DEBUG_RATE(mvm, "Best ANT: %s Best RSSI: %d\n",
-                      rs_pretty_ant(best_ant), best_rssi);
+                      iwl_rs_pretty_ant(best_ant), best_rssi);
 
        if (best_ant != ANT_A && best_ant != ANT_B)
                rate->ant = first_antenna(valid_tx_ant);
@@ -2652,7 +2607,6 @@ void rs_update_last_rssi(struct iwl_mvm *mvm,
        lq_sta->pers.chains = rx_status->chains;
        lq_sta->pers.chain_signal[0] = rx_status->chain_signal[0];
        lq_sta->pers.chain_signal[1] = rx_status->chain_signal[1];
-       lq_sta->pers.chain_signal[2] = rx_status->chain_signal[2];
        lq_sta->pers.last_rssi = S8_MIN;
 
        for (i = 0; i < ARRAY_SIZE(lq_sta->pers.chain_signal); i++) {
@@ -2738,8 +2692,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
                return;
 
        lq_sta = mvm_sta;
-       iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags,
-                                 info->band, &info->control.rates[0]);
+       iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags,
+                                    info->band, &info->control.rates[0]);
        info->control.rates[0].count = 1;
 
        /* Report the optimal rate based on rssi and STA caps if we haven't
@@ -2749,8 +2703,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
                optimal_rate = rs_get_optimal_rate(mvm, lq_sta);
                last_ucode_rate = ucode_rate_from_rs_rate(mvm,
                                                          optimal_rate);
-               iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, info->band,
-                                         &txrc->reported_rate);
+               iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band,
+                                            &txrc->reported_rate);
        }
 }
 
@@ -2909,7 +2863,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
 
        mvm->drv_rx_stats.success_frames++;
 
-       switch (rate & RATE_MCS_CHAN_WIDTH_MSK) {
+       switch (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) {
        case RATE_MCS_CHAN_WIDTH_20:
                mvm->drv_rx_stats.bw_20_frames++;
                break;
@@ -2926,10 +2880,10 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
                WARN_ONCE(1, "bad BW. rate 0x%x", rate);
        }
 
-       if (rate & RATE_MCS_HT_MSK) {
+       if (rate & RATE_MCS_HT_MSK_V1) {
                mvm->drv_rx_stats.ht_frames++;
-               nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1;
-       } else if (rate & RATE_MCS_VHT_MSK) {
+               nss = ((rate & RATE_HT_MCS_NSS_MSK_V1) >> RATE_HT_MCS_NSS_POS_V1) + 1;
+       } else if (rate & RATE_MCS_VHT_MSK_V1) {
                mvm->drv_rx_stats.vht_frames++;
                nss = ((rate & RATE_VHT_MCS_NSS_MSK) >>
                       RATE_VHT_MCS_NSS_POS) + 1;
@@ -2942,7 +2896,7 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
        else if (nss == 2)
                mvm->drv_rx_stats.mimo2_frames++;
 
-       if (rate & RATE_MCS_SGI_MSK)
+       if (rate & RATE_MCS_SGI_MSK_V1)
                mvm->drv_rx_stats.sgi_frames++;
        else
                mvm->drv_rx_stats.ngi_frames++;
@@ -3323,7 +3277,7 @@ static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
        int i;
        int num_rates = ARRAY_SIZE(lq_cmd->rs_table);
        __le32 ucode_rate_le32 = cpu_to_le32(ucode_rate);
-       u8 ant = (ucode_rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS;
+       u8 ant = (ucode_rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
 
        for (i = 0; i < num_rates; i++)
                lq_cmd->rs_table[i] = ucode_rate_le32;
@@ -3688,35 +3642,37 @@ static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta)
        IWL_DEBUG_RATE(mvm, "leave\n");
 }
 
-int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
+int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)
 {
 
-       char *type, *bw;
+       char *type;
        u8 mcs = 0, nss = 0;
-       u8 ant = (rate & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS;
+       u8 ant = (rate & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
+       u32 bw = (rate & RATE_MCS_CHAN_WIDTH_MSK_V1) >>
+               RATE_MCS_CHAN_WIDTH_POS;
 
-       if (!(rate & RATE_MCS_HT_MSK) &&
-           !(rate & RATE_MCS_VHT_MSK) &&
-           !(rate & RATE_MCS_HE_MSK)) {
+       if (!(rate & RATE_MCS_HT_MSK_V1) &&
+           !(rate & RATE_MCS_VHT_MSK_V1) &&
+           !(rate & RATE_MCS_HE_MSK_V1)) {
                int index = iwl_hwrate_to_plcp_idx(rate);
 
                return scnprintf(buf, bufsz, "Legacy | ANT: %s Rate: %s Mbps",
-                                rs_pretty_ant(ant),
+                                iwl_rs_pretty_ant(ant),
                                 index == IWL_RATE_INVALID ? "BAD" :
-                                iwl_rate_mcs[index].mbps);
+                                iwl_rate_mcs(index)->mbps);
        }
 
-       if (rate & RATE_MCS_VHT_MSK) {
+       if (rate & RATE_MCS_VHT_MSK_V1) {
                type = "VHT";
                mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
                nss = ((rate & RATE_VHT_MCS_NSS_MSK)
                       >> RATE_VHT_MCS_NSS_POS) + 1;
-       } else if (rate & RATE_MCS_HT_MSK) {
+       } else if (rate & RATE_MCS_HT_MSK_V1) {
                type = "HT";
-               mcs = rate & RATE_HT_MCS_INDEX_MSK;
-               nss = ((rate & RATE_HT_MCS_NSS_MSK)
-                      >> RATE_HT_MCS_NSS_POS) + 1;
-       } else if (rate & RATE_MCS_HE_MSK) {
+               mcs = rate & RATE_HT_MCS_INDEX_MSK_V1;
+               nss = ((rate & RATE_HT_MCS_NSS_MSK_V1)
+                      >> RATE_HT_MCS_NSS_POS_V1) + 1;
+       } else if (rate & RATE_MCS_HE_MSK_V1) {
                type = "HE";
                mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
                nss = ((rate & RATE_VHT_MCS_NSS_MSK)
@@ -3725,29 +3681,12 @@ int rs_pretty_print_rate(char *buf, int bufsz, const u32 rate)
                type = "Unknown"; /* shouldn't happen */
        }
 
-       switch (rate & RATE_MCS_CHAN_WIDTH_MSK) {
-       case RATE_MCS_CHAN_WIDTH_20:
-               bw = "20Mhz";
-               break;
-       case RATE_MCS_CHAN_WIDTH_40:
-               bw = "40Mhz";
-               break;
-       case RATE_MCS_CHAN_WIDTH_80:
-               bw = "80Mhz";
-               break;
-       case RATE_MCS_CHAN_WIDTH_160:
-               bw = "160Mhz";
-               break;
-       default:
-               bw = "BAD BW";
-       }
-
        return scnprintf(buf, bufsz,
                         "0x%x: %s | ANT: %s BW: %s MCS: %d NSS: %d %s%s%s%s%s",
-                        rate, type, rs_pretty_ant(ant), bw, mcs, nss,
-                        (rate & RATE_MCS_SGI_MSK) ? "SGI " : "NGI ",
+                        rate, type, iwl_rs_pretty_ant(ant), iwl_rs_pretty_bw(bw), mcs, nss,
+                        (rate & RATE_MCS_SGI_MSK_V1) ? "SGI " : "NGI ",
                         (rate & RATE_MCS_STBC_MSK) ? "STBC " : "",
-                        (rate & RATE_MCS_LDPC_MSK) ? "LDPC " : "",
+                        (rate & RATE_MCS_LDPC_MSK_V1) ? "LDPC " : "",
                         (rate & RATE_HE_DUAL_CARRIER_MODE_MSK) ? "DCM " : "",
                         (rate & RATE_MCS_BF_MSK) ? "BF " : "");
 }
@@ -3830,10 +3769,9 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
                          lq_sta->active_legacy_rate);
        desc += scnprintf(buff + desc, bufsz - desc, "fixed rate 0x%X\n",
                          lq_sta->pers.dbg_fixed_rate);
-       desc += scnprintf(buff + desc, bufsz - desc, "valid_tx_ant %s%s%s\n",
+       desc += scnprintf(buff + desc, bufsz - desc, "valid_tx_ant %s%s\n",
            (iwl_mvm_get_valid_tx_ant(mvm) & ANT_A) ? "ANT_A," : "",
-           (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "",
-           (iwl_mvm_get_valid_tx_ant(mvm) & ANT_C) ? "ANT_C" : "");
+           (iwl_mvm_get_valid_tx_ant(mvm) & ANT_B) ? "ANT_B," : "");
        desc += scnprintf(buff + desc, bufsz - desc, "lq type %s\n",
                          (is_legacy(rate)) ? "legacy" :
                          is_vht(rate) ? "VHT" : "HT");
@@ -3891,7 +3829,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 
                desc += scnprintf(buff + desc, bufsz - desc,
                                  " rate[%d] 0x%X ", i, r);
-               desc += rs_pretty_print_rate(buff + desc, bufsz - desc, r);
+               desc += rs_pretty_print_rate_v1(buff + desc, bufsz - desc, r);
                if (desc < bufsz - 1)
                        buff[desc++] = '\n';
        }
index 32104c9..b7bc8c1 100644 (file)
@@ -5,11 +5,6 @@
  * Copyright(c) 2015 Intel Mobile Communications GmbH
  * Copyright(c) 2017 Intel Deutschland GmbH
  * Copyright(c) 2018 - 2019 Intel Corporation
- *
- * Contact Information:
- *  Intel Linux Wireless <linuxwifi@intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
  *****************************************************************************/
 
 #ifndef __rs_h__
@@ -36,11 +31,6 @@ struct iwl_rs_rate_info {
 
 #define IWL_RATE_60M_PLCP 3
 
-enum {
-       IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
-       IWL_RATE_INVALID = IWL_RATE_COUNT,
-};
-
 #define LINK_QUAL_MAX_RETRY_NUM 16
 
 enum {
@@ -211,13 +201,6 @@ struct rs_rate {
 #define is_ht80(rate)         ((rate)->bw == RATE_MCS_CHAN_WIDTH_80)
 #define is_ht160(rate)        ((rate)->bw == RATE_MCS_CHAN_WIDTH_160)
 
-#define IWL_MAX_MCS_DISPLAY_SIZE       12
-
-struct iwl_rate_mcs_info {
-       char    mbps[IWL_MAX_MCS_DISPLAY_SIZE];
-       char    mcs[IWL_MAX_MCS_DISPLAY_SIZE];
-};
-
 /**
  * struct iwl_lq_sta_rs_fw - rate and related statistics for RS in FW
  * @last_rate_n_flags: last rate reported by FW
index 8ef5399..d22f40a 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2012-2014, 2018-2020 Intel Corporation
+ * Copyright (C) 2012-2014, 2018-2021 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -103,7 +103,7 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
                                        struct iwl_rx_phy_info *phy_info,
                                        struct ieee80211_rx_status *rx_status)
 {
-       int energy_a, energy_b, energy_c, max_energy;
+       int energy_a, energy_b, max_energy;
        u32 val;
 
        val =
@@ -114,14 +114,10 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
        energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >>
                                                IWL_RX_INFO_ENERGY_ANT_B_POS;
        energy_b = energy_b ? -energy_b : S8_MIN;
-       energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >>
-                                               IWL_RX_INFO_ENERGY_ANT_C_POS;
-       energy_c = energy_c ? -energy_c : S8_MIN;
        max_energy = max(energy_a, energy_b);
-       max_energy = max(max_energy, energy_c);
 
-       IWL_DEBUG_STATS(mvm, "energy In A %d B %d C %d , and max %d\n",
-                       energy_a, energy_b, energy_c, max_energy);
+       IWL_DEBUG_STATS(mvm, "energy In A %d B %d  , and max %d\n",
+                       energy_a, energy_b, max_energy);
 
        rx_status->signal = max_energy;
        rx_status->chains = (le16_to_cpu(phy_info->phy_flags) &
@@ -129,7 +125,6 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
                                        >> RX_RES_PHY_FLAGS_ANTENNA_POS;
        rx_status->chain_signal[0] = energy_a;
        rx_status->chain_signal[1] = energy_b;
-       rx_status->chain_signal[2] = energy_c;
 }
 
 /*
@@ -235,7 +230,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
                mdata->rx.airtime += le16_to_cpu(phy_info->frame_time);
        }
 
-       if (!(rate_n_flags & (RATE_MCS_HT_MSK | RATE_MCS_VHT_MSK)))
+       if (!(rate_n_flags & (RATE_MCS_HT_MSK_V1 | RATE_MCS_VHT_MSK_V1)))
                return;
 
        mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
@@ -249,10 +244,10 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
            mvmsta->sta_id != mvmvif->ap_sta_id)
                return;
 
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
-               thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK];
-               thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK) >>
-                                       RATE_HT_MCS_NSS_POS);
+       if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
+               thr = thresh_tpt[rate_n_flags & RATE_HT_MCS_RATE_CODE_MSK_V1];
+               thr *= 1 + ((rate_n_flags & RATE_HT_MCS_NSS_MSK_V1) >>
+                                       RATE_HT_MCS_NSS_POS_V1);
        } else {
                if (WARN_ON((rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK) >=
                                ARRAY_SIZE(thresh_tpt)))
@@ -262,7 +257,7 @@ static void iwl_mvm_rx_handle_tcm(struct iwl_mvm *mvm,
                                        RATE_VHT_MCS_NSS_POS);
        }
 
-       thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) >>
+       thr <<= ((rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) >>
                                RATE_MCS_CHAN_WIDTH_POS);
 
        mdata->uapsd_nonagg_detect.rx_bytes += len;
@@ -455,7 +450,7 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
        }
 
        /* Set up the HT phy flags */
-       switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
+       switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) {
        case RATE_MCS_CHAN_WIDTH_20:
                break;
        case RATE_MCS_CHAN_WIDTH_40:
@@ -468,20 +463,20 @@ void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
                rx_status->bw = RATE_INFO_BW_160;
                break;
        }
-       if (!(rate_n_flags & RATE_MCS_CCK_MSK) &&
-           rate_n_flags & RATE_MCS_SGI_MSK)
+       if (!(rate_n_flags & RATE_MCS_CCK_MSK_V1) &&
+           rate_n_flags & RATE_MCS_SGI_MSK_V1)
                rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
        if (rate_n_flags & RATE_HT_MCS_GF_MSK)
                rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;
-       if (rate_n_flags & RATE_MCS_LDPC_MSK)
+       if (rate_n_flags & RATE_MCS_LDPC_MSK_V1)
                rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
+       if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
                u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
                                RATE_MCS_STBC_POS;
                rx_status->encoding = RX_ENC_HT;
-               rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+               rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1;
                rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
+       } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {
                u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
                                RATE_MCS_STBC_POS;
                rx_status->nss =
index c12f303..e0601f8 100644 (file)
@@ -240,8 +240,7 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
 static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
                                            struct napi_struct *napi,
                                            struct sk_buff *skb, int queue,
-                                           struct ieee80211_sta *sta,
-                                           bool csi)
+                                           struct ieee80211_sta *sta)
 {
        if (iwl_mvm_check_pn(mvm, skb, queue, sta))
                kfree_skb(skb);
@@ -269,7 +268,6 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm,
                (rate_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS;
        rx_status->chain_signal[0] = energy_a;
        rx_status->chain_signal[1] = energy_b;
-       rx_status->chain_signal[2] = S8_MIN;
 }
 
 static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
@@ -620,7 +618,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
                while ((skb = __skb_dequeue(skb_list))) {
                        iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
                                                        reorder_buf->queue,
-                                                       sta, false);
+                                                       sta);
                        reorder_buf->num_stored--;
                }
        }
@@ -1198,7 +1196,7 @@ static void iwl_mvm_decode_he_mu_ext(struct iwl_mvm *mvm,
        }
 
        if (FIELD_GET(IWL_RX_PHY_DATA4_HE_MU_EXT_CH2_CRC_OK, phy_data4) &&
-           (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) != RATE_MCS_CHAN_WIDTH_20) {
+           (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) != RATE_MCS_CHAN_WIDTH_20) {
                he_mu->flags1 |=
                        cpu_to_le16(IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_RU_KNOWN |
                                    IEEE80211_RADIOTAP_HE_MU_FLAGS1_CH2_CTR_26T_RU_KNOWN);
@@ -1235,7 +1233,7 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
         * the TSF/timers are not be transmitted in HE-MU.
         */
        u8 ru = le32_get_bits(phy_data->d1, IWL_RX_PHY_DATA1_HE_RU_ALLOC_MASK);
-       u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK;
+       u32 he_type = rate_n_flags & RATE_MCS_HE_TYPE_MSK_V1;
        u8 offs = 0;
 
        rx_status->bw = RATE_INFO_BW_HE_RU;
@@ -1290,13 +1288,13 @@ iwl_mvm_decode_he_phy_ru_alloc(struct iwl_mvm_rx_phy_data *phy_data,
 
        if (he_mu)
                he_mu->flags2 |=
-                       le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
+                       le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1,
                                                   rate_n_flags),
                                         IEEE80211_RADIOTAP_HE_MU_FLAGS2_BW_FROM_SIG_A_BW);
-       else if (he_type == RATE_MCS_HE_TYPE_TRIG)
+       else if (he_type == RATE_MCS_HE_TYPE_TRIG_V1)
                he->data6 |=
                        cpu_to_le16(IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW_KNOWN) |
-                       le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK,
+                       le16_encode_bits(FIELD_GET(RATE_MCS_CHAN_WIDTH_MSK_V1,
                                                   rate_n_flags),
                                         IEEE80211_RADIOTAP_HE_DATA6_TB_PPDU_BW);
 }
@@ -1508,9 +1506,9 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
 
        stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >> RATE_MCS_STBC_POS;
        rx_status->nss =
-               ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
-                                       RATE_VHT_MCS_NSS_POS) + 1;
-       rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
+               ((rate_n_flags & RATE_MCS_NSS_MSK) >>
+                RATE_MCS_NSS_POS) + 1;
+       rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
        rx_status->encoding = RX_ENC_HE;
        rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
        if (rate_n_flags & RATE_MCS_BF_MSK)
@@ -1562,14 +1560,15 @@ static void iwl_mvm_rx_he(struct iwl_mvm *mvm, struct sk_buff *skb,
                }
                break;
        case 3:
-               if ((he_type == RATE_MCS_HE_TYPE_SU ||
-                    he_type == RATE_MCS_HE_TYPE_EXT_SU) &&
-                   rate_n_flags & RATE_MCS_SGI_MSK)
-                       rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
-               else
-                       rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
+               rx_status->he_gi = NL80211_RATE_INFO_HE_GI_3_2;
                ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
                break;
+       case 4:
+               rx_status->he_gi = NL80211_RATE_INFO_HE_GI_0_8;
+               ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_4X;
+               break;
+       default:
+               ltf = IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE_UNKNOWN;
        }
 
        he->data5 |= le16_encode_bits(ltf,
@@ -1653,7 +1652,8 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
        struct iwl_mvm_rx_phy_data phy_data = {
                .info_type = IWL_RX_PHY_INFO_TYPE_NONE,
        };
-       bool csi = false;
+       u32 format;
+       bool is_sgi;
 
        if (unlikely(test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)))
                return;
@@ -1691,6 +1691,13 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                phy_data.d2 = desc->v1.phy_data2;
                phy_data.d3 = desc->v1.phy_data3;
        }
+       if (iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,
+                                   REPLY_RX_MPDU_CMD, 0) < 4) {
+               rate_n_flags = iwl_new_rate_from_v1(rate_n_flags);
+               IWL_DEBUG_DROP(mvm, "Got old format rate, converting. New rate: 0x%x\n",
+                              rate_n_flags);
+       }
+       format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
 
        len = le16_to_cpu(desc->mpdu_len);
 
@@ -1744,7 +1751,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                break;
        }
 
-       if (rate_n_flags & RATE_MCS_HE_MSK)
+       if (format == RATE_MCS_HE_MSK)
                iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags,
                              phy_info, queue);
 
@@ -1761,7 +1768,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
        }
        /* set the preamble flag if appropriate */
-       if (rate_n_flags & RATE_MCS_CCK_MSK &&
+       if (format == RATE_MCS_CCK_MSK &&
            phy_info & IWL_RX_MPDU_PHY_SHORT_PREAMBLE)
                rx_status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
 
@@ -1937,33 +1944,34 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
                }
        }
 
-       if (!(rate_n_flags & RATE_MCS_CCK_MSK) &&
-           rate_n_flags & RATE_MCS_SGI_MSK)
+       is_sgi = format == RATE_MCS_HE_MSK ?
+               iwl_he_is_sgi(rate_n_flags) :
+               rate_n_flags & RATE_MCS_SGI_MSK;
+
+       if (!(format == RATE_MCS_CCK_MSK) && is_sgi)
                rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-       if (rate_n_flags & RATE_HT_MCS_GF_MSK)
-               rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;
        if (rate_n_flags & RATE_MCS_LDPC_MSK)
                rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
+       if (format == RATE_MCS_HT_MSK) {
                u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
-                               RATE_MCS_STBC_POS;
+                       RATE_MCS_STBC_POS;
                rx_status->encoding = RX_ENC_HT;
-               rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+               rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);
                rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
+       } else if (format == RATE_MCS_VHT_MSK) {
                u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
-                               RATE_MCS_STBC_POS;
-               rx_status->nss =
-                       ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
-                                               RATE_VHT_MCS_NSS_POS) + 1;
-               rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
+                       RATE_MCS_STBC_POS;
+                       rx_status->nss =
+                       ((rate_n_flags & RATE_MCS_NSS_MSK) >>
+                       RATE_MCS_NSS_POS) + 1;
+               rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
                rx_status->encoding = RX_ENC_VHT;
                rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
                if (rate_n_flags & RATE_MCS_BF_MSK)
                        rx_status->enc_flags |= RX_ENC_FLAG_BF;
-       } else if (!(rate_n_flags & RATE_MCS_HE_MSK)) {
-               int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
-                                                              rx_status->band);
+       } else if (!(format == RATE_MCS_HE_MSK)) {
+               int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
+                                                                rx_status->band);
 
                if (WARN(rate < 0 || rate > 0xFF,
                         "Invalid rate flags 0x%x, band %d,\n",
@@ -1994,7 +2002,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
 
        if (!iwl_mvm_reorder(mvm, napi, queue, sta, skb, desc))
                iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue,
-                                               sta, csi);
+                                               sta);
 out:
        rcu_read_unlock();
 }
@@ -2013,12 +2021,24 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
        struct ieee80211_sta *sta = NULL;
        struct sk_buff *skb;
        u8 channel, energy_a, energy_b;
+       u32 format;
        struct iwl_mvm_rx_phy_data phy_data = {
                .info_type = le32_get_bits(desc->phy_info[1],
                                           IWL_RX_PHY_DATA1_INFO_TYPE_MASK),
                .d0 = desc->phy_info[0],
                .d1 = desc->phy_info[1],
        };
+       bool is_sgi;
+
+       if (iwl_fw_lookup_notif_ver(mvm->fw, DATA_PATH_GROUP,
+                                   RX_NO_DATA_NOTIF, 0) < 2) {
+               IWL_DEBUG_DROP(mvm, "Got an old rate format. Old rate: 0x%x\n",
+                              rate_n_flags);
+               rate_n_flags = iwl_new_rate_from_v1(rate_n_flags);
+               IWL_DEBUG_DROP(mvm, " Rate after conversion to the new format: 0x%x\n",
+                              rate_n_flags);
+       }
+       format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
 
        if (unlikely(iwl_rx_packet_payload_len(pkt) < sizeof(*desc)))
                return;
@@ -2075,7 +2095,7 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
                break;
        }
 
-       if (rate_n_flags & RATE_MCS_HE_MSK)
+       if (format == RATE_MCS_HE_MSK)
                iwl_mvm_rx_he(mvm, skb, &phy_data, rate_n_flags,
                              phy_info, queue);
 
@@ -2091,23 +2111,24 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
 
        rcu_read_lock();
 
-       if (!(rate_n_flags & RATE_MCS_CCK_MSK) &&
-           rate_n_flags & RATE_MCS_SGI_MSK)
+       is_sgi = format == RATE_MCS_HE_MSK ?
+               iwl_he_is_sgi(rate_n_flags) :
+               rate_n_flags & RATE_MCS_SGI_MSK;
+
+       if (!(format == RATE_MCS_CCK_MSK) && is_sgi)
                rx_status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-       if (rate_n_flags & RATE_HT_MCS_GF_MSK)
-               rx_status->enc_flags |= RX_ENC_FLAG_HT_GF;
        if (rate_n_flags & RATE_MCS_LDPC_MSK)
                rx_status->enc_flags |= RX_ENC_FLAG_LDPC;
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
+       if (format == RATE_MCS_HT_MSK) {
                u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
                                RATE_MCS_STBC_POS;
                rx_status->encoding = RX_ENC_HT;
-               rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+               rx_status->rate_idx = RATE_HT_MCS_INDEX(rate_n_flags);
                rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
+       } else if (format == RATE_MCS_VHT_MSK) {
                u8 stbc = (rate_n_flags & RATE_MCS_STBC_MSK) >>
                                RATE_MCS_STBC_POS;
-               rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
+               rx_status->rate_idx = rate_n_flags & RATE_MCS_CODE_MSK;
                rx_status->encoding = RX_ENC_VHT;
                rx_status->enc_flags |= stbc << RX_ENC_FLAG_STBC_SHIFT;
                if (rate_n_flags & RATE_MCS_BF_MSK)
@@ -2120,12 +2141,12 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,
                rx_status->nss =
                        le32_get_bits(desc->rx_vec[0],
                                      RX_NO_DATA_RX_VEC0_VHT_NSTS_MSK) + 1;
-       } else if (rate_n_flags & RATE_MCS_HE_MSK) {
+       } else if (format == RATE_MCS_HE_MSK) {
                rx_status->nss =
                        le32_get_bits(desc->rx_vec[0],
                                      RX_NO_DATA_RX_VEC0_HE_NSTS_MSK) + 1;
        } else {
-               int rate = iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
+               int rate = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
                                                               rx_status->band);
 
                if (WARN(rate < 0 || rate > 0xFF,
index d78e436..a138b5c 100644 (file)
@@ -163,7 +163,7 @@ iwl_mvm_scan_rate_n_flags(struct iwl_mvm *mvm, enum nl80211_band band,
        tx_ant = BIT(mvm->scan_last_antenna_idx) << RATE_MCS_ANT_POS;
 
        if (band == NL80211_BAND_2GHZ && !no_cck)
-               return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK |
+               return cpu_to_le32(IWL_RATE_1M_PLCP | RATE_MCS_CCK_MSK_V1 |
                                   tx_ant);
        else
                return cpu_to_le32(IWL_RATE_6M_PLCP | tx_ant);
@@ -1995,8 +1995,16 @@ static u16 iwl_mvm_scan_umac_flags_v2(struct iwl_mvm *mvm,
 {
        u16 flags = 0;
 
+       /*
+        * If no direct SSIDs are provided perform a passive scan. Otherwise,
+        * if there is a single SSID which is not the broadcast SSID, assume
+        * that the scan is intended for roaming purposes and thus enable Rx on
+        * all chains to improve chances of hearing the beacons/probe responses.
+        */
        if (params->n_ssids == 0)
                flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE;
+       else if (params->n_ssids == 1 && params->ssids[0].ssid_len)
+               flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_USE_ALL_RX_CHAINS;
 
        if (iwl_mvm_is_scan_fragmented(params->type))
                flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1;
index 0a13c2b..bdd4ee4 100644 (file)
@@ -268,6 +268,7 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
        int rate_idx = -1;
        u8 rate_plcp;
        u32 rate_flags = 0;
+       bool is_cck;
        struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
 
        /* info->control is only relevant for non HW rate control */
@@ -299,11 +300,18 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
        BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
 
        /* Get PLCP rate for tx_cmd->rate_n_flags */
-       rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
+       rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(mvm->fw, rate_idx);
+       is_cck = (rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE);
 
-       /* Set CCK flag as needed */
-       if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
-               rate_flags |= RATE_MCS_CCK_MSK;
+       /* Set CCK or OFDM flag */
+       if (iwl_fw_lookup_cmd_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 8) {
+               if (!is_cck)
+                       rate_flags |= RATE_MCS_LEGACY_OFDM_MSK;
+               else
+                       rate_flags |= RATE_MCS_CCK_MSK;
+       } else if (is_cck) {
+               rate_flags |= RATE_MCS_CCK_MSK_V1;
+       }
 
        return (u32)rate_plcp | rate_flags;
 }
@@ -1284,31 +1292,72 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status)
 }
 #endif /* CONFIG_IWLWIFI_DEBUG */
 
-void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
-                              enum nl80211_band band,
-                              struct ieee80211_tx_rate *r)
+static int iwl_mvm_get_hwrate_chan_width(u32 chan_width)
 {
-       if (rate_n_flags & RATE_HT_MCS_GF_MSK)
-               r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
-       switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK) {
+       switch (chan_width) {
        case RATE_MCS_CHAN_WIDTH_20:
-               break;
+               return 0;
        case RATE_MCS_CHAN_WIDTH_40:
-               r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
-               break;
+               return IEEE80211_TX_RC_40_MHZ_WIDTH;
        case RATE_MCS_CHAN_WIDTH_80:
-               r->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH;
-               break;
+               return IEEE80211_TX_RC_80_MHZ_WIDTH;
        case RATE_MCS_CHAN_WIDTH_160:
-               r->flags |= IEEE80211_TX_RC_160_MHZ_WIDTH;
-               break;
+               return IEEE80211_TX_RC_160_MHZ_WIDTH;
+       default:
+               return 0;
        }
+}
+
+void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
+                              enum nl80211_band band,
+                              struct ieee80211_tx_rate *r)
+{
+       u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
+       u32 rate = format == RATE_MCS_HT_MSK ?
+               RATE_HT_MCS_INDEX(rate_n_flags) :
+               rate_n_flags & RATE_MCS_CODE_MSK;
+
+       r->flags |=
+               iwl_mvm_get_hwrate_chan_width(rate_n_flags &
+                                             RATE_MCS_CHAN_WIDTH_MSK);
+
        if (rate_n_flags & RATE_MCS_SGI_MSK)
                r->flags |= IEEE80211_TX_RC_SHORT_GI;
-       if (rate_n_flags & RATE_MCS_HT_MSK) {
+       if (format ==  RATE_MCS_HT_MSK) {
                r->flags |= IEEE80211_TX_RC_MCS;
-               r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
-       } else if (rate_n_flags & RATE_MCS_VHT_MSK) {
+               r->idx = rate;
+       } else if (format ==  RATE_MCS_VHT_MSK) {
+               ieee80211_rate_set_vht(r, rate,
+                                      ((rate_n_flags & RATE_MCS_NSS_MSK) >>
+                                       RATE_MCS_NSS_POS) + 1);
+               r->flags |= IEEE80211_TX_RC_VHT_MCS;
+       } else if (format == RATE_MCS_HE_MSK) {
+               /* mac80211 cannot do this without ieee80211_tx_status_ext()
+                * but it only matters for radiotap */
+               r->idx = 0;
+       } else {
+               r->idx = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
+                                                              band);
+       }
+}
+
+void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
+                                 enum nl80211_band band,
+                                 struct ieee80211_tx_rate *r)
+{
+       if (rate_n_flags & RATE_HT_MCS_GF_MSK)
+               r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+
+       r->flags |=
+               iwl_mvm_get_hwrate_chan_width(rate_n_flags &
+                                             RATE_MCS_CHAN_WIDTH_MSK_V1);
+
+       if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
+               r->flags |= IEEE80211_TX_RC_SHORT_GI;
+       if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
+               r->flags |= IEEE80211_TX_RC_MCS;
+               r->idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK_V1;
+       } else if (rate_n_flags & RATE_MCS_VHT_MSK_V1) {
                ieee80211_rate_set_vht(
                        r, rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK,
                        ((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
@@ -1323,14 +1372,20 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
 /*
  * translate ucode response to mac80211 tx status control values
  */
-static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags,
+static void iwl_mvm_hwrate_to_tx_status(const struct iwl_fw *fw,
+                                       u32 rate_n_flags,
                                        struct ieee80211_tx_info *info)
 {
        struct ieee80211_tx_rate *r = &info->status.rates[0];
 
+       if (iwl_fw_lookup_notif_ver(fw, LONG_GROUP,
+                                   TX_CMD, 0) > 6)
+               rate_n_flags = iwl_new_rate_from_v1(rate_n_flags);
+
        info->status.antenna =
-               ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
-       iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r);
+               ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
+       iwl_mvm_hwrate_to_tx_rate(rate_n_flags,
+                                 info->band, r);
 }
 
 static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
@@ -1450,7 +1505,9 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                        /* the FW should have stopped the queue and not
                         * return this status
                         */
-                       WARN_ON(1);
+                       IWL_ERR_LIMIT(mvm,
+                                     "FW reported TX filtered, status=0x%x, FC=0x%x\n",
+                                     status, le16_to_cpu(hdr->frame_control));
                        info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
                        break;
                default:
@@ -1472,8 +1529,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
                iwl_mvm_tx_status_check_trigger(mvm, status, hdr->frame_control);
 
                info->status.rates[0].count = tx_resp->failure_frame + 1;
-               iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),
+
+               iwl_mvm_hwrate_to_tx_status(mvm->fw,
+                                           le32_to_cpu(tx_resp->initial_rate),
                                            info);
+
+               /* Don't assign the converted initial_rate, because driver
+                * TLC uses this and doesn't support the new FW rate
+                */
                info->status.status_driver_data[1] =
                        (void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);
 
@@ -1835,7 +1898,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
                        info->flags |= IEEE80211_TX_STAT_AMPDU;
                        memcpy(&info->status, &tx_info->status,
                               sizeof(tx_info->status));
-                       iwl_mvm_hwrate_to_tx_status(rate, info);
+                       iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, info);
                }
        }
 
@@ -1856,7 +1919,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
                        goto out;
 
                tx_info->band = chanctx_conf->def.chan->band;
-               iwl_mvm_hwrate_to_tx_status(rate, tx_info);
+               iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info);
 
                if (!iwl_mvm_has_tlc_offload(mvm)) {
                        IWL_DEBUG_TX_REPLY(mvm,
index 4a3d297..caf1dcf 100644 (file)
@@ -135,31 +135,25 @@ int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len,
        return iwl_mvm_send_cmd_status(mvm, &cmd, status);
 }
 
-#define IWL_DECLARE_RATE_INFO(r) \
-       [IWL_RATE_##r##M_INDEX] = IWL_RATE_##r##M_PLCP
+int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
+                                         enum nl80211_band band)
+{
+       int format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
+       int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;
+       bool is_LB = band == NL80211_BAND_2GHZ;
 
-/*
- * Translate from fw_rate_index (IWL_RATE_XXM_INDEX) to PLCP
- */
-static const u8 fw_rate_idx_to_plcp[IWL_RATE_COUNT] = {
-       IWL_DECLARE_RATE_INFO(1),
-       IWL_DECLARE_RATE_INFO(2),
-       IWL_DECLARE_RATE_INFO(5),
-       IWL_DECLARE_RATE_INFO(11),
-       IWL_DECLARE_RATE_INFO(6),
-       IWL_DECLARE_RATE_INFO(9),
-       IWL_DECLARE_RATE_INFO(12),
-       IWL_DECLARE_RATE_INFO(18),
-       IWL_DECLARE_RATE_INFO(24),
-       IWL_DECLARE_RATE_INFO(36),
-       IWL_DECLARE_RATE_INFO(48),
-       IWL_DECLARE_RATE_INFO(54),
-};
+       if (format == RATE_MCS_LEGACY_OFDM_MSK)
+               return is_LB ? rate + IWL_FIRST_OFDM_RATE :
+                       rate;
+
+       /* CCK is not allowed in HB */
+       return is_LB ? rate : -1;
+}
 
 int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
                                        enum nl80211_band band)
 {
-       int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;
+       int rate = rate_n_flags & RATE_LEGACY_RATE_MSK_V1;
        int idx;
        int band_offset = 0;
 
@@ -167,16 +161,24 @@ int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
        if (band != NL80211_BAND_2GHZ)
                band_offset = IWL_FIRST_OFDM_RATE;
        for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
-               if (fw_rate_idx_to_plcp[idx] == rate)
+               if (iwl_fw_rate_idx_to_plcp(idx) == rate)
                        return idx - band_offset;
 
        return -1;
 }
 
-u8 iwl_mvm_mac80211_idx_to_hwrate(int rate_idx)
+u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx)
 {
-       /* Get PLCP rate for tx_cmd->rate_n_flags */
-       return fw_rate_idx_to_plcp[rate_idx];
+       if (iwl_fw_lookup_cmd_ver(fw, LONG_GROUP,
+                                 TX_CMD, 0) > 8)
+               /* In the new rate legacy rates are indexed:
+                * 0 - 3 for CCK and 0 - 7 for OFDM.
+                */
+               return (rate_idx >= IWL_FIRST_OFDM_RATE ?
+                       rate_idx - IWL_FIRST_OFDM_RATE :
+                       rate_idx);
+
+       return iwl_fw_rate_idx_to_plcp(rate_idx);
 }
 
 u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac)
@@ -217,6 +219,7 @@ u8 first_antenna(u8 mask)
        return BIT(ffs(mask) - 1);
 }
 
+#define MAX_ANT_NUM 2
 /*
  * Toggles between TX antennas to send the probe request on.
  * Receives the bitmask of valid TX antennas and the *index* used
@@ -405,6 +408,9 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm,
 
        lockdep_assert_held(&mvm->mutex);
 
+       if (iwlmvm_mod_params.power_scheme != IWL_POWER_SCHEME_CAM)
+               return false;
+
        if (num_of_ant(iwl_mvm_get_valid_rx_ant(mvm)) == 1)
                return false;
 
index 239a722..85a6da7 100644 (file)
@@ -57,6 +57,10 @@ iwl_pcie_ctxt_info_dbg_enable(struct iwl_trans *trans,
                        dbg_flags |= IWL_PRPH_SCRATCH_EDBG_DEST_DRAM;
                        dbg_cfg->hwm_base_addr = cpu_to_le64(frag->physical);
                        dbg_cfg->hwm_size = cpu_to_le32(frag->size);
+                       dbg_cfg->debug_token_config = cpu_to_le32(trans->dbg.ucode_preset);
+                       IWL_DEBUG_FW(trans,
+                                    "WRT: Applying DRAM destination (debug_token_config=%u)\n",
+                                    dbg_cfg->debug_token_config);
                        IWL_DEBUG_FW(trans,
                                     "WRT: Applying DRAM destination (alloc_id=%u, num_frags=%u)\n",
                                     alloc_id,
index 3b97438..c574f04 100644 (file)
@@ -499,6 +499,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
 /* Ma devices */
        {IWL_PCI_DEVICE(0x2729, PCI_ANY_ID, iwl_ma_trans_cfg)},
        {IWL_PCI_DEVICE(0x7E40, PCI_ANY_ID, iwl_ma_trans_cfg)},
+       {IWL_PCI_DEVICE(0x7F70, PCI_ANY_ID, iwl_ma_trans_cfg)},
 
 /* Bz devices */
        {IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)},
@@ -518,7 +519,7 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
 #define IWL_DEV_INFO(_device, _subdevice, _cfg, _name) \
        _IWL_DEV_INFO(_device, _subdevice, IWL_CFG_ANY, IWL_CFG_ANY,       \
                      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,  \
-                     IWL_CFG_NO_CDB, _cfg, _name)
+                     IWL_CFG_ANY, _cfg, _name)
 
 static const struct iwl_dev_info iwl_dev_info_table[] = {
 #if IS_ENABLED(CONFIG_IWLMVM)
@@ -532,15 +533,25 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
        IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
        IWL_DEV_INFO(0xA370, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name),
        IWL_DEV_INFO(0xA370, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
+       IWL_DEV_INFO(0x54F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
+       IWL_DEV_INFO(0x54F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name),
        IWL_DEV_INFO(0x51F0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
        IWL_DEV_INFO(0x51F0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
+       IWL_DEV_INFO(0x51F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
+       IWL_DEV_INFO(0x51F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+       IWL_DEV_INFO(0x54F0, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
+       IWL_DEV_INFO(0x54F0, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
+       IWL_DEV_INFO(0x7A70, 0x1691, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690s_name),
+       IWL_DEV_INFO(0x7A70, 0x1692, iwlax411_2ax_cfg_so_gf4_a0, iwl_ax411_killer_1690i_name),
 
        IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name),
+       IWL_DEV_INFO(0x7E40, 0x1691, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690s_name),
+       IWL_DEV_INFO(0x7E40, 0x1692, iwl_cfg_ma_a0_gf4_a0, iwl_ax411_killer_1690i_name),
 
 /* AX200 */
+       IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
        IWL_DEV_INFO(0x2723, 0x1653, iwl_ax200_cfg_cc, iwl_ax200_killer_1650w_name),
        IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name),
-       IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name),
 
        /* Qu with Hr */
        IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL),
@@ -639,6 +650,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
        IWL_DEV_INFO(0x7AF0, 0x0510, iwlax211_2ax_cfg_so_gf_a0, NULL),
        IWL_DEV_INFO(0x7AF0, 0x0A10, iwlax211_2ax_cfg_so_gf_a0, NULL),
 
+       /* So with JF */
+       IWL_DEV_INFO(0x7A70, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
+       IWL_DEV_INFO(0x7A70, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
+       IWL_DEV_INFO(0x7AF0, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_160_name),
+       IWL_DEV_INFO(0x7AF0, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_160_name),
+
        /* SnJ with HR */
        IWL_DEV_INFO(0x2725, 0x00B0, iwlax411_2ax_cfg_sosnj_gf4_a0, NULL),
        IWL_DEV_INFO(0x2726, 0x0090, iwlax211_cfg_snj_gf_a0, NULL),
@@ -648,6 +665,12 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
        IWL_DEV_INFO(0x2726, 0x0510, iwlax211_cfg_snj_gf_a0, NULL),
        IWL_DEV_INFO(0x2726, 0x1651, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650s_name),
        IWL_DEV_INFO(0x2726, 0x1652, iwl_cfg_snj_hr_b0, iwl_ax201_killer_1650i_name),
+       IWL_DEV_INFO(0x2726, 0x1671, iwlax211_cfg_snj_gf_a0, iwl_ax211_killer_1675s_name),
+       IWL_DEV_INFO(0x2726, 0x1672, iwlax211_cfg_snj_gf_a0, iwl_ax211_killer_1675i_name),
+       IWL_DEV_INFO(0x2726, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name),
+       IWL_DEV_INFO(0x2726, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name),
+       IWL_DEV_INFO(0x7F70, 0x1691, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690s_name),
+       IWL_DEV_INFO(0x7F70, 0x1692, iwlax411_2ax_cfg_sosnj_gf4_a0, iwl_ax411_killer_1690i_name),
 
        _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
                      IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY,
@@ -703,17 +726,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
                      iwl9260_2ac_cfg, iwl9462_name),
 
        _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
-                     IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
-                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
-                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
-                     iwl9260_2ac_cfg, iwl9560_160_name),
-       _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
-                     IWL_CFG_MAC_TYPE_PNJ, IWL_CFG_ANY,
-                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
-                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
-                     iwl9260_2ac_cfg, iwl9560_name),
-
-       _IWL_DEV_INFO(0x2526, IWL_CFG_ANY,
                      IWL_CFG_MAC_TYPE_TH, IWL_CFG_ANY,
                      IWL_CFG_RF_TYPE_TH, IWL_CFG_ANY,
                      IWL_CFG_160, IWL_CFG_CORES_BT_GNSS, IWL_CFG_NO_CDB,
@@ -1053,11 +1065,6 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
                      iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
        _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
                      IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
-                     IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY,
-                     IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
-                     iwl_cfg_so_a0_hr_a0, iwl_ax203_name),
-       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
-                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
                      IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY,
                      IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
                      iwl_cfg_so_a0_hr_a0, iwl_ax101_name),
@@ -1112,6 +1119,50 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
                      IWL_CFG_RF_TYPE_MR, IWL_CFG_ANY,
                      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
                      iwl_cfg_bz_a0_mr_a0, iwl_bz_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+                     IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+                     iwl_cfg_bz_a0_fm_a0, iwl_bz_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY,
+                     IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
+                     iwl_cfg_gl_a0_fm_a0, iwl_bz_name),
+
+/* SoF with JF2 */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
+
+/* SoF with JF */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
 
 /* SoF with JF2 */
        _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
@@ -1191,16 +1242,158 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
 #endif /* CONFIG_IWLMVM */
 };
 
+/*
+ * In case that there is no OTP on the NIC, get the rf id and cdb info
+ * from the prph registers.
+ */
+static int get_crf_id(struct iwl_trans *iwl_trans)
+{
+       int ret = 0;
+       u32 wfpm_ctrl_addr;
+       u32 wfpm_otp_cfg_addr;
+       u32 sd_reg_ver_addr;
+       u32 cdb = 0;
+       u32 val;
+
+       if (iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
+               wfpm_ctrl_addr = WFPM_CTRL_REG_GEN2;
+               wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR_GEN2;
+               sd_reg_ver_addr = SD_REG_VER_GEN2;
+       /* Qu/Pu families have other addresses */
+       } else {
+               wfpm_ctrl_addr = WFPM_CTRL_REG;
+               wfpm_otp_cfg_addr = WFPM_OTP_CFG1_ADDR;
+               sd_reg_ver_addr = SD_REG_VER;
+       }
+
+       if (!iwl_trans_grab_nic_access(iwl_trans)) {
+               IWL_ERR(iwl_trans, "Failed to grab nic access before reading crf id\n");
+               ret = -EIO;
+               goto out;
+       }
+
+       /* Enable access to peripheral registers */
+       val = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr);
+       val |= ENABLE_WFPM;
+       iwl_write_umac_prph_no_grab(iwl_trans, wfpm_ctrl_addr, val);
+
+       /* Read crf info */
+       val = iwl_read_prph_no_grab(iwl_trans, sd_reg_ver_addr);
+
+       /* Read cdb info (also contains the jacket info if needed in the future */
+       cdb = iwl_read_umac_prph_no_grab(iwl_trans, wfpm_otp_cfg_addr);
+
+       /* Map between crf id to rf id */
+       switch (REG_CRF_ID_TYPE(val)) {
+       case REG_CRF_ID_TYPE_JF_1:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF1 << 12);
+               break;
+       case REG_CRF_ID_TYPE_JF_2:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_JF2 << 12);
+               break;
+       case REG_CRF_ID_TYPE_HR_NONE_CDB:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR1 << 12);
+               break;
+       case REG_CRF_ID_TYPE_HR_CDB:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_HR2 << 12);
+               break;
+       case REG_CRF_ID_TYPE_GF:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_GF << 12);
+               break;
+       case REG_CRF_ID_TYPE_MR:
+               iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_MR << 12);
+               break;
+               case REG_CRF_ID_TYPE_FM:
+                       iwl_trans->hw_rf_id = (IWL_CFG_RF_TYPE_FM << 12);
+                       break;
+       default:
+               ret = -EIO;
+               IWL_ERR(iwl_trans,
+                       "Can find a correct rfid for crf id 0x%x\n",
+                       REG_CRF_ID_TYPE(val));
+               goto out_release;
+
+       }
+
+       /* Set CDB capabilities */
+       if (cdb & BIT(4)) {
+               iwl_trans->hw_rf_id += BIT(28);
+               IWL_INFO(iwl_trans, "Adding cdb to rf id\n");
+       }
+
+       IWL_INFO(iwl_trans, "Detected RF 0x%x from crf id 0x%x\n",
+                iwl_trans->hw_rf_id, REG_CRF_ID_TYPE(val));
+
+out_release:
+       iwl_trans_release_nic_access(iwl_trans);
+
+out:
+       return ret;
+}
+
 /* PCI registers */
 #define PCI_CFG_RETRY_TIMEOUT  0x041
 
+static const struct iwl_dev_info *
+iwl_pci_find_dev_info(u16 device, u16 subsystem_device,
+                     u16 mac_type, u8 mac_step,
+                     u16 rf_type, u8 cdb, u8 rf_id, u8 no_160, u8 cores)
+{
+       int i;
+
+       for (i = ARRAY_SIZE(iwl_dev_info_table) - 1; i >= 0; i--) {
+               const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
+
+               if (dev_info->device != (u16)IWL_CFG_ANY &&
+                   dev_info->device != device)
+                       continue;
+
+               if (dev_info->subdevice != (u16)IWL_CFG_ANY &&
+                   dev_info->subdevice != subsystem_device)
+                       continue;
+
+               if (dev_info->mac_type != (u16)IWL_CFG_ANY &&
+                   dev_info->mac_type != mac_type)
+                       continue;
+
+               if (dev_info->mac_step != (u8)IWL_CFG_ANY &&
+                   dev_info->mac_step != mac_step)
+                       continue;
+
+               if (dev_info->rf_type != (u16)IWL_CFG_ANY &&
+                   dev_info->rf_type != rf_type)
+                       continue;
+
+               if (dev_info->cdb != (u8)IWL_CFG_ANY &&
+                   dev_info->cdb != cdb)
+                       continue;
+
+               if (dev_info->rf_id != (u8)IWL_CFG_ANY &&
+                   dev_info->rf_id != rf_id)
+                       continue;
+
+               if (dev_info->no_160 != (u8)IWL_CFG_ANY &&
+                   dev_info->no_160 != no_160)
+                       continue;
+
+               if (dev_info->cores != (u8)IWL_CFG_ANY &&
+                   dev_info->cores != cores)
+                       continue;
+
+               return dev_info;
+       }
+
+       return NULL;
+}
+
 static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        const struct iwl_cfg_trans_params *trans;
        const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
+       const struct iwl_dev_info *dev_info;
        struct iwl_trans *iwl_trans;
        struct iwl_trans_pcie *trans_pcie;
-       int i, ret;
+       int ret;
        const struct iwl_cfg *cfg;
 
        trans = (void *)(ent->driver_data & ~TRANS_CFG_MARKER);
@@ -1222,37 +1415,48 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
 
+       /*
+        * Let's try to grab NIC access early here. Sometimes, NICs may
+        * fail to initialize, and if that happens it's better if we see
+        * issues early on (and can reprobe, per the logic inside), than
+        * first trying to load the firmware etc. and potentially only
+        * detecting any problems when the first interface is brought up.
+        */
+       ret = iwl_finish_nic_init(iwl_trans);
+       if (ret)
+               goto out_free_trans;
+       if (iwl_trans_grab_nic_access(iwl_trans)) {
+               /* all good */
+               iwl_trans_release_nic_access(iwl_trans);
+       } else {
+               ret = -EIO;
+               goto out_free_trans;
+       }
+
        iwl_trans->hw_rf_id = iwl_read32(iwl_trans, CSR_HW_RF_ID);
 
-       for (i = 0; i < ARRAY_SIZE(iwl_dev_info_table); i++) {
-               const struct iwl_dev_info *dev_info = &iwl_dev_info_table[i];
-               if ((dev_info->device == (u16)IWL_CFG_ANY ||
-                    dev_info->device == pdev->device) &&
-                   (dev_info->subdevice == (u16)IWL_CFG_ANY ||
-                    dev_info->subdevice == pdev->subsystem_device) &&
-                   (dev_info->mac_type == (u16)IWL_CFG_ANY ||
-                    dev_info->mac_type ==
-                    CSR_HW_REV_TYPE(iwl_trans->hw_rev)) &&
-                   (dev_info->mac_step == (u8)IWL_CFG_ANY ||
-                    dev_info->mac_step ==
-                    CSR_HW_REV_STEP(iwl_trans->hw_rev)) &&
-                   (dev_info->rf_type == (u16)IWL_CFG_ANY ||
-                    dev_info->rf_type ==
-                    CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id)) &&
-                   (dev_info->cdb == IWL_CFG_NO_CDB ||
-                    CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id)) &&
-                   (dev_info->rf_id == (u8)IWL_CFG_ANY ||
-                    dev_info->rf_id ==
-                    IWL_SUBDEVICE_RF_ID(pdev->subsystem_device)) &&
-                   (dev_info->no_160 == (u8)IWL_CFG_ANY ||
-                    dev_info->no_160 ==
-                    IWL_SUBDEVICE_NO_160(pdev->subsystem_device)) &&
-                   (dev_info->cores == (u8)IWL_CFG_ANY ||
-                    dev_info->cores ==
-                    IWL_SUBDEVICE_CORES(pdev->subsystem_device))) {
-                       iwl_trans->cfg = dev_info->cfg;
-                       iwl_trans->name = dev_info->name;
-               }
+       /*
+        * The RF_ID is set to zero in blank OTP so read version to
+        * extract the RF_ID.
+        * This is relevant only for family 9000 and up.
+        */
+       if (iwl_trans->trans_cfg->rf_id &&
+           iwl_trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_9000 &&
+           !CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id) && get_crf_id(iwl_trans))
+               goto out_free_trans;
+
+       dev_info = iwl_pci_find_dev_info(pdev->device, pdev->subsystem_device,
+                                        CSR_HW_REV_TYPE(iwl_trans->hw_rev),
+                                        CSR_HW_REV_STEP(iwl_trans->hw_rev),
+                                        CSR_HW_RFID_TYPE(iwl_trans->hw_rf_id),
+                                        CSR_HW_RFID_IS_CDB(iwl_trans->hw_rf_id),
+                                        IWL_SUBDEVICE_RF_ID(pdev->subsystem_device),
+                                        IWL_SUBDEVICE_NO_160(pdev->subsystem_device),
+                                        IWL_SUBDEVICE_CORES(pdev->subsystem_device));
+
+       if (dev_info) {
+               iwl_trans->cfg = dev_info->cfg;
+               iwl_trans->name = dev_info->name;
        }
 
 #if IS_ENABLED(CONFIG_IWLMVM)
index 8e45eb3..14602d6 100644 (file)
@@ -2149,6 +2149,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
        u32 inta_fh_msk = ~MSIX_FH_INT_CAUSES_DATA_QUEUE;
        u32 inta_fh, inta_hw;
        bool polling = false;
+       bool sw_err;
 
        if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)
                inta_fh_msk |= MSIX_FH_INT_CAUSES_Q0;
@@ -2221,9 +2222,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
                wake_up(&trans_pcie->ucode_write_waitq);
        }
 
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+               sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
+       else
+               sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR;
+
        /* Error detected by uCode */
-       if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) ||
-           (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) {
+       if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) || sw_err) {
                IWL_ERR(trans,
                        "Microcode SW error detected. Restarting 0x%X.\n",
                        inta_fh);
index bf0c32a..645cb4d 100644 (file)
@@ -47,7 +47,7 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
 
        iwl_pcie_apm_config(trans);
 
-       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       ret = iwl_finish_nic_init(trans);
        if (ret)
                return ret;
 
@@ -131,21 +131,9 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
        if (trans_pcie->is_down)
                return;
 
-       if (trans->state >= IWL_TRANS_FW_STARTED) {
-               if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
-                       iwl_set_bit(trans, CSR_GP_CNTRL,
-                                   CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_REQ);
-                       iwl_poll_bit(trans, CSR_GP_CNTRL,
-                                    CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
-                                    CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
-                                    5000);
-                       msleep(100);
-                       iwl_set_bit(trans, CSR_GP_CNTRL,
-                                   CSR_GP_CNTRL_REG_FLAG_SW_RESET);
-               } else if (trans_pcie->fw_reset_handshake) {
+       if (trans->state >= IWL_TRANS_FW_STARTED)
+               if (trans_pcie->fw_reset_handshake)
                        iwl_trans_pcie_fw_reset_handshake(trans);
-               }
-       }
 
        trans_pcie->is_down = true;
 
@@ -175,18 +163,6 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
        else
                iwl_pcie_ctxt_info_free(trans);
 
-       /* Make sure (redundant) we've released our request to stay awake */
-       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
-               iwl_clear_bit(trans, CSR_GP_CNTRL,
-                             CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
-       else
-               iwl_clear_bit(trans, CSR_GP_CNTRL,
-                             CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
-       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
-               iwl_set_bit(trans, CSR_GP_CNTRL,
-                           CSR_GP_CNTRL_REG_FLAG_SW_RESET);
-       }
        /* Stop the device, and put it in low power state */
        iwl_pcie_gen2_apm_stop(trans, false);
 
@@ -466,13 +442,15 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans,
 
        iwl_pcie_set_ltr(trans);
 
-       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+               iwl_write32(trans, CSR_FUNC_SCRATCH, CSR_FUNC_SCRATCH_INIT_VALUE);
                iwl_set_bit(trans, CSR_GP_CNTRL,
                            CSR_GP_CNTRL_REG_FLAG_ROM_START);
-       else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
+       } else if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) {
                iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1);
-       else
+       } else {
                iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1);
+       }
 
        /* re-check RF-Kill state since we may have missed the interrupt */
        hw_rfkill = iwl_pcie_check_hw_rf_kill(trans);
index f252680..1efb53f 100644 (file)
@@ -129,7 +129,12 @@ out:
 static void iwl_trans_pcie_sw_reset(struct iwl_trans *trans)
 {
        /* Reset entire device - do controller reset (results in SHRD_HW_RST) */
-       iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+               iwl_set_bit(trans, CSR_GP_CNTRL,
+                           CSR_GP_CNTRL_REG_FLAG_SW_RESET);
+       else
+               iwl_set_bit(trans, CSR_RESET,
+                           CSR_RESET_REG_FLAG_SW_RESET);
        usleep_range(5000, 6000);
 }
 
@@ -306,7 +311,7 @@ static int iwl_pcie_apm_init(struct iwl_trans *trans)
        if (trans->trans_cfg->base_params->pll_cfg)
                iwl_set_bit(trans, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
 
-       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       ret = iwl_finish_nic_init(trans);
        if (ret)
                return ret;
 
@@ -378,7 +383,7 @@ static void iwl_pcie_apm_lp_xtal_enable(struct iwl_trans *trans)
 
        iwl_trans_pcie_sw_reset(trans);
 
-       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       ret = iwl_finish_nic_init(trans);
        if (WARN_ON(ret)) {
                /* Release XTAL ON request */
                __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
@@ -458,6 +463,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
                                   CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
                                   CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
                                   100);
+               msleep(100);
        } else {
                iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
 
@@ -1056,7 +1062,7 @@ struct iwl_causes_list {
        u8 addr;
 };
 
-static struct iwl_causes_list causes_list[] = {
+static const struct iwl_causes_list causes_list_common[] = {
        {MSIX_FH_INT_CAUSES_D2S_CH0_NUM,        CSR_MSIX_FH_INT_MASK_AD, 0},
        {MSIX_FH_INT_CAUSES_D2S_CH1_NUM,        CSR_MSIX_FH_INT_MASK_AD, 0x1},
        {MSIX_FH_INT_CAUSES_S2D,                CSR_MSIX_FH_INT_MASK_AD, 0x3},
@@ -1067,30 +1073,50 @@ static struct iwl_causes_list causes_list[] = {
        {MSIX_HW_INT_CAUSES_REG_CT_KILL,        CSR_MSIX_HW_INT_MASK_AD, 0x16},
        {MSIX_HW_INT_CAUSES_REG_RF_KILL,        CSR_MSIX_HW_INT_MASK_AD, 0x17},
        {MSIX_HW_INT_CAUSES_REG_PERIODIC,       CSR_MSIX_HW_INT_MASK_AD, 0x18},
-       {MSIX_HW_INT_CAUSES_REG_SW_ERR,         CSR_MSIX_HW_INT_MASK_AD, 0x29},
        {MSIX_HW_INT_CAUSES_REG_SCD,            CSR_MSIX_HW_INT_MASK_AD, 0x2A},
        {MSIX_HW_INT_CAUSES_REG_FH_TX,          CSR_MSIX_HW_INT_MASK_AD, 0x2B},
        {MSIX_HW_INT_CAUSES_REG_HW_ERR,         CSR_MSIX_HW_INT_MASK_AD, 0x2D},
        {MSIX_HW_INT_CAUSES_REG_HAP,            CSR_MSIX_HW_INT_MASK_AD, 0x2E},
 };
 
+static const struct iwl_causes_list causes_list_pre_bz[] = {
+       {MSIX_HW_INT_CAUSES_REG_SW_ERR,         CSR_MSIX_HW_INT_MASK_AD, 0x29},
+};
+
+static const struct iwl_causes_list causes_list_bz[] = {
+       {MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ,      CSR_MSIX_HW_INT_MASK_AD, 0x29},
+};
+
+static void iwl_pcie_map_list(struct iwl_trans *trans,
+                             const struct iwl_causes_list *causes,
+                             int arr_size, int val)
+{
+       int i;
+
+       for (i = 0; i < arr_size; i++) {
+               iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
+               iwl_clear_bit(trans, causes[i].mask_reg,
+                             causes[i].cause_num);
+       }
+}
+
 static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie =  IWL_TRANS_GET_PCIE_TRANS(trans);
        int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
-       int i, arr_size = ARRAY_SIZE(causes_list);
-       struct iwl_causes_list *causes = causes_list;
-
        /*
         * Access all non RX causes and map them to the default irq.
         * In case we are missing at least one interrupt vector,
         * the first interrupt vector will serve non-RX and FBQ causes.
         */
-       for (i = 0; i < arr_size; i++) {
-               iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
-               iwl_clear_bit(trans, causes[i].mask_reg,
-                             causes[i].cause_num);
-       }
+       iwl_pcie_map_list(trans, causes_list_common,
+                         ARRAY_SIZE(causes_list_common), val);
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+               iwl_pcie_map_list(trans, causes_list_bz,
+                                 ARRAY_SIZE(causes_list_bz), val);
+       else
+               iwl_pcie_map_list(trans, causes_list_pre_bz,
+                                 ARRAY_SIZE(causes_list_pre_bz), val);
 }
 
 static void iwl_pcie_map_rx_causes(struct iwl_trans *trans)
@@ -1208,8 +1234,12 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans)
        }
 
        /* Make sure (redundant) we've released our request to stay awake */
-       iwl_clear_bit(trans, CSR_GP_CNTRL,
-                     CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+               iwl_clear_bit(trans, CSR_GP_CNTRL,
+                             CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
+       else
+               iwl_clear_bit(trans, CSR_GP_CNTRL,
+                             CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
        /* Stop the device, and put it in low power state */
        iwl_pcie_apm_stop(trans, false);
@@ -1501,7 +1531,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
        iwl_set_bit(trans, CSR_GP_CNTRL,
                    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
-       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       ret = iwl_finish_nic_init(trans);
        if (ret)
                return ret;
 
@@ -1734,7 +1764,7 @@ static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
 {
        int ret;
 
-       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       ret = iwl_finish_nic_init(trans);
        if (ret < 0)
                return ret;
 
@@ -2140,9 +2170,12 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
 
        if (trans_pcie->cmd_hold_nic_awake)
                goto out;
-
-       __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
-                                  CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+       if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+               __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
+                                          CSR_GP_CNTRL_REG_FLAG_BZ_MAC_ACCESS_REQ);
+       else
+               __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
+                                          CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
        /*
         * Above we read the CSR_GP_CNTRL register, which will flush
         * any previous writes, but we need the write that clears the
@@ -3203,9 +3236,11 @@ static int iwl_trans_get_fw_monitor_len(struct iwl_trans *trans, u32 *len)
        return 0;
 }
 
-static struct iwl_trans_dump_data
-*iwl_trans_pcie_dump_data(struct iwl_trans *trans,
-                         u32 dump_mask)
+static struct iwl_trans_dump_data *
+iwl_trans_pcie_dump_data(struct iwl_trans *trans,
+                        u32 dump_mask,
+                        const struct iwl_dump_sanitize_ops *sanitize_ops,
+                        void *sanitize_ctx)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_fw_error_dump_data *data;
@@ -3305,6 +3340,10 @@ static struct iwl_trans_dump_data
                                txcmd->caplen = cpu_to_le32(caplen);
                                memcpy(txcmd->data, cmdq->entries[idx].cmd,
                                       caplen);
+                               if (sanitize_ops && sanitize_ops->frob_hcmd)
+                                       sanitize_ops->frob_hcmd(sanitize_ctx,
+                                                               txcmd->data,
+                                                               caplen);
                                txcmd = (void *)((u8 *)txcmd->data + caplen);
                        }
 
@@ -3365,7 +3404,10 @@ static void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
 
        if (trans_pcie->msix_enabled) {
                inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
-               sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
+               if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+                       sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
+               else
+                       sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
        } else {
                inta_addr = CSR_INT;
                sw_err_bit = CSR_INT_BIT_SW_ERR;
index 20436a2..5d6dc1d 100644 (file)
@@ -292,6 +292,7 @@ err_add_card:
        if_usb_reset_device(cardp);
 dealloc:
        if_usb_free(cardp);
+       kfree(cardp);
 
 error:
        return r;
@@ -316,6 +317,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
 
        /* Unlink and free urb */
        if_usb_free(cardp);
+       kfree(cardp);
 
        usb_set_intfdata(intf, NULL);
        usb_put_dev(interface_to_usbdev(intf));
index 6cbba84..a58c1e1 100644 (file)
@@ -169,7 +169,7 @@ static ssize_t anycast_mask_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
+       return sysfs_emit(buf, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
 }
 
 /**
@@ -222,7 +222,7 @@ static ssize_t prb_rsp_limit_show(struct device *dev,
                return ret;
 
        retry_limit = le32_to_cpu(mesh_access.data[1]);
-       return snprintf(buf, 10, "%d\n", retry_limit);
+       return sysfs_emit(buf, "%d\n", retry_limit);
 }
 
 /**
@@ -270,7 +270,7 @@ static ssize_t lbs_mesh_show(struct device *dev,
                             struct device_attribute *attr, char *buf)
 {
        struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-       return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
+       return sysfs_emit(buf, "0x%X\n", !!priv->mesh_dev);
 }
 
 /**
@@ -369,7 +369,7 @@ static ssize_t bootflag_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
+       return sysfs_emit(buf, "%d\n", le32_to_cpu(defs.bootflag));
 }
 
 /**
@@ -419,7 +419,7 @@ static ssize_t boottime_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 12, "%d\n", defs.boottime);
+       return sysfs_emit(buf, "%d\n", defs.boottime);
 }
 
 /**
@@ -479,7 +479,7 @@ static ssize_t channel_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
+       return sysfs_emit(buf, "%d\n", le16_to_cpu(defs.channel));
 }
 
 /**
@@ -605,7 +605,7 @@ static ssize_t protocol_id_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
+       return sysfs_emit(buf, "%d\n", defs.meshie.val.active_protocol_id);
 }
 
 /**
@@ -667,7 +667,7 @@ static ssize_t metric_id_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
+       return sysfs_emit(buf, "%d\n", defs.meshie.val.active_metric_id);
 }
 
 /**
@@ -729,7 +729,7 @@ static ssize_t capability_show(struct device *dev,
        if (ret)
                return ret;
 
-       return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
+       return sysfs_emit(buf, "%d\n", defs.meshie.val.mesh_capability);
 }
 
 /**
index fe0a69e..75b5319 100644 (file)
@@ -230,6 +230,7 @@ static int if_usb_probe(struct usb_interface *intf,
 
 dealloc:
        if_usb_free(cardp);
+       kfree(cardp);
 error:
 lbtf_deb_leave(LBTF_DEB_MAIN);
        return -ENOMEM;
@@ -254,6 +255,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
 
        /* Unlink and free urb */
        if_usb_free(cardp);
+       kfree(cardp);
 
        usb_set_intfdata(intf, NULL);
        usb_put_dev(interface_to_usbdev(intf));
index 426e39d..9736aa0 100644 (file)
@@ -505,6 +505,22 @@ static int mwifiex_usb_probe(struct usb_interface *intf,
                }
        }
 
+       switch (card->usb_boot_state) {
+       case USB8XXX_FW_DNLD:
+               /* Reject broken descriptors. */
+               if (!card->rx_cmd_ep || !card->tx_cmd_ep)
+                       return -ENODEV;
+               if (card->bulk_out_maxpktsize == 0)
+                       return -ENODEV;
+               break;
+       case USB8XXX_FW_READY:
+               /* Assume the driver can handle missing endpoints for now. */
+               break;
+       default:
+               WARN_ON(1);
+               return -ENODEV;
+       }
+
        usb_set_intfdata(intf, card);
 
        ret = mwifiex_add_card(card, &card->fw_done, &usb_ops,
index e65b226..2d58aa3 100644 (file)
@@ -65,8 +65,11 @@ int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int offset, int len)
        offset = be32_to_cpup(list);
        ret = mtd_read(mtd, offset, len, &retlen, eep);
        put_mtd_device(mtd);
-       if (ret)
+       if (ret) {
+               dev_err(dev->dev, "reading EEPROM from mtd %s failed: %i\n",
+                       part, ret);
                goto out_put_node;
+       }
 
        if (retlen < len) {
                ret = -EINVAL;
index 2cb3969..25f9cbe 100644 (file)
@@ -1698,6 +1698,19 @@ int mt7615_mcu_fw_log_2_host(struct mt7615_dev *dev, u8 ctrl)
                                 sizeof(data), true);
 }
 
+static int mt7615_mcu_cal_cache_apply(struct mt7615_dev *dev)
+{
+       struct {
+               bool cache_enable;
+               u8 pad[3];
+       } data = {
+               .cache_enable = true
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_CAL_CACHE, &data,
+                                sizeof(data), false);
+}
+
 static int mt7663_load_n9(struct mt7615_dev *dev, const char *name)
 {
        u32 offset = 0, override_addr = 0, flag = FW_START_DLYCAL;
@@ -1906,9 +1919,14 @@ int mt7615_mcu_init(struct mt7615_dev *dev)
        mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
        dev_dbg(dev->mt76.dev, "Firmware init done\n");
        set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
-       mt7615_mcu_fw_log_2_host(dev, 0);
 
-       return 0;
+       if (dev->dbdc_support) {
+               ret = mt7615_mcu_cal_cache_apply(dev);
+               if (ret)
+                       return ret;
+       }
+
+       return mt7615_mcu_fw_log_2_host(dev, 0);
 }
 EXPORT_SYMBOL_GPL(mt7615_mcu_init);
 
index 32e2518..26b4b87 100644 (file)
@@ -2477,6 +2477,7 @@ void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
        mt76_connac_mcu_set_wow_ctrl(phy, vif, suspend, wowlan);
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_iter);
+#endif /* CONFIG_PM */
 
 u32 mt76_connac_mcu_reg_rr(struct mt76_dev *dev, u32 offset)
 {
@@ -2505,7 +2506,6 @@ void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val)
        mt76_mcu_send_msg(dev, MCU_CMD_REG_WRITE, &req, sizeof(req), false);
 }
 EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_wr);
-#endif /* CONFIG_PM */
 
 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
 MODULE_LICENSE("Dual BSD/GPL");
index b89faab..4e2c9da 100644 (file)
@@ -531,6 +531,7 @@ enum {
        MCU_EXT_CMD_TX_POWER_FEATURE_CTRL = 0x58,
        MCU_EXT_CMD_RXDCOC_CAL = 0x59,
        MCU_EXT_CMD_TXDPD_CAL = 0x60,
+       MCU_EXT_CMD_CAL_CACHE = 0x67,
        MCU_EXT_CMD_SET_RDD_TH = 0x7c,
        MCU_EXT_CMD_SET_RDD_PATTERN = 0x7d,
 };
index 4b7f38f..a15aa25 100644 (file)
@@ -82,7 +82,7 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_radar_trigger, NULL,
                         mt7915_radar_trigger, "%lld\n");
 
 static int
-mt7915_fw_debug_set(void *data, u64 val)
+mt7915_fw_debug_wm_set(void *data, u64 val)
 {
        struct mt7915_dev *dev = data;
        enum {
@@ -92,29 +92,103 @@ mt7915_fw_debug_set(void *data, u64 val)
                DEBUG_SPL,
                DEBUG_RPT_RX,
        } debug;
+       int ret;
 
-       dev->fw_debug = !!val;
+       dev->fw_debug_wm = val ? MCU_FW_LOG_TO_HOST : 0;
 
-       mt7915_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0);
+       ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, dev->fw_debug_wm);
+       if (ret)
+               return ret;
 
-       for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++)
-               mt7915_mcu_fw_dbg_ctrl(dev, debug, dev->fw_debug);
+       for (debug = DEBUG_TXCMD; debug <= DEBUG_RPT_RX; debug++) {
+               ret = mt7915_mcu_fw_dbg_ctrl(dev, debug, !!dev->fw_debug_wm);
+               if (ret)
+                       return ret;
+       }
+
+       /* WM CPU info record control */
+       mt76_clear(dev, MT_CPU_UTIL_CTRL, BIT(0));
+       mt76_wr(dev, MT_DIC_CMD_REG_CMD, BIT(2) | BIT(13) | !dev->fw_debug_wm);
+       mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR, BIT(5));
+       mt76_wr(dev, MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR, BIT(5));
 
        return 0;
 }
 
 static int
-mt7915_fw_debug_get(void *data, u64 *val)
+mt7915_fw_debug_wm_get(void *data, u64 *val)
 {
        struct mt7915_dev *dev = data;
 
-       *val = dev->fw_debug;
+       *val = dev->fw_debug_wm;
 
        return 0;
 }
 
-DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7915_fw_debug_get,
-                        mt7915_fw_debug_set, "%lld\n");
+DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wm, mt7915_fw_debug_wm_get,
+                        mt7915_fw_debug_wm_set, "%lld\n");
+
+static int
+mt7915_fw_debug_wa_set(void *data, u64 val)
+{
+       struct mt7915_dev *dev = data;
+       int ret;
+
+       dev->fw_debug_wa = val ? MCU_FW_LOG_TO_HOST : 0;
+
+       ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, dev->fw_debug_wa);
+       if (ret)
+               return ret;
+
+       return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(SET), MCU_WA_PARAM_PDMA_RX,
+                                !!dev->fw_debug_wa, 0);
+}
+
+static int
+mt7915_fw_debug_wa_get(void *data, u64 *val)
+{
+       struct mt7915_dev *dev = data;
+
+       *val = dev->fw_debug_wa;
+
+       return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug_wa, mt7915_fw_debug_wa_get,
+                        mt7915_fw_debug_wa_set, "%lld\n");
+
+static int
+mt7915_fw_util_wm_show(struct seq_file *file, void *data)
+{
+       struct mt7915_dev *dev = file->private;
+
+       if (dev->fw_debug_wm) {
+               seq_printf(file, "Busy: %u%%  Peak busy: %u%%\n",
+                          mt76_rr(dev, MT_CPU_UTIL_BUSY_PCT),
+                          mt76_rr(dev, MT_CPU_UTIL_PEAK_BUSY_PCT));
+               seq_printf(file, "Idle count: %u  Peak idle count: %u\n",
+                          mt76_rr(dev, MT_CPU_UTIL_IDLE_CNT),
+                          mt76_rr(dev, MT_CPU_UTIL_PEAK_IDLE_CNT));
+       }
+
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(mt7915_fw_util_wm);
+
+static int
+mt7915_fw_util_wa_show(struct seq_file *file, void *data)
+{
+       struct mt7915_dev *dev = file->private;
+
+       if (dev->fw_debug_wa)
+               return mt7915_mcu_wa_cmd(dev, MCU_WA_PARAM_CMD(QUERY),
+                                        MCU_WA_PARAM_CPU_UTIL, 0, 0);
+
+       return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(mt7915_fw_util_wa);
 
 static void
 mt7915_ampdu_stat_read_phy(struct mt7915_phy *phy,
@@ -460,7 +534,12 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
        debugfs_create_file("xmit-queues", 0400, dir, phy,
                            &mt7915_xmit_queues_fops);
        debugfs_create_file("tx_stats", 0400, dir, phy, &mt7915_tx_stats_fops);
-       debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
+       debugfs_create_file("fw_debug_wm", 0600, dir, dev, &fops_fw_debug_wm);
+       debugfs_create_file("fw_debug_wa", 0600, dir, dev, &fops_fw_debug_wa);
+       debugfs_create_file("fw_util_wm", 0400, dir, dev,
+                           &mt7915_fw_util_wm_fops);
+       debugfs_create_file("fw_util_wa", 0400, dir, dev,
+                           &mt7915_fw_util_wa_fops);
        debugfs_create_file("implicit_txbf", 0600, dir, dev,
                            &fops_implicit_txbf);
        debugfs_create_file("txpower_sku", 0400, dir, phy,
@@ -481,19 +560,71 @@ int mt7915_init_debugfs(struct mt7915_phy *phy)
 #ifdef CONFIG_MAC80211_DEBUGFS
 /** per-station debugfs **/
 
-static int mt7915_sta_fixed_rate_set(void *data, u64 rate)
+static ssize_t mt7915_sta_fixed_rate_set(struct file *file,
+                                        const char __user *user_buf,
+                                        size_t count, loff_t *ppos)
 {
-       struct ieee80211_sta *sta = data;
+       struct ieee80211_sta *sta = file->private_data;
        struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-
-       /* usage: <he ltf> <tx mode> <ldpc> <stbc> <bw> <gi> <nss> <mcs>
-        * <tx mode>: see enum mt76_phy_type
+       struct mt7915_dev *dev = msta->vif->phy->dev;
+       struct ieee80211_vif *vif;
+       struct sta_phy phy = {};
+       char buf[100];
+       int ret;
+       u32 field;
+       u8 i, gi, he_ltf;
+
+       if (count >= sizeof(buf))
+               return -EINVAL;
+
+       if (copy_from_user(buf, user_buf, count))
+               return -EFAULT;
+
+       if (count && buf[count - 1] == '\n')
+               buf[count - 1] = '\0';
+       else
+               buf[count] = '\0';
+
+       /* mode - cck: 0, ofdm: 1, ht: 2, gf: 3, vht: 4, he_su: 8, he_er: 9
+        * bw - bw20: 0, bw40: 1, bw80: 2, bw160: 3
+        * nss - vht: 1~4, he: 1~4, others: ignore
+        * mcs - cck: 0~4, ofdm: 0~7, ht: 0~32, vht: 0~9, he_su: 0~11, he_er: 0~2
+        * gi - (ht/vht) lgi: 0, sgi: 1; (he) 0.8us: 0, 1.6us: 1, 3.2us: 2
+        * ldpc - off: 0, on: 1
+        * stbc - off: 0, on: 1
+        * he_ltf - 1xltf: 0, 2xltf: 1, 4xltf: 2
         */
-       return mt7915_mcu_set_fixed_rate(msta->vif->phy->dev, sta, rate);
+       if (sscanf(buf, "%hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu",
+                  &phy.type, &phy.bw, &phy.nss, &phy.mcs, &gi,
+                  &phy.ldpc, &phy.stbc, &he_ltf) != 8) {
+               dev_warn(dev->mt76.dev,
+                        "format: Mode BW NSS MCS (HE)GI LDPC STBC HE_LTF\n");
+               field = RATE_PARAM_AUTO;
+               goto out;
+       }
+
+       phy.ldpc = (phy.bw || phy.ldpc) * GENMASK(2, 0);
+       for (i = 0; i <= phy.bw; i++) {
+               phy.sgi |= gi << (i << sta->he_cap.has_he);
+               phy.he_ltf |= he_ltf << (i << sta->he_cap.has_he);
+       }
+       field = RATE_PARAM_FIXED;
+
+out:
+       vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);
+       ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy, field);
+       if (ret)
+               return -EFAULT;
+
+       return count;
 }
 
-DEFINE_DEBUGFS_ATTRIBUTE(fops_fixed_rate, NULL,
-                        mt7915_sta_fixed_rate_set, "%llx\n");
+static const struct file_operations fops_fixed_rate = {
+       .write = mt7915_sta_fixed_rate_set,
+       .open = simple_open,
+       .owner = THIS_MODULE,
+       .llseek = default_llseek,
+};
 
 static int
 mt7915_queues_show(struct seq_file *s, void *data)
index 21e6ef0..5fcf35f 100644 (file)
@@ -89,7 +89,7 @@ bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask)
                         0, 5000);
 }
 
-static u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw)
+u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw)
 {
        mt76_wr(dev, MT_WTBLON_TOP_WDUCR,
                FIELD_PREP(MT_WTBLON_TOP_WDUCR_GROUP, (wcid >> 7)));
@@ -2077,10 +2077,8 @@ void mt7915_mac_sta_rc_work(struct work_struct *work)
 
                if (changed & (IEEE80211_RC_SUPP_RATES_CHANGED |
                               IEEE80211_RC_NSS_CHANGED |
-                              IEEE80211_RC_BW_CHANGED)) {
-                       mt7915_mcu_add_he(dev, vif, sta);
-                       mt7915_mcu_add_rate_ctrl(dev, vif, sta);
-               }
+                              IEEE80211_RC_BW_CHANGED))
+                       mt7915_mcu_add_rate_ctrl(dev, vif, sta, true);
 
                if (changed & IEEE80211_RC_SMPS_CHANGED)
                        mt7915_mcu_add_smps(dev, vif, sta);
index 8be7891..057ab27 100644 (file)
@@ -172,6 +172,9 @@ static void mt7915_init_bitrate_mask(struct ieee80211_vif *vif)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(mvif->bitrate_mask.control); i++) {
+               mvif->bitrate_mask.control[i].gi = NL80211_TXRATE_DEFAULT_GI;
+               mvif->bitrate_mask.control[i].he_gi = GENMASK(7, 0);
+               mvif->bitrate_mask.control[i].he_ltf = GENMASK(7, 0);
                mvif->bitrate_mask.control[i].legacy = GENMASK(31, 0);
                memset(mvif->bitrate_mask.control[i].ht_mcs, GENMASK(7, 0),
                       sizeof(mvif->bitrate_mask.control[i].ht_mcs));
@@ -663,7 +666,7 @@ int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
        if (ret)
                return ret;
 
-       return mt7915_mcu_add_rate_ctrl(dev, vif, sta);
+       return mt7915_mcu_add_rate_ctrl(dev, vif, sta, false);
 }
 
 void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
@@ -994,7 +997,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
 {
        struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
        struct mt7915_dev *dev = msta->vif->phy->dev;
-       struct ieee80211_hw *hw = msta->vif->phy->mt76->hw;
        u32 *changed = data;
 
        spin_lock_bh(&dev->sta_poll_lock);
@@ -1002,8 +1004,6 @@ static void mt7915_sta_rc_work(void *data, struct ieee80211_sta *sta)
        if (list_empty(&msta->rc_list))
                list_add_tail(&msta->rc_list, &dev->sta_rc_list);
        spin_unlock_bh(&dev->sta_poll_lock);
-
-       ieee80211_queue_work(hw, &dev->rc_work);
 }
 
 static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
@@ -1011,7 +1011,11 @@ static void mt7915_sta_rc_update(struct ieee80211_hw *hw,
                                 struct ieee80211_sta *sta,
                                 u32 changed)
 {
+       struct mt7915_phy *phy = mt7915_hw_phy(hw);
+       struct mt7915_dev *dev = phy->dev;
+
        mt7915_sta_rc_work(&changed, sta);
+       ieee80211_queue_work(hw, &dev->rc_work);
 }
 
 static int
@@ -1019,22 +1023,22 @@ mt7915_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                        const struct cfg80211_bitrate_mask *mask)
 {
        struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-       enum nl80211_band band = mvif->phy->mt76->chandef.chan->band;
-       u32 changed;
-
-       if (mask->control[band].gi == NL80211_TXRATE_FORCE_LGI)
-               return -EINVAL;
+       struct mt7915_phy *phy = mt7915_hw_phy(hw);
+       struct mt7915_dev *dev = phy->dev;
+       u32 changed = IEEE80211_RC_SUPP_RATES_CHANGED;
 
-       changed = IEEE80211_RC_SUPP_RATES_CHANGED;
        mvif->bitrate_mask = *mask;
 
-       /* Update firmware rate control to add a boundary on top of table
-        * to limit the rate selection for each peer, so when set bitrates
-        * vht-mcs-5 1:9, which actually means nss = 1 mcs = 0~9. This only
-        * applies to data frames as for the other mgmt, mcast, bcast still
-        * use legacy rates as it is.
+       /* if multiple rates across different preambles are given we can
+        * reconfigure this info with all peers using sta_rec command with
+        * the below exception cases.
+        * - single rate : if a rate is passed along with different preambles,
+        * we select the highest one as fixed rate. i.e VHT MCS for VHT peers.
+        * - multiple rates: if it's not in range format i.e 0-{7,8,9} for VHT
+        * then multiple MCS setting (MCS 4,5,6) is not supported.
         */
        ieee80211_iterate_stations_atomic(hw, mt7915_sta_rc_work, &changed);
+       ieee80211_queue_work(hw, &dev->rc_work);
 
        return 0;
 }
index b4cc4cb..899957b 100644 (file)
@@ -416,8 +416,7 @@ exit:
        return mt76_tx_queue_skb_raw(dev, mdev->q_mcu[qid], skb, 0);
 }
 
-static int
-mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
+int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
 {
        struct {
                __le32 args[3];
@@ -429,7 +428,7 @@ mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3)
                },
        };
 
-       return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), true);
+       return mt76_mcu_send_msg(&dev->mt76, cmd, &req, sizeof(req), false);
 }
 
 static void
@@ -2050,6 +2049,129 @@ mt7915_mcu_sta_bfee_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
        bfee->fb_identity_matrix = (nrow == 1 && tx_ant == 2);
 }
 
+int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_sta *sta,
+                                  void *data, u32 field)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+       struct sta_phy *phy = data;
+       struct sta_rec_ra_fixed *ra;
+       struct sk_buff *skb;
+       struct tlv *tlv;
+       int len = sizeof(struct sta_req_hdr) + sizeof(*ra);
+
+       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       tlv = mt7915_mcu_add_tlv(skb, STA_REC_RA_UPDATE, sizeof(*ra));
+       ra = (struct sta_rec_ra_fixed *)tlv;
+
+       switch (field) {
+       case RATE_PARAM_AUTO:
+               break;
+       case RATE_PARAM_FIXED:
+       case RATE_PARAM_FIXED_MCS:
+       case RATE_PARAM_FIXED_GI:
+       case RATE_PARAM_FIXED_HE_LTF:
+               ra->phy = *phy;
+               break;
+       default:
+               break;
+       }
+       ra->field = cpu_to_le32(field);
+
+       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+                                    MCU_EXT_CMD(STA_REC_UPDATE), true);
+}
+
+static int
+mt7915_mcu_add_rate_ctrl_fixed(struct mt7915_dev *dev,
+                              struct ieee80211_vif *vif,
+                              struct ieee80211_sta *sta)
+{
+       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
+       struct cfg80211_chan_def *chandef = &mvif->phy->mt76->chandef;
+       struct cfg80211_bitrate_mask *mask = &mvif->bitrate_mask;
+       enum nl80211_band band = chandef->chan->band;
+       struct sta_phy phy = {};
+       int ret, nrates = 0;
+
+#define __sta_phy_bitrate_mask_check(_mcs, _gi, _he)                           \
+       do {                                                                    \
+               u8 i, gi = mask->control[band]._gi;                             \
+               gi = (_he) ? gi : gi == NL80211_TXRATE_FORCE_SGI;               \
+               for (i = 0; i <= sta->bandwidth; i++) {                         \
+                       phy.sgi |= gi << (i << (_he));                          \
+                       phy.he_ltf |= mask->control[band].he_ltf << (i << (_he));\
+               }                                                               \
+               for (i = 0; i < ARRAY_SIZE(mask->control[band]._mcs); i++)      \
+                       nrates += hweight16(mask->control[band]._mcs[i]);       \
+               phy.mcs = ffs(mask->control[band]._mcs[0]) - 1;                 \
+       } while (0)
+
+       if (sta->he_cap.has_he) {
+               __sta_phy_bitrate_mask_check(he_mcs, he_gi, 1);
+       } else if (sta->vht_cap.vht_supported) {
+               __sta_phy_bitrate_mask_check(vht_mcs, gi, 0);
+       } else if (sta->ht_cap.ht_supported) {
+               __sta_phy_bitrate_mask_check(ht_mcs, gi, 0);
+       } else {
+               nrates = hweight32(mask->control[band].legacy);
+               phy.mcs = ffs(mask->control[band].legacy) - 1;
+       }
+#undef __sta_phy_bitrate_mask_check
+
+       /* fall back to auto rate control */
+       if (mask->control[band].gi == NL80211_TXRATE_DEFAULT_GI &&
+           mask->control[band].he_gi == GENMASK(7, 0) &&
+           mask->control[band].he_ltf == GENMASK(7, 0) &&
+           nrates != 1)
+               return 0;
+
+       /* fixed single rate */
+       if (nrates == 1) {
+               ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
+                                                    RATE_PARAM_FIXED_MCS);
+               if (ret)
+                       return ret;
+       }
+
+       /* fixed GI */
+       if (mask->control[band].gi != NL80211_TXRATE_DEFAULT_GI ||
+           mask->control[band].he_gi != GENMASK(7, 0)) {
+               struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
+               u32 addr;
+
+               /* firmware updates only TXCMD but doesn't take WTBL into
+                * account, so driver should update here to reflect the
+                * actual txrate hardware sends out.
+                */
+               addr = mt7915_mac_wtbl_lmac_addr(dev, msta->wcid.idx, 7);
+               if (sta->he_cap.has_he)
+                       mt76_rmw_field(dev, addr, GENMASK(31, 24), phy.sgi);
+               else
+                       mt76_rmw_field(dev, addr, GENMASK(15, 12), phy.sgi);
+
+               ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
+                                                    RATE_PARAM_FIXED_GI);
+               if (ret)
+                       return ret;
+       }
+
+       /* fixed HE_LTF */
+       if (mask->control[band].he_ltf != GENMASK(7, 0)) {
+               ret = mt7915_mcu_set_fixed_rate_ctrl(dev, vif, sta, &phy,
+                                                    RATE_PARAM_FIXED_HE_LTF);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static void
 mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                             struct ieee80211_vif *vif, struct ieee80211_sta *sta)
@@ -2092,8 +2214,6 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
        }
 
        if (sta->ht_cap.ht_supported) {
-               const u8 *mcs_mask = mask->control[band].ht_mcs;
-
                ra->supp_mode |= MODE_HT;
                ra->af = sta->ht_cap.ampdu_factor;
                ra->ht_gf = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD);
@@ -2111,12 +2231,12 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                    (sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
                        cap |= STA_CAP_LDPC;
 
-               mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs, mcs_mask);
+               mt7915_mcu_set_sta_ht_mcs(sta, ra->ht_mcs,
+                                         mask->control[band].ht_mcs);
                ra->supp_ht_mcs = *(__le32 *)ra->ht_mcs;
        }
 
        if (sta->vht_cap.vht_supported) {
-               const u16 *mcs_mask = mask->control[band].vht_mcs;
                u8 af;
 
                ra->supp_mode |= MODE_VHT;
@@ -2137,7 +2257,8 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                    (sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
                        cap |= STA_CAP_VHT_LDPC;
 
-               mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs, mcs_mask);
+               mt7915_mcu_set_sta_vht_mcs(sta, ra->supp_vht_mcs,
+                                          mask->control[band].vht_mcs);
        }
 
        if (sta->he_cap.has_he) {
@@ -2149,44 +2270,40 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
 }
 
 int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                            struct ieee80211_sta *sta)
+                            struct ieee80211_sta *sta, bool changed)
 {
        struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
        struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
        struct sk_buff *skb;
-       int len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_ra);
+       int ret;
 
-       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
+       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta,
+                                      MT7915_STA_UPDATE_MAX_SIZE);
        if (IS_ERR(skb))
                return PTR_ERR(skb);
 
-       mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
-
-       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-                                    MCU_EXT_CMD(STA_REC_UPDATE), true);
-}
-
-int mt7915_mcu_add_he(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                     struct ieee80211_sta *sta)
-{
-       struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
-       struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
-       struct sk_buff *skb;
-       int len;
-
-       if (!sta->he_cap.has_he)
-               return 0;
-
-       len = sizeof(struct sta_req_hdr) + sizeof(struct sta_rec_he);
+       /* firmware rc algorithm refers to sta_rec_he for HE control.
+        * once dev->rc_work changes the settings driver should also
+        * update sta_rec_he here.
+        */
+       if (sta->he_cap.has_he && changed)
+               mt7915_mcu_sta_he_tlv(skb, sta, vif);
 
-       skb = mt7915_mcu_alloc_sta_req(dev, mvif, msta, len);
-       if (IS_ERR(skb))
-               return PTR_ERR(skb);
+       /* sta_rec_ra accommodates BW, NSS and only MCS range format
+        * i.e 0-{7,8,9} for VHT.
+        */
+       mt7915_mcu_sta_rate_ctrl_tlv(skb, dev, vif, sta);
 
-       mt7915_mcu_sta_he_tlv(skb, sta, vif);
+       ret = mt76_mcu_skb_send_msg(&dev->mt76, skb,
+                                   MCU_EXT_CMD(STA_REC_UPDATE), true);
+       if (ret)
+               return ret;
 
-       return mt76_mcu_skb_send_msg(&dev->mt76, skb,
-                                    MCU_EXT_CMD(STA_REC_UPDATE), true);
+       /* sta_rec_ra_fixed accommodates single rate, (HE)GI and HE_LTE,
+        * and updates as peer fixed rate parameters, which overrides
+        * sta_rec_ra and firmware rate control algorithm.
+        */
+       return mt7915_mcu_add_rate_ctrl_fixed(dev, vif, sta);
 }
 
 static int
@@ -2443,9 +2560,8 @@ mt7915_mcu_beacon_check_caps(struct mt7915_phy *phy, struct ieee80211_vif *vif,
                              len);
        if (ie && ie[1] >= sizeof(*ht)) {
                ht = (void *)(ie + 2);
-               bc = le32_to_cpu(ht->cap_info);
-
-               vc->ldpc |= !!(bc & IEEE80211_HT_CAP_LDPC_CODING);
+               vc->ldpc |= !!(le16_to_cpu(ht->cap_info) &
+                              IEEE80211_HT_CAP_LDPC_CODING);
        }
 
        ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, mgmt->u.beacon.variable,
@@ -2863,7 +2979,7 @@ static int mt7915_load_firmware(struct mt7915_dev *dev)
        return 0;
 }
 
-int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl)
+int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl)
 {
        struct {
                u8 ctrl_val;
@@ -2872,6 +2988,10 @@ int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl)
                .ctrl_val = ctrl
        };
 
+       if (type == MCU_FW_LOG_WA)
+               return mt76_mcu_send_msg(&dev->mt76, MCU_WA_EXT_CMD(FW_LOG_2_HOST),
+                                        &data, sizeof(data), true);
+
        return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(FW_LOG_2_HOST), &data,
                                 sizeof(data), true);
 }
@@ -2984,7 +3104,11 @@ int mt7915_mcu_init(struct mt7915_dev *dev)
                return ret;
 
        set_bit(MT76_STATE_MCU_RUNNING, &dev->mphy.state);
-       ret = mt7915_mcu_fw_log_2_host(dev, 0);
+       ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WM, 0);
+       if (ret)
+               return ret;
+
+       ret = mt7915_mcu_fw_log_2_host(dev, MCU_FW_LOG_WA, 0);
        if (ret)
                return ret;
 
index d66918d..1f5a64b 100644 (file)
@@ -229,6 +229,11 @@ enum {
        MCU_S2D_H2CN
 };
 
+enum {
+       MCU_FW_LOG_WM,
+       MCU_FW_LOG_WA,
+       MCU_FW_LOG_TO_HOST,
+};
 
 #define __MCU_CMD_FIELD_ID     GENMASK(7, 0)
 #define __MCU_CMD_FIELD_EXT_ID GENMASK(15, 8)
@@ -304,6 +309,8 @@ enum {
 };
 
 enum {
+       MCU_WA_PARAM_PDMA_RX = 0x04,
+       MCU_WA_PARAM_CPU_UTIL = 0x0b,
        MCU_WA_PARAM_RED = 0x0e,
 };
 
@@ -886,7 +893,7 @@ struct sta_rec_sec {
        struct sec_key key[2];
 } __packed;
 
-struct ra_phy {
+struct sta_phy {
        u8 type;
        u8 flag;
        u8 stbc;
@@ -930,7 +937,7 @@ struct sta_rec_ra {
 
        __le32 sta_cap;
 
-       struct ra_phy phy;
+       struct sta_phy phy;
 } __packed;
 
 struct sta_rec_ra_fixed {
@@ -943,7 +950,7 @@ struct sta_rec_ra_fixed {
        u8 op_vht_rx_nss;
        u8 op_vht_rx_nss_type;
 
-       struct ra_phy phy;
+       struct sta_phy phy;
 
        u8 spe_en;
        u8 short_preamble;
@@ -951,8 +958,14 @@ struct sta_rec_ra_fixed {
        u8 mmps_mode;
 } __packed;
 
-#define RATE_PARAM_FIXED               3
-#define RATE_PARAM_AUTO                        20
+enum {
+       RATE_PARAM_FIXED = 3,
+       RATE_PARAM_FIXED_HE_LTF = 7,
+       RATE_PARAM_FIXED_MCS,
+       RATE_PARAM_FIXED_GI = 11,
+       RATE_PARAM_AUTO = 20,
+};
+
 #define RATE_CFG_MCS                   GENMASK(3, 0)
 #define RATE_CFG_NSS                   GENMASK(7, 4)
 #define RATE_CFG_GI                    GENMASK(11, 8)
index 7bbb38e..1f6ba30 100644 (file)
@@ -34,6 +34,9 @@ static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
                u32 mapped;
                u32 size;
        } fixed_map[] = {
+               { 0x00400000, 0x80000, 0x10000 }, /* WF_MCU_SYSRAM */
+               { 0x00410000, 0x90000, 0x10000 }, /* WF_MCU_SYSRAM (configure regs) */
+               { 0x40000000, 0x70000, 0x10000 }, /* WF_UMAC_SYSRAM */
                { 0x54000000, 0x02000, 0x1000 }, /* WFDMA PCIE0 MCU DMA0 */
                { 0x55000000, 0x03000, 0x1000 }, /* WFDMA PCIE0 MCU DMA1 */
                { 0x58000000, 0x06000, 0x1000 }, /* WFDMA PCIE1 MCU DMA0 (MEM_DMA) */
index fff15f6..e69b4c8 100644 (file)
@@ -270,8 +270,9 @@ struct mt7915_dev {
 
        bool dbdc_support;
        bool flash_mode;
-       bool fw_debug;
        bool ibf;
+       u8 fw_debug_wm;
+       u8 fw_debug_wa;
 
        void *cal;
 
@@ -409,17 +410,17 @@ int mt7915_mcu_add_beacon(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                             bool enable);
 int mt7915_mcu_add_rate_ctrl(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                            struct ieee80211_sta *sta);
-int mt7915_mcu_add_he(struct mt7915_dev *dev, struct ieee80211_vif *vif,
-                     struct ieee80211_sta *sta);
+                            struct ieee80211_sta *sta, bool changed);
 int mt7915_mcu_add_smps(struct mt7915_dev *dev, struct ieee80211_vif *vif,
                        struct ieee80211_sta *sta);
 int mt7915_set_channel(struct mt7915_phy *phy);
 int mt7915_mcu_set_chan_info(struct mt7915_phy *phy, int cmd);
 int mt7915_mcu_set_tx(struct mt7915_dev *dev, struct ieee80211_vif *vif);
 int mt7915_mcu_update_edca(struct mt7915_dev *dev, void *req);
-int mt7915_mcu_set_fixed_rate(struct mt7915_dev *dev,
-                             struct ieee80211_sta *sta, u32 rate);
+int mt7915_mcu_set_fixed_rate_ctrl(struct mt7915_dev *dev,
+                                  struct ieee80211_vif *vif,
+                                  struct ieee80211_sta *sta,
+                                  void *data, u32 field);
 int mt7915_mcu_set_eeprom(struct mt7915_dev *dev);
 int mt7915_mcu_get_eeprom(struct mt7915_dev *dev, u32 offset);
 int mt7915_mcu_set_mac(struct mt7915_dev *dev, int band, bool enable,
@@ -449,7 +450,8 @@ int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif,
                           struct ieee80211_sta *sta, struct rate_info *rate);
 int mt7915_mcu_rdd_cmd(struct mt7915_dev *dev, enum mt7915_rdd_cmd cmd,
                       u8 index, u8 rx_sel, u8 val);
-int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 ctrl);
+int mt7915_mcu_wa_cmd(struct mt7915_dev *dev, int cmd, u32 a1, u32 a2, u32 a3);
+int mt7915_mcu_fw_log_2_host(struct mt7915_dev *dev, u8 type, u8 ctrl);
 int mt7915_mcu_fw_dbg_ctrl(struct mt7915_dev *dev, u32 module, u8 level);
 void mt7915_mcu_rx_event(struct mt7915_dev *dev, struct sk_buff *skb);
 void mt7915_mcu_exit(struct mt7915_dev *dev);
@@ -480,6 +482,7 @@ static inline void mt7915_irq_disable(struct mt7915_dev *dev, u32 mask)
                mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
 }
 
+u32 mt7915_mac_wtbl_lmac_addr(struct mt7915_dev *dev, u16 wcid, u8 dw);
 bool mt7915_mac_wtbl_update(struct mt7915_dev *dev, int idx, u32 mask);
 void mt7915_mac_reset_counters(struct mt7915_phy *phy);
 void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy);
index a2e9878..5969353 100644 (file)
 #define MT_HIF_REMAP_L2_BASE           GENMASK(31, 12)
 #define MT_HIF_REMAP_BASE_L2           0x00000
 
+#define MT_DIC_CMD_REG_BASE            0x41f000
+#define MT_DIC_CMD_REG(ofs)            (MT_DIC_CMD_REG_BASE + (ofs))
+#define MT_DIC_CMD_REG_CMD             MT_DIC_CMD_REG(0x10)
+
+#define MT_CPU_UTIL_BASE               0x41f030
+#define MT_CPU_UTIL(ofs)               (MT_CPU_UTIL_BASE + (ofs))
+#define MT_CPU_UTIL_BUSY_PCT           MT_CPU_UTIL(0x00)
+#define MT_CPU_UTIL_PEAK_BUSY_PCT      MT_CPU_UTIL(0x04)
+#define MT_CPU_UTIL_IDLE_CNT           MT_CPU_UTIL(0x08)
+#define MT_CPU_UTIL_PEAK_IDLE_CNT      MT_CPU_UTIL(0x0c)
+#define MT_CPU_UTIL_CTRL               MT_CPU_UTIL(0x1c)
+
 #define MT_SWDEF_BASE                  0x41f200
 #define MT_SWDEF(ofs)                  (MT_SWDEF_BASE + (ofs))
 #define MT_SWDEF_MODE                  MT_SWDEF(0x3c)
 #define MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY      BIT(18)
 #define MT_WF_PHY_RXTD12_IRPI_SW_CLR   BIT(29)
 
+#define MT_MCU_WM_CIRQ_BASE                    0x89010000
+#define MT_MCU_WM_CIRQ(ofs)                    (MT_MCU_WM_CIRQ_BASE + (ofs))
+#define MT_MCU_WM_CIRQ_IRQ_MASK_CLR_ADDR       MT_MCU_WM_CIRQ(0x80)
+#define MT_MCU_WM_CIRQ_IRQ_SOFT_ADDR           MT_MCU_WM_CIRQ(0xc0)
+
 #endif
index 8726504..210998f 100644 (file)
@@ -62,7 +62,8 @@ mt7921_init_wiphy(struct ieee80211_hw *hw)
        hw->vif_data_size = sizeof(struct mt7921_vif);
 
        wiphy->iface_combinations = if_comb;
-       wiphy->flags &= ~WIPHY_FLAG_IBSS_RSN;
+       wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
+                         WIPHY_FLAG_4ADDR_STATION);
        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
        wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
        wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
index 1c363ea..49c52d7 100644 (file)
@@ -70,17 +70,15 @@ mt76_worker_setup(struct ieee80211_hw *hw, struct mt76_worker *w,
 
        if (fn)
                w->fn = fn;
-       w->task = kthread_create(__mt76_worker_fn, w, "mt76-%s %s",
-                                name, dev_name);
+       w->task = kthread_run(__mt76_worker_fn, w,
+                             "mt76-%s %s", name, dev_name);
 
-       ret = PTR_ERR_OR_ZERO(w->task);
-       if (ret) {
+       if (IS_ERR(w->task)) {
+               ret = PTR_ERR(w->task);
                w->task = NULL;
                return ret;
        }
 
-       wake_up_process(w->task);
-
        return 0;
 }
 
index 5857842..4efab90 100644 (file)
@@ -28,7 +28,7 @@ u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
        usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
                        RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
                        (unsigned long)addr, idx & 0x03,
-                       &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
+                       &priv->io_dmabuf->bits8, sizeof(val), 500);
 
        val = priv->io_dmabuf->bits8;
        mutex_unlock(&priv->io_mutex);
@@ -45,7 +45,7 @@ u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
        usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
                        RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
                        (unsigned long)addr, idx & 0x03,
-                       &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
+                       &priv->io_dmabuf->bits16, sizeof(val), 500);
 
        val = priv->io_dmabuf->bits16;
        mutex_unlock(&priv->io_mutex);
@@ -62,7 +62,7 @@ u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
        usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
                        RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
                        (unsigned long)addr, idx & 0x03,
-                       &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
+                       &priv->io_dmabuf->bits32, sizeof(val), 500);
 
        val = priv->io_dmabuf->bits32;
        mutex_unlock(&priv->io_mutex);
@@ -79,7 +79,7 @@ void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
                        (unsigned long)addr, idx & 0x03,
-                       &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
+                       &priv->io_dmabuf->bits8, sizeof(val), 500);
 
        mutex_unlock(&priv->io_mutex);
 }
@@ -93,7 +93,7 @@ void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
                        (unsigned long)addr, idx & 0x03,
-                       &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
+                       &priv->io_dmabuf->bits16, sizeof(val), 500);
 
        mutex_unlock(&priv->io_mutex);
 }
@@ -107,7 +107,7 @@ void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
                        (unsigned long)addr, idx & 0x03,
-                       &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
+                       &priv->io_dmabuf->bits32, sizeof(val), 500);
 
        mutex_unlock(&priv->io_mutex);
 }
@@ -183,7 +183,7 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
        usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
                        RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
                        addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
-                       HZ / 2);
+                       500);
 
        mutex_unlock(&priv->io_mutex);
 
index 06fb6e5..d02ec5a 100644 (file)
@@ -1412,7 +1412,7 @@ static void rtw89_core_ba_work(struct work_struct *work)
        list_for_each_entry_safe(rtwtxq, tmp, &rtwdev->ba_list, list) {
                struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
                struct ieee80211_sta *sta = txq->sta;
-               struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+               struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
                u8 tid = txq->tid;
 
                if (!sta) {
@@ -1462,7 +1462,7 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
        struct ieee80211_hw *hw = rtwdev->hw;
        struct ieee80211_txq *txq = rtw89_txq_to_txq(rtwtxq);
        struct ieee80211_sta *sta = txq->sta;
-       struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+       struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
 
        if (unlikely(skb_get_queue_mapping(skb) == IEEE80211_AC_VO))
                return;
@@ -1534,7 +1534,7 @@ static bool rtw89_core_txq_agg_wait(struct rtw89_dev *rtwdev,
 {
        struct rtw89_txq *rtwtxq = (struct rtw89_txq *)txq->drv_priv;
        struct ieee80211_sta *sta = txq->sta;
-       struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
+       struct rtw89_sta *rtwsta = sta ? (struct rtw89_sta *)sta->drv_priv : NULL;
 
        if (!sta || rtwsta->max_agg_wait <= 0)
                return false;
index 69384c4..afcd07a 100644 (file)
@@ -560,7 +560,7 @@ static int hfc_pub_cfg_chk(struct rtw89_dev *rtwdev)
        const struct rtw89_hfc_pub_cfg *pub_cfg = &param->pub_cfg;
 
        if (pub_cfg->grp0 + pub_cfg->grp1 != pub_cfg->pub_max)
-               return 0;
+               return -EFAULT;
 
        return 0;
 }
index 34333c4..20e6767 100644 (file)
 #define B_AX_CH10_BUSY                 BIT(0)
 
 /* Configure */
-#define R_AX_PCIE_INIT_CFG1    0x1000
-#define B_AX_PCIE_RXRST_KEEP_REG       BIT(23)
-#define B_AX_PCIE_TXRST_KEEP_REG       BIT(22)
-#define B_AX_DIS_RXDMA_PRE             BIT(2)
-
 #define R_AX_PCIE_INIT_CFG2            0x1004
 #define B_AX_WD_ITVL_IDLE              GENMASK(27, 24)
 #define B_AX_WD_ITVL_ACT               GENMASK(19, 16)
index b1b87f0..5c6ffca 100644 (file)
@@ -757,7 +757,7 @@ static void rtw8852a_ctrl_ch(struct rtw89_dev *rtwdev, u8 central_ch,
                else
                        rtw89_phy_write32_idx(rtwdev, R_P1_MODE,
                                              B_P1_MODE_SEL,
-                                             1, phy_idx);
+                                             0, phy_idx);
                /* SCO compensate FC setting */
                sco_comp = rtw8852a_sco_mapping(central_ch);
                rtw89_phy_write32_idx(rtwdev, R_FC0_BW, B_FC0_BW_INV,
index 6a12021..6821ea9 100644 (file)
@@ -58,7 +58,7 @@ static int rsi_usb_card_write(struct rsi_hw *adapter,
                              (void *)seg,
                              (int)len,
                              &transfer,
-                             HZ * 5);
+                             USB_CTRL_SET_TIMEOUT);
 
        if (status < 0) {
                rsi_dbg(ERR_ZONE,
index f26fc15..354a7e1 100644 (file)
@@ -488,12 +488,9 @@ static int wl1271_probe(struct spi_device *spi)
        spi->bits_per_word = 32;
 
        glue->reg = devm_regulator_get(&spi->dev, "vwlan");
-       if (PTR_ERR(glue->reg) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
-       if (IS_ERR(glue->reg)) {
-               dev_err(glue->dev, "can't get regulator\n");
-               return PTR_ERR(glue->reg);
-       }
+       if (IS_ERR(glue->reg))
+               return dev_err_probe(glue->dev, PTR_ERR(glue->reg),
+                                    "can't get regulator\n");
 
        ret = wlcore_probe_of(spi, glue, pdev_data);
        if (ret) {