Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
authorKalle Valo <kvalo@codeaurora.org>
Thu, 3 Oct 2019 13:39:51 +0000 (16:39 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 3 Oct 2019 13:39:51 +0000 (16:39 +0300)
ath.git patches for 5.5. Major changes:

ath10k

* add support for hardware rfkill on devices where firmware supports it

31 files changed:
Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
drivers/net/wireless/ath/ar5523/ar5523.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/coredump.c
drivers/net/wireless/ath/ath10k/coredump.h
drivers/net/wireless/ath/ath10k/debugfs_sta.c
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/hw.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/mac.h
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/qmi.c
drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.c
drivers/net/wireless/ath/ath10k/qmi_wlfw_v01.h
drivers/net/wireless/ath/ath10k/sdio.c
drivers/net/wireless/ath/ath10k/snoc.c
drivers/net/wireless/ath/ath10k/snoc.h
drivers/net/wireless/ath/ath10k/usb.c
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi-tlv.h
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath5k/pci.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/pci.c
drivers/net/wireless/ath/wil6210/pcie_bus.c
drivers/net/wireless/ath/wil6210/wmi.c

index ae661e6..0171283 100644 (file)
@@ -81,6 +81,12 @@ Optional properties:
        Definition: Name of external front end module used. Some valid FEM names
                    for example: "microsemi-lx5586", "sky85703-11"
                    and "sky85803" etc.
+- qcom,snoc-host-cap-8bit-quirk:
+       Usage: Optional
+       Value type: <empty>
+       Definition: Quirk specifying that the firmware expects the 8bit version
+                   of the host capability QMI request
+- qcom,xo-cal-data: xo cal offset to be configured in xo trim register.
 
 Example (to supply PCI based wifi block details):
 
index b94759d..da2d179 100644 (file)
@@ -255,7 +255,8 @@ static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata,
 
        if (flags & AR5523_CMD_FLAG_MAGIC)
                hdr->magic = cpu_to_be32(1 << 24);
-       memcpy(hdr + 1, idata, ilen);
+       if (ilen)
+               memcpy(hdr + 1, idata, ilen);
 
        cmd->odata = odata;
        cmd->olen = olen;
index dc45d16..36c62d6 100644 (file)
@@ -677,13 +677,22 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
        complete(&ar->target_suspend);
 }
 
-static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
+static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
+       int ret;
        u32 param = 0;
 
-       ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
-       ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
-       ath10k_bmi_read32(ar, hi_acs_flags, &param);
+       ret = ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256);
+       if (ret)
+               return ret;
+
+       ret = ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99);
+       if (ret)
+               return ret;
+
+       ret = ath10k_bmi_read32(ar, hi_acs_flags, &param);
+       if (ret)
+               return ret;
 
        /* Data transfer is not initiated, when reduced Tx completion
         * is used for SDIO. disable it until fixed
@@ -700,14 +709,23 @@ static void ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
        else
                param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET;
 
-       ath10k_bmi_write32(ar, hi_acs_flags, param);
+       ret = ath10k_bmi_write32(ar, hi_acs_flags, param);
+       if (ret)
+               return ret;
 
        /* Explicitly set fwlog prints to zero as target may turn it on
         * based on scratch registers.
         */
-       ath10k_bmi_read32(ar, hi_option_flag, &param);
+       ret = ath10k_bmi_read32(ar, hi_option_flag, &param);
+       if (ret)
+               return ret;
+
        param |= HI_OPTION_DISABLE_DBGLOG;
-       ath10k_bmi_write32(ar, hi_option_flag, param);
+       ret = ath10k_bmi_write32(ar, hi_option_flag, param);
+       if (ret)
+               return ret;
+
+       return 0;
 }
 
 static int ath10k_init_configure_target(struct ath10k *ar)
@@ -2118,12 +2136,15 @@ static int ath10k_init_uart(struct ath10k *ar)
                return ret;
        }
 
-       if (!uart_print && ar->hw_params.uart_pin_workaround) {
-               ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin,
-                                        ar->hw_params.uart_pin);
-               if (ret) {
-                       ath10k_warn(ar, "failed to set UART TX pin: %d", ret);
-                       return ret;
+       if (!uart_print) {
+               if (ar->hw_params.uart_pin_workaround) {
+                       ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin,
+                                                ar->hw_params.uart_pin);
+                       if (ret) {
+                               ath10k_warn(ar, "failed to set UART TX pin: %d",
+                                           ret);
+                               return ret;
+                       }
                }
 
                return 0;
@@ -2562,8 +2583,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
                if (status)
                        goto err;
 
-               if (ar->hif.bus == ATH10K_BUS_SDIO)
-                       ath10k_init_sdio(ar, mode);
+               if (ar->hif.bus == ATH10K_BUS_SDIO) {
+                       status = ath10k_init_sdio(ar, mode);
+                       if (status) {
+                               ath10k_err(ar, "failed to init SDIO: %d\n", status);
+                               goto err;
+                       }
+               }
        }
 
        ar->htc.htc_ops.target_send_suspend_complete =
@@ -2784,7 +2810,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
 
        status = ath10k_hif_set_target_log_mode(ar, fw_diag_log);
        if (status && status != -EOPNOTSUPP) {
-               ath10k_warn(ar, "set traget log mode faileds: %d\n", status);
+               ath10k_warn(ar, "set target log mode failed: %d\n", status);
                goto err_hif_stop;
        }
 
index 4d7db07..af68eb5 100644 (file)
@@ -169,6 +169,7 @@ struct ath10k_wmi {
        struct wmi_cmd_map *cmd;
        struct wmi_vdev_param_map *vdev_param;
        struct wmi_pdev_param_map *pdev_param;
+       struct wmi_peer_param_map *peer_param;
        const struct wmi_ops *ops;
        const struct wmi_peer_flags_map *peer_flags;
 
@@ -963,12 +964,20 @@ struct ath10k {
        u32 hw_eeprom_rd;
        u32 ht_cap_info;
        u32 vht_cap_info;
+       u32 vht_supp_mcs;
        u32 num_rf_chains;
        u32 max_spatial_stream;
        /* protected by conf_mutex */
+       u32 low_2ghz_chan;
+       u32 high_2ghz_chan;
        u32 low_5ghz_chan;
        u32 high_5ghz_chan;
        bool ani_enabled;
+       u32 sys_cap_info;
+
+       /* protected by data_lock */
+       bool hw_rfkill_on;
+
        /* protected by conf_mutex */
        u8 ps_state_enable;
 
index b6d2932..2a44980 100644 (file)
@@ -703,7 +703,7 @@ static const struct ath10k_mem_region qca99x0_hw20_mem_regions[] = {
        },
        {
                .type = ATH10K_MEM_REGION_TYPE_REG,
-               .start = 0x98000,
+               .start = 0x980000,
                .len = 0x50000,
                .name = "IRAM",
                .section_table = {
@@ -786,7 +786,7 @@ static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = {
        },
        {
                .type = ATH10K_MEM_REGION_TYPE_REG,
-               .start = 0x98000,
+               .start = 0x980000,
                .len = 0x50000,
                .name = "IRAM",
                .section_table = {
@@ -891,7 +891,7 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
        },
        {
                .type = ATH10K_MEM_REGION_TYPE_REG,
-               .start = 0x98000,
+               .start = 0x980000,
                .len = 0x50000,
                .name = "IRAM",
                .section_table = {
@@ -951,6 +951,19 @@ static const struct ath10k_mem_region qca4019_hw10_mem_regions[] = {
        },
 };
 
+static const struct ath10k_mem_region wcn399x_hw10_mem_regions[] = {
+       {
+               /* MSA region start is not fixed, hence it is assigned at runtime */
+               .type = ATH10K_MEM_REGION_TYPE_MSA,
+               .len = 0x100000,
+               .name = "DRAM",
+               .section_table = {
+                       .sections = NULL,
+                       .size = 0,
+               },
+       },
+};
+
 static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
        {
                .hw_id = QCA6174_HW_1_0_VERSION,
@@ -1048,6 +1061,14 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
                        .size = ARRAY_SIZE(qca4019_hw10_mem_regions),
                },
        },
+       {
+               .hw_id = WCN3990_HW_1_0_DEV_VERSION,
+               .hw_rev = ATH10K_HW_WCN3990,
+               .region_table = {
+                       .regions = wcn399x_hw10_mem_regions,
+                       .size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
+               },
+       },
 };
 
 static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar)
@@ -1208,9 +1229,11 @@ static struct ath10k_dump_file_data *ath10k_coredump_build(struct ath10k *ar)
                dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
                dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_RAM_DATA);
                dump_tlv->tlv_len = cpu_to_le32(crash_data->ramdump_buf_len);
-               memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
-                      crash_data->ramdump_buf_len);
-               sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
+               if (crash_data->ramdump_buf_len) {
+                       memcpy(dump_tlv->tlv_data, crash_data->ramdump_buf,
+                              crash_data->ramdump_buf_len);
+                       sofar += sizeof(*dump_tlv) + crash_data->ramdump_buf_len;
+               }
        }
 
        mutex_unlock(&ar->dump_mutex);
@@ -1257,6 +1280,9 @@ int ath10k_coredump_register(struct ath10k *ar)
        if (test_bit(ATH10K_FW_CRASH_DUMP_RAM_DATA, &ath10k_coredump_mask)) {
                crash_data->ramdump_buf_len = ath10k_coredump_get_ramdump_size(ar);
 
+               if (!crash_data->ramdump_buf_len)
+                       return 0;
+
                crash_data->ramdump_buf = vzalloc(crash_data->ramdump_buf_len);
                if (!crash_data->ramdump_buf)
                        return -ENOMEM;
index 09de419..8bf03e8 100644 (file)
@@ -115,6 +115,7 @@ enum ath10k_mem_region_type {
        ATH10K_MEM_REGION_TYPE_IRAM2    = 5,
        ATH10K_MEM_REGION_TYPE_IOSRAM   = 6,
        ATH10K_MEM_REGION_TYPE_IOREG    = 7,
+       ATH10K_MEM_REGION_TYPE_MSA      = 8,
 };
 
 /* Define a section of the region which should be copied. As not all parts
index 42931a6..367539f 100644 (file)
@@ -430,7 +430,7 @@ ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
        }
 
        ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
-                                       WMI_PEER_DEBUG, peer_debug_trigger);
+                                       ar->wmi.peer_param->debug, peer_debug_trigger);
        if (ret) {
                ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
                            ret);
index 53f1095..9f0e7b4 100644 (file)
@@ -2726,7 +2726,7 @@ static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
                spin_lock_bh(&ar->data_lock);
 
                peer = ath10k_peer_find_by_id(ar, peer_id);
-               if (!peer) {
+               if (!peer || !peer->sta) {
                        spin_unlock_bh(&ar->data_lock);
                        rcu_read_unlock();
                        continue;
index c415e97..5584917 100644 (file)
@@ -155,6 +155,9 @@ const struct ath10k_hw_values qca6174_values = {
        .num_target_ce_config_wlan      = 7,
        .ce_desc_meta_data_mask         = 0xFFFC,
        .ce_desc_meta_data_lsb          = 2,
+       .rfkill_pin                     = 16,
+       .rfkill_cfg                     = 0,
+       .rfkill_on_level                = 1,
 };
 
 const struct ath10k_hw_values qca99x0_values = {
index 2ae57c1..35a3623 100644 (file)
@@ -379,6 +379,9 @@ struct ath10k_hw_values {
        u8 num_target_ce_config_wlan;
        u16 ce_desc_meta_data_mask;
        u8 ce_desc_meta_data_lsb;
+       u32 rfkill_pin;
+       u32 rfkill_cfg;
+       bool rfkill_on_level;
 };
 
 extern const struct ath10k_hw_values qca988x_values;
index a6d2185..3d2c8fc 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/etherdevice.h>
 #include <linux/acpi.h>
 #include <linux/of.h>
+#include <linux/bitfield.h>
 
 #include "hif.h"
 #include "core.h"
@@ -2773,7 +2774,7 @@ static int ath10k_setup_peer_smps(struct ath10k *ar, struct ath10k_vif *arvif,
                return -EINVAL;
 
        return ath10k_wmi_peer_set_param(ar, arvif->vdev_id, addr,
-                                        WMI_PEER_SMPS_STATE,
+                                        ar->wmi.peer_param->smps_state,
                                         ath10k_smps_map[smps]);
 }
 
@@ -2930,7 +2931,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
         * poked with peer param command.
         */
        ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, arvif->bssid,
-                                       WMI_PEER_DUMMY_VAR, 1);
+                                       ar->wmi.peer_param->dummy_var, 1);
        if (ret) {
                ath10k_warn(ar, "failed to poke peer %pM param for ps workaround on vdev %i: %d\n",
                            arvif->bssid, arvif->vdev_id, ret);
@@ -3708,7 +3709,7 @@ static int ath10k_mac_tx(struct ath10k *ar,
                         struct ieee80211_vif *vif,
                         enum ath10k_hw_txrx_mode txmode,
                         enum ath10k_mac_tx_path txpath,
-                        struct sk_buff *skb)
+                        struct sk_buff *skb, bool noque_offchan)
 {
        struct ieee80211_hw *hw = ar->hw;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -3738,10 +3739,10 @@ static int ath10k_mac_tx(struct ath10k *ar,
                }
        }
 
-       if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
+       if (!noque_offchan && info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
                if (!ath10k_mac_tx_frm_has_freq(ar)) {
-                       ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %pK\n",
-                                  skb);
+                       ath10k_dbg(ar, ATH10K_DBG_MAC, "mac queued offchannel skb %pK len %d\n",
+                                  skb, skb->len);
 
                        skb_queue_tail(&ar->offchan_tx_queue, skb);
                        ieee80211_queue_work(hw, &ar->offchan_tx_work);
@@ -3803,8 +3804,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
 
                mutex_lock(&ar->conf_mutex);
 
-               ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK\n",
-                          skb);
+               ath10k_dbg(ar, ATH10K_DBG_MAC, "mac offchannel skb %pK len %d\n",
+                          skb, skb->len);
 
                hdr = (struct ieee80211_hdr *)skb->data;
                peer_addr = ieee80211_get_DA(hdr);
@@ -3850,7 +3851,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
                txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
                txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
 
-               ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
+               ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, true);
                if (ret) {
                        ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
                                    ret);
@@ -3860,8 +3861,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
                time_left =
                wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
                if (time_left == 0)
-                       ath10k_warn(ar, "timed out waiting for offchannel skb %pK\n",
-                                   skb);
+                       ath10k_warn(ar, "timed out waiting for offchannel skb %pK, len: %d\n",
+                                   skb, skb->len);
 
                if (!peer && tmp_peer_created) {
                        ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
@@ -4065,7 +4066,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
        if (ret)
                return ret;
 
-       skb = ieee80211_tx_dequeue(hw, txq);
+       skb = ieee80211_tx_dequeue_ni(hw, txq);
        if (!skb) {
                spin_lock_bh(&ar->htt.tx_lock);
                ath10k_htt_tx_dec_pending(htt);
@@ -4097,7 +4098,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
                spin_unlock_bh(&ar->htt.tx_lock);
        }
 
-       ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
+       ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
        if (unlikely(ret)) {
                ath10k_warn(ar, "failed to push frame: %d\n", ret);
 
@@ -4378,7 +4379,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
                spin_unlock_bh(&ar->htt.tx_lock);
        }
 
-       ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
+       ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb, false);
        if (ret) {
                ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
                if (is_htt) {
@@ -4754,6 +4755,63 @@ static int __ath10k_fetch_bb_timing_dt(struct ath10k *ar,
        return 0;
 }
 
+static int ath10k_mac_rfkill_config(struct ath10k *ar)
+{
+       u32 param;
+       int ret;
+
+       if (ar->hw_values->rfkill_pin == 0) {
+               ath10k_warn(ar, "ath10k does not support hardware rfkill with this device\n");
+               return -EOPNOTSUPP;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_MAC,
+                  "mac rfkill_pin %d rfkill_cfg %d rfkill_on_level %d",
+                  ar->hw_values->rfkill_pin, ar->hw_values->rfkill_cfg,
+                  ar->hw_values->rfkill_on_level);
+
+       param = FIELD_PREP(WMI_TLV_RFKILL_CFG_RADIO_LEVEL,
+                          ar->hw_values->rfkill_on_level) |
+               FIELD_PREP(WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM,
+                          ar->hw_values->rfkill_pin) |
+               FIELD_PREP(WMI_TLV_RFKILL_CFG_PIN_AS_GPIO,
+                          ar->hw_values->rfkill_cfg);
+
+       ret = ath10k_wmi_pdev_set_param(ar,
+                                       ar->wmi.pdev_param->rfkill_config,
+                                       param);
+       if (ret) {
+               ath10k_warn(ar,
+                           "failed to set rfkill config 0x%x: %d\n",
+                           param, ret);
+               return ret;
+       }
+       return 0;
+}
+
+int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable)
+{
+       enum wmi_tlv_rfkill_enable_radio param;
+       int ret;
+
+       if (enable)
+               param = WMI_TLV_RFKILL_ENABLE_RADIO_ON;
+       else
+               param = WMI_TLV_RFKILL_ENABLE_RADIO_OFF;
+
+       ath10k_dbg(ar, ATH10K_DBG_MAC, "mac rfkill enable %d", param);
+
+       ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rfkill_enable,
+                                       param);
+       if (ret) {
+               ath10k_warn(ar, "failed to set rfkill enable param %d: %d\n",
+                           param, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 static int ath10k_start(struct ieee80211_hw *hw)
 {
        struct ath10k *ar = hw->priv;
@@ -4788,6 +4846,16 @@ static int ath10k_start(struct ieee80211_hw *hw)
                goto err;
        }
 
+       spin_lock_bh(&ar->data_lock);
+
+       if (ar->hw_rfkill_on) {
+               ar->hw_rfkill_on = false;
+               spin_unlock_bh(&ar->data_lock);
+               goto err;
+       }
+
+       spin_unlock_bh(&ar->data_lock);
+
        ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL);
        if (ret) {
                ath10k_err(ar, "Could not init hif: %d\n", ret);
@@ -4801,6 +4869,14 @@ static int ath10k_start(struct ieee80211_hw *hw)
                goto err_power_down;
        }
 
+       if (ar->sys_cap_info & WMI_TLV_SYS_CAP_INFO_RFKILL) {
+               ret = ath10k_mac_rfkill_config(ar);
+               if (ret && ret != -EOPNOTSUPP) {
+                       ath10k_warn(ar, "failed to configure rfkill: %d", ret);
+                       goto err_core_stop;
+               }
+       }
+
        param = ar->wmi.pdev_param->pmf_qos;
        ret = ath10k_wmi_pdev_set_param(ar, param, 1);
        if (ret) {
@@ -4960,7 +5036,8 @@ static void ath10k_stop(struct ieee80211_hw *hw)
 
        mutex_lock(&ar->conf_mutex);
        if (ar->state != ATH10K_STATE_OFF) {
-               ath10k_halt(ar);
+               if (!ar->hw_rfkill_on)
+                       ath10k_halt(ar);
                ar->state = ATH10K_STATE_OFF;
        }
        mutex_unlock(&ar->conf_mutex);
@@ -5635,6 +5712,37 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
        mutex_unlock(&ar->conf_mutex);
 }
 
+static void ath10k_recalculate_mgmt_rate(struct ath10k *ar,
+                                        struct ieee80211_vif *vif,
+                                        struct cfg80211_chan_def *def)
+{
+       struct ath10k_vif *arvif = (void *)vif->drv_priv;
+       const struct ieee80211_supported_band *sband;
+       u8 basic_rate_idx;
+       int hw_rate_code;
+       u32 vdev_param;
+       u16 bitrate;
+       int ret;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       sband = ar->hw->wiphy->bands[def->chan->band];
+       basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
+       bitrate = sband->bitrates[basic_rate_idx].bitrate;
+
+       hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
+       if (hw_rate_code < 0) {
+               ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
+               return;
+       }
+
+       vdev_param = ar->wmi.vdev_param->mgmt_rate;
+       ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+                                       hw_rate_code);
+       if (ret)
+               ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
+}
+
 static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
                                    struct ieee80211_vif *vif,
                                    struct ieee80211_bss_conf *info,
@@ -5645,10 +5753,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
        struct cfg80211_chan_def def;
        u32 vdev_param, pdev_param, slottime, preamble;
        u16 bitrate, hw_value;
-       u8 rate, basic_rate_idx, rateidx;
-       int ret = 0, hw_rate_code, mcast_rate;
+       u8 rate, rateidx;
+       int ret = 0, mcast_rate;
        enum nl80211_band band;
-       const struct ieee80211_supported_band *sband;
 
        mutex_lock(&ar->conf_mutex);
 
@@ -5872,29 +5979,9 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
                                    arvif->vdev_id,  ret);
        }
 
-       if (changed & BSS_CHANGED_BASIC_RATES) {
-               if (ath10k_mac_vif_chan(vif, &def)) {
-                       mutex_unlock(&ar->conf_mutex);
-                       return;
-               }
-
-               sband = ar->hw->wiphy->bands[def.chan->band];
-               basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
-               bitrate = sband->bitrates[basic_rate_idx].bitrate;
-
-               hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate);
-               if (hw_rate_code < 0) {
-                       ath10k_warn(ar, "bitrate not supported %d\n", bitrate);
-                       mutex_unlock(&ar->conf_mutex);
-                       return;
-               }
-
-               vdev_param = ar->wmi.vdev_param->mgmt_rate;
-               ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
-                                               hw_rate_code);
-               if (ret)
-                       ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret);
-       }
+       if (changed & BSS_CHANGED_BASIC_RATES &&
+           !ath10k_mac_vif_chan(arvif->vif, &def))
+               ath10k_recalculate_mgmt_rate(ar, vif, &def);
 
        mutex_unlock(&ar->conf_mutex);
 }
@@ -6239,7 +6326,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
        if (sta && sta->tdls)
                ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-                                         WMI_PEER_AUTHORIZE, 1);
+                                         ar->wmi.peer_param->authorize, 1);
 
 exit:
        mutex_unlock(&ar->conf_mutex);
@@ -6330,7 +6417,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
                           sta->addr, bw, mode);
 
                err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-                                               WMI_PEER_PHYMODE, mode);
+                                               ar->wmi.peer_param->phymode, mode);
                if (err) {
                        ath10k_warn(ar, "failed to update STA %pM peer phymode %d: %d\n",
                                    sta->addr, mode, err);
@@ -6338,7 +6425,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
                }
 
                err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-                                               WMI_PEER_CHAN_WIDTH, bw);
+                                               ar->wmi.peer_param->chan_width, bw);
                if (err)
                        ath10k_warn(ar, "failed to update STA %pM peer bw %d: %d\n",
                                    sta->addr, bw, err);
@@ -6349,7 +6436,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
                           sta->addr, nss);
 
                err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-                                               WMI_PEER_NSS, nss);
+                                               ar->wmi.peer_param->nss, nss);
                if (err)
                        ath10k_warn(ar, "failed to update STA %pM nss %d: %d\n",
                                    sta->addr, nss, err);
@@ -6360,7 +6447,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
                           sta->addr, smps);
 
                err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-                                               WMI_PEER_SMPS_STATE, smps);
+                                               ar->wmi.peer_param->smps_state, smps);
                if (err)
                        ath10k_warn(ar, "failed to update STA %pM smps %d: %d\n",
                                    sta->addr, smps, err);
@@ -6434,7 +6521,7 @@ static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
        mutex_lock(&ar->conf_mutex);
 
        ret = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
-                                       WMI_PEER_USE_FIXED_PWR, txpwr);
+                                       ar->wmi.peer_param->use_fixed_power, txpwr);
        if (ret) {
                ath10k_warn(ar, "failed to set tx power for station ret: %d\n",
                            ret);
@@ -6549,8 +6636,12 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
 
                spin_unlock_bh(&ar->data_lock);
 
-               if (!sta->tdls)
+               if (!sta->tdls) {
+                       ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
+                       ath10k_mac_dec_num_stations(arvif, sta);
+                       kfree(arsta->tx_stats);
                        goto exit;
+               }
 
                ret = ath10k_wmi_update_fw_tdls_state(ar, arvif->vdev_id,
                                                      WMI_TDLS_ENABLE_ACTIVE);
@@ -7419,7 +7510,7 @@ static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar,
        err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
                                        WMI_PEER_PARAM_FIXED_RATE, rate);
        if (err)
-               ath10k_warn(ar, "failed to eanble STA %pM peer fixed rate: %d\n",
+               ath10k_warn(ar, "failed to enable STA %pM peer fixed rate: %d\n",
                            sta->addr, err);
 
        return true;
index 1fe8494..98d83a2 100644 (file)
@@ -72,6 +72,7 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
                                            u8 tid);
 int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
 void ath10k_mac_wait_tx_complete(struct ath10k *ar);
+int ath10k_mac_rfkill_enable_radio(struct ath10k *ar, bool enable);
 
 static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
                                      struct sk_buff *skb)
index a0b4d26..bb44f5a 100644 (file)
@@ -2567,35 +2567,31 @@ static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
 
        ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
 
-       val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_RESET_CONTROL_ADDRESS);
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-                          val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
+       val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
+       ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
+                              val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
 }
 
 static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
 {
        u32 val;
 
-       val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_RESET_CONTROL_ADDRESS);
+       val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
 
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-                          val | SOC_RESET_CONTROL_CE_RST_MASK);
+       ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
+                              val | SOC_RESET_CONTROL_CE_RST_MASK);
        msleep(10);
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
-                          val & ~SOC_RESET_CONTROL_CE_RST_MASK);
+       ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
+                              val & ~SOC_RESET_CONTROL_CE_RST_MASK);
 }
 
 static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
 {
        u32 val;
 
-       val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
-                               SOC_LF_TIMER_CONTROL0_ADDRESS);
-       ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
-                          SOC_LF_TIMER_CONTROL0_ADDRESS,
-                          val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
+       val = ath10k_pci_soc_read32(ar, SOC_LF_TIMER_CONTROL0_ADDRESS);
+       ath10k_pci_soc_write32(ar, SOC_LF_TIMER_CONTROL0_ADDRESS,
+                              val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
 }
 
 static int ath10k_pci_warm_reset(struct ath10k *ar)
@@ -3490,7 +3486,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        struct ath10k_pci *ar_pci;
        enum ath10k_hw_rev hw_rev;
        struct ath10k_bus_params bus_params = {};
-       bool pci_ps;
+       bool pci_ps, is_qca988x = false;
        int (*pci_soft_reset)(struct ath10k *ar);
        int (*pci_hard_reset)(struct ath10k *ar);
        u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
@@ -3500,6 +3496,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
        case QCA988X_2_0_DEVICE_ID:
                hw_rev = ATH10K_HW_QCA988X;
                pci_ps = false;
+               is_qca988x = true;
                pci_soft_reset = ath10k_pci_warm_reset;
                pci_hard_reset = ath10k_pci_qca988x_chip_reset;
                targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
@@ -3619,25 +3616,34 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
                goto err_deinit_irq;
        }
 
+       bus_params.dev_type = ATH10K_DEV_TYPE_LL;
+       bus_params.link_can_suspend = true;
+       /* Read CHIP_ID before reset to catch QCA9880-AR1A v1 devices that
+        * fall off the bus during chip_reset. These chips have the same pci
+        * device id as the QCA9880 BR4A or 2R4E. So that's why the check.
+        */
+       if (is_qca988x) {
+               bus_params.chip_id =
+                       ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
+               if (bus_params.chip_id != 0xffffffff) {
+                       if (!ath10k_pci_chip_is_supported(pdev->device,
+                                                         bus_params.chip_id))
+                               goto err_unsupported;
+               }
+       }
+
        ret = ath10k_pci_chip_reset(ar);
        if (ret) {
                ath10k_err(ar, "failed to reset chip: %d\n", ret);
                goto err_free_irq;
        }
 
-       bus_params.dev_type = ATH10K_DEV_TYPE_LL;
-       bus_params.link_can_suspend = true;
        bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS);
-       if (bus_params.chip_id == 0xffffffff) {
-               ath10k_err(ar, "failed to get chip id\n");
-               goto err_free_irq;
-       }
+       if (bus_params.chip_id == 0xffffffff)
+               goto err_unsupported;
 
-       if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) {
-               ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
-                          pdev->device, bus_params.chip_id);
+       if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id))
                goto err_free_irq;
-       }
 
        ret = ath10k_core_register(ar, &bus_params);
        if (ret) {
@@ -3647,6 +3653,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
 
        return 0;
 
+err_unsupported:
+       ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
+                  pdev->device, bus_params.chip_id);
+
 err_free_irq:
        ath10k_pci_free_irq(ar);
        ath10k_pci_rx_retry_sync(ar);
index 3b63b62..637f83e 100644 (file)
@@ -111,6 +111,7 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
        struct wlfw_msa_info_resp_msg_v01 resp = {};
        struct wlfw_msa_info_req_msg_v01 req = {};
        struct ath10k *ar = qmi->ar;
+       phys_addr_t max_mapped_addr;
        struct qmi_txn txn;
        int ret;
        int i;
@@ -150,8 +151,20 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
                goto out;
        }
 
+       max_mapped_addr = qmi->msa_pa + qmi->msa_mem_size;
        qmi->nr_mem_region = resp.mem_region_info_len;
        for (i = 0; i < resp.mem_region_info_len; i++) {
+               if (resp.mem_region_info[i].size > qmi->msa_mem_size ||
+                   resp.mem_region_info[i].region_addr > max_mapped_addr ||
+                   resp.mem_region_info[i].region_addr < qmi->msa_pa ||
+                   resp.mem_region_info[i].size +
+                   resp.mem_region_info[i].region_addr > max_mapped_addr) {
+                       ath10k_err(ar, "received out of range memory region address 0x%llx with size 0x%x, aborting\n",
+                                  resp.mem_region_info[i].region_addr,
+                                  resp.mem_region_info[i].size);
+                       ret = -EINVAL;
+                       goto fail_unwind;
+               }
                qmi->mem_region[i].addr = resp.mem_region_info[i].region_addr;
                qmi->mem_region[i].size = resp.mem_region_info[i].size;
                qmi->mem_region[i].secure = resp.mem_region_info[i].secure_flag;
@@ -165,6 +178,8 @@ static int ath10k_qmi_msa_mem_info_send_sync_msg(struct ath10k_qmi *qmi)
        ath10k_dbg(ar, ATH10K_DBG_QMI, "qmi msa mem info request completed\n");
        return 0;
 
+fail_unwind:
+       memset(&qmi->mem_region[0], 0, sizeof(qmi->mem_region[0]) * i);
 out:
        return ret;
 }
@@ -291,10 +306,16 @@ static int ath10k_qmi_send_cal_report_req(struct ath10k_qmi *qmi)
        struct wlfw_cal_report_resp_msg_v01 resp = {};
        struct wlfw_cal_report_req_msg_v01 req = {};
        struct ath10k *ar = qmi->ar;
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
        struct qmi_txn txn;
        int i, j = 0;
        int ret;
 
+       if (ar_snoc->xo_cal_supported) {
+               req.xo_cal_data_valid = 1;
+               req.xo_cal_data = ar_snoc->xo_cal_data;
+       }
+
        ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_cal_report_resp_msg_v01_ei,
                           &resp);
        if (ret < 0)
@@ -581,22 +602,29 @@ static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
 {
        struct wlfw_host_cap_resp_msg_v01 resp = {};
        struct wlfw_host_cap_req_msg_v01 req = {};
+       struct qmi_elem_info *req_ei;
        struct ath10k *ar = qmi->ar;
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
        struct qmi_txn txn;
        int ret;
 
        req.daemon_support_valid = 1;
        req.daemon_support = 0;
 
-       ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
-                          wlfw_host_cap_resp_msg_v01_ei, &resp);
+       ret = qmi_txn_init(&qmi->qmi_hdl, &txn, wlfw_host_cap_resp_msg_v01_ei,
+                          &resp);
        if (ret < 0)
                goto out;
 
+       if (test_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags))
+               req_ei = wlfw_host_cap_8bit_req_msg_v01_ei;
+       else
+               req_ei = wlfw_host_cap_req_msg_v01_ei;
+
        ret = qmi_send_request(&qmi->qmi_hdl, NULL, &txn,
                               QMI_WLFW_HOST_CAP_REQ_V01,
                               WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN,
-                              wlfw_host_cap_req_msg_v01_ei, &req);
+                              req_ei, &req);
        if (ret < 0) {
                qmi_txn_cancel(&txn);
                ath10k_err(ar, "failed to send host capability request: %d\n", ret);
@@ -643,7 +671,7 @@ int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
                               wlfw_ini_req_msg_v01_ei, &req);
        if (ret < 0) {
                qmi_txn_cancel(&txn);
-               ath10k_err(ar, "fail to send fw log reqest: %d\n", ret);
+               ath10k_err(ar, "failed to send fw log request: %d\n", ret);
                goto out;
        }
 
@@ -652,7 +680,7 @@ int ath10k_qmi_set_fw_log_mode(struct ath10k *ar, u8 fw_log_mode)
                goto out;
 
        if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
-               ath10k_err(ar, "fw log request rejectedr: %d\n",
+               ath10k_err(ar, "fw log request rejected: %d\n",
                           resp.resp.error);
                ret = -EINVAL;
                goto out;
@@ -671,6 +699,7 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
        struct wlfw_ind_register_resp_msg_v01 resp = {};
        struct wlfw_ind_register_req_msg_v01 req = {};
        struct ath10k *ar = qmi->ar;
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
        struct qmi_txn txn;
        int ret;
 
@@ -681,6 +710,11 @@ ath10k_qmi_ind_register_send_sync_msg(struct ath10k_qmi *qmi)
        req.msa_ready_enable_valid = 1;
        req.msa_ready_enable = 1;
 
+       if (ar_snoc->xo_cal_supported) {
+               req.xo_cal_enable_valid = 1;
+               req.xo_cal_enable = 1;
+       }
+
        ret = qmi_txn_init(&qmi->qmi_hdl, &txn,
                           wlfw_ind_register_resp_msg_v01_ei, &resp);
        if (ret < 0)
@@ -795,9 +829,13 @@ ath10k_qmi_driver_event_post(struct ath10k_qmi *qmi,
 static void ath10k_qmi_event_server_exit(struct ath10k_qmi *qmi)
 {
        struct ath10k *ar = qmi->ar;
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
 
        ath10k_qmi_remove_msa_permission(qmi);
        ath10k_core_free_board_files(ar);
+       if (!test_bit(ATH10K_SNOC_FLAG_UNREGISTERING, &ar_snoc->flags))
+               ath10k_snoc_fw_crashed_dump(ar);
+
        ath10k_snoc_fw_indication(ar, ATH10K_QMI_EVENT_FW_DOWN_IND);
        ath10k_dbg(ar, ATH10K_DBG_QMI, "wifi fw qmi service disconnected\n");
 }
index 1fe05c6..86fcf4e 100644 (file)
@@ -1988,6 +1988,28 @@ struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[] = {
        {}
 };
 
+struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[] = {
+       {
+               .data_type      = QMI_OPT_FLAG,
+               .elem_len       = 1,
+               .elem_size      = sizeof(u8),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x10,
+               .offset         = offsetof(struct wlfw_host_cap_req_msg_v01,
+                                          daemon_support_valid),
+       },
+       {
+               .data_type      = QMI_UNSIGNED_1_BYTE,
+               .elem_len       = 1,
+               .elem_size      = sizeof(u8),
+               .array_type     = NO_ARRAY,
+               .tlv_type       = 0x10,
+               .offset         = offsetof(struct wlfw_host_cap_req_msg_v01,
+                                          daemon_support),
+       },
+       {}
+};
+
 struct qmi_elem_info wlfw_host_cap_resp_msg_v01_ei[] = {
        {
                .data_type      = QMI_STRUCT,
index bca1186..4d107e1 100644 (file)
@@ -575,6 +575,7 @@ struct wlfw_host_cap_req_msg_v01 {
 
 #define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 189
 extern struct qmi_elem_info wlfw_host_cap_req_msg_v01_ei[];
+extern struct qmi_elem_info wlfw_host_cap_8bit_req_msg_v01_ei[];
 
 struct wlfw_host_cap_resp_msg_v01 {
        struct qmi_response_type_v01 resp;
index 9870d2d..120200a 100644 (file)
@@ -2086,9 +2086,6 @@ static int ath10k_sdio_probe(struct sdio_func *func,
                goto err_free_wq;
        }
 
-       /* TODO: remove this once SDIO support is fully implemented */
-       ath10k_warn(ar, "WARNING: ath10k SDIO support is work-in-progress, problems may arise!\n");
-
        return 0;
 
 err_free_wq:
index b491361..cd22c86 100644 (file)
@@ -9,9 +9,11 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/property.h>
 #include <linux/regulator/consumer.h>
 
 #include "ce.h"
+#include "coredump.h"
 #include "debug.h"
 #include "hif.h"
 #include "htc.h"
@@ -36,15 +38,15 @@ static char *const ce_name[] = {
        "WLAN_CE_11",
 };
 
-static struct ath10k_vreg_info vreg_cfg[] = {
-       {NULL, "vdd-0.8-cx-mx", 800000, 850000, 0, 0, false},
-       {NULL, "vdd-1.8-xo", 1800000, 1850000, 0, 0, false},
-       {NULL, "vdd-1.3-rfa", 1300000, 1350000, 0, 0, false},
-       {NULL, "vdd-3.3-ch0", 3300000, 3350000, 0, 0, false},
+static const char * const ath10k_regulators[] = {
+       "vdd-0.8-cx-mx",
+       "vdd-1.8-xo",
+       "vdd-1.3-rfa",
+       "vdd-3.3-ch0",
 };
 
-static struct ath10k_clk_info clk_cfg[] = {
-       {NULL, "cxo_ref_clk_pin", 0, false},
+static const char * const ath10k_clocks[] = {
+       "cxo_ref_clk_pin",
 };
 
 static void ath10k_snoc_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
@@ -976,8 +978,7 @@ static int ath10k_snoc_wlan_enable(struct ath10k *ar,
                                  sizeof(struct ath10k_svc_pipe_cfg);
        cfg.ce_svc_cfg = (struct ath10k_svc_pipe_cfg *)
                &target_service_to_ce_map_wlan;
-       cfg.num_shadow_reg_cfg = sizeof(target_shadow_reg_cfg_map) /
-                                       sizeof(struct ath10k_shadow_reg_cfg);
+       cfg.num_shadow_reg_cfg = ARRAY_SIZE(target_shadow_reg_cfg_map);
        cfg.shadow_reg_cfg = (struct ath10k_shadow_reg_cfg *)
                &target_shadow_reg_cfg_map;
 
@@ -1257,10 +1258,29 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
                ar_snoc->ce_irqs[i].irq_line = res->start;
        }
 
+       ret = device_property_read_u32(&pdev->dev, "qcom,xo-cal-data",
+                                      &ar_snoc->xo_cal_data);
+       ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc xo-cal-data return %d\n", ret);
+       if (ret == 0) {
+               ar_snoc->xo_cal_supported = true;
+               ath10k_dbg(ar, ATH10K_DBG_SNOC, "xo cal data %x\n",
+                          ar_snoc->xo_cal_data);
+       }
+       ret = 0;
+
 out:
        return ret;
 }
 
+static void ath10k_snoc_quirks_init(struct ath10k *ar)
+{
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
+       struct device *dev = &ar_snoc->dev->dev;
+
+       if (of_property_read_bool(dev->of_node, "qcom,snoc-host-cap-8bit-quirk"))
+               set_bit(ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK, &ar_snoc->flags);
+}
+
 int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type)
 {
        struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
@@ -1337,296 +1357,102 @@ static void ath10k_snoc_release_resource(struct ath10k *ar)
                ath10k_ce_free_pipe(ar, i);
 }
 
-static int ath10k_get_vreg_info(struct ath10k *ar, struct device *dev,
-                               struct ath10k_vreg_info *vreg_info)
-{
-       struct regulator *reg;
-       int ret = 0;
-
-       reg = devm_regulator_get_optional(dev, vreg_info->name);
-
-       if (IS_ERR(reg)) {
-               ret = PTR_ERR(reg);
-
-               if (ret  == -EPROBE_DEFER) {
-                       ath10k_err(ar, "EPROBE_DEFER for regulator: %s\n",
-                                  vreg_info->name);
-                       return ret;
-               }
-               if (vreg_info->required) {
-                       ath10k_err(ar, "Regulator %s doesn't exist: %d\n",
-                                  vreg_info->name, ret);
-                       return ret;
-               }
-               ath10k_dbg(ar, ATH10K_DBG_SNOC,
-                          "Optional regulator %s doesn't exist: %d\n",
-                          vreg_info->name, ret);
-               goto done;
-       }
-
-       vreg_info->reg = reg;
-
-done:
-       ath10k_dbg(ar, ATH10K_DBG_SNOC,
-                  "snog vreg %s min_v %u max_v %u load_ua %u settle_delay %lu\n",
-                  vreg_info->name, vreg_info->min_v, vreg_info->max_v,
-                  vreg_info->load_ua, vreg_info->settle_delay);
-
-       return 0;
-}
-
-static int ath10k_get_clk_info(struct ath10k *ar, struct device *dev,
-                              struct ath10k_clk_info *clk_info)
-{
-       struct clk *handle;
-       int ret = 0;
-
-       handle = devm_clk_get(dev, clk_info->name);
-       if (IS_ERR(handle)) {
-               ret = PTR_ERR(handle);
-               if (clk_info->required) {
-                       ath10k_err(ar, "snoc clock %s isn't available: %d\n",
-                                  clk_info->name, ret);
-                       return ret;
-               }
-               ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc ignoring clock %s: %d\n",
-                          clk_info->name,
-                          ret);
-               return 0;
-       }
-
-       ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s freq %u\n",
-                  clk_info->name, clk_info->freq);
-
-       clk_info->handle = handle;
-
-       return ret;
-}
-
-static int __ath10k_snoc_vreg_on(struct ath10k *ar,
-                                struct ath10k_vreg_info *vreg_info)
-{
-       int ret;
-
-       ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being enabled\n",
-                  vreg_info->name);
-
-       ret = regulator_set_voltage(vreg_info->reg, vreg_info->min_v,
-                                   vreg_info->max_v);
-       if (ret) {
-               ath10k_err(ar,
-                          "failed to set regulator %s voltage-min: %d voltage-max: %d\n",
-                          vreg_info->name, vreg_info->min_v, vreg_info->max_v);
-               return ret;
-       }
-
-       if (vreg_info->load_ua) {
-               ret = regulator_set_load(vreg_info->reg, vreg_info->load_ua);
-               if (ret < 0) {
-                       ath10k_err(ar, "failed to set regulator %s load: %d\n",
-                                  vreg_info->name, vreg_info->load_ua);
-                       goto err_set_load;
-               }
-       }
-
-       ret = regulator_enable(vreg_info->reg);
-       if (ret) {
-               ath10k_err(ar, "failed to enable regulator %s\n",
-                          vreg_info->name);
-               goto err_enable;
-       }
-
-       if (vreg_info->settle_delay)
-               udelay(vreg_info->settle_delay);
-
-       return 0;
-
-err_enable:
-       regulator_set_load(vreg_info->reg, 0);
-err_set_load:
-       regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
-
-       return ret;
-}
-
-static int __ath10k_snoc_vreg_off(struct ath10k *ar,
-                                 struct ath10k_vreg_info *vreg_info)
+static int ath10k_hw_power_on(struct ath10k *ar)
 {
+       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
        int ret;
 
-       ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc regulator %s being disabled\n",
-                  vreg_info->name);
+       ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
 
-       ret = regulator_disable(vreg_info->reg);
+       ret = regulator_bulk_enable(ar_snoc->num_vregs, ar_snoc->vregs);
        if (ret)
-               ath10k_err(ar, "failed to disable regulator %s\n",
-                          vreg_info->name);
-
-       ret = regulator_set_load(vreg_info->reg, 0);
-       if (ret < 0)
-               ath10k_err(ar, "failed to set load %s\n", vreg_info->name);
+               return ret;
 
-       ret = regulator_set_voltage(vreg_info->reg, 0, vreg_info->max_v);
+       ret = clk_bulk_prepare_enable(ar_snoc->num_clks, ar_snoc->clks);
        if (ret)
-               ath10k_err(ar, "failed to set voltage %s\n", vreg_info->name);
+               goto vreg_off;
 
        return ret;
-}
-
-static int ath10k_snoc_vreg_on(struct ath10k *ar)
-{
-       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
-       struct ath10k_vreg_info *vreg_info;
-       int ret = 0;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
-               vreg_info = &ar_snoc->vreg[i];
-
-               if (!vreg_info->reg)
-                       continue;
-
-               ret = __ath10k_snoc_vreg_on(ar, vreg_info);
-               if (ret)
-                       goto err_reg_config;
-       }
-
-       return 0;
-
-err_reg_config:
-       for (i = i - 1; i >= 0; i--) {
-               vreg_info = &ar_snoc->vreg[i];
-
-               if (!vreg_info->reg)
-                       continue;
-
-               __ath10k_snoc_vreg_off(ar, vreg_info);
-       }
 
+vreg_off:
+       regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
        return ret;
 }
 
-static int ath10k_snoc_vreg_off(struct ath10k *ar)
+static int ath10k_hw_power_off(struct ath10k *ar)
 {
        struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
-       struct ath10k_vreg_info *vreg_info;
-       int ret = 0;
-       int i;
-
-       for (i = ARRAY_SIZE(vreg_cfg) - 1; i >= 0; i--) {
-               vreg_info = &ar_snoc->vreg[i];
 
-               if (!vreg_info->reg)
-                       continue;
+       ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
 
-               ret = __ath10k_snoc_vreg_off(ar, vreg_info);
-       }
+       clk_bulk_disable_unprepare(ar_snoc->num_clks, ar_snoc->clks);
 
-       return ret;
+       return regulator_bulk_disable(ar_snoc->num_vregs, ar_snoc->vregs);
 }
 
-static int ath10k_snoc_clk_init(struct ath10k *ar)
+static void ath10k_msa_dump_memory(struct ath10k *ar,
+                                  struct ath10k_fw_crash_data *crash_data)
 {
        struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
-       struct ath10k_clk_info *clk_info;
-       int ret = 0;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
-               clk_info = &ar_snoc->clk[i];
-
-               if (!clk_info->handle)
-                       continue;
-
-               ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being enabled\n",
-                          clk_info->name);
+       const struct ath10k_hw_mem_layout *mem_layout;
+       const struct ath10k_mem_region *current_region;
+       struct ath10k_dump_ram_data_hdr *hdr;
+       size_t buf_len;
+       u8 *buf;
 
-               if (clk_info->freq) {
-                       ret = clk_set_rate(clk_info->handle, clk_info->freq);
-
-                       if (ret) {
-                               ath10k_err(ar, "failed to set clock %s freq %u\n",
-                                          clk_info->name, clk_info->freq);
-                               goto err_clock_config;
-                       }
-               }
-
-               ret = clk_prepare_enable(clk_info->handle);
-               if (ret) {
-                       ath10k_err(ar, "failed to enable clock %s\n",
-                                  clk_info->name);
-                       goto err_clock_config;
-               }
-       }
-
-       return 0;
-
-err_clock_config:
-       for (i = i - 1; i >= 0; i--) {
-               clk_info = &ar_snoc->clk[i];
-
-               if (!clk_info->handle)
-                       continue;
-
-               clk_disable_unprepare(clk_info->handle);
-       }
+       if (!crash_data && !crash_data->ramdump_buf)
+               return;
 
-       return ret;
-}
+       mem_layout = ath10k_coredump_get_mem_layout(ar);
+       if (!mem_layout)
+               return;
 
-static int ath10k_snoc_clk_deinit(struct ath10k *ar)
-{
-       struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
-       struct ath10k_clk_info *clk_info;
-       int i;
+       current_region = &mem_layout->region_table.regions[0];
 
-       for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
-               clk_info = &ar_snoc->clk[i];
+       buf = crash_data->ramdump_buf;
+       buf_len = crash_data->ramdump_buf_len;
+       memset(buf, 0, buf_len);
 
-               if (!clk_info->handle)
-                       continue;
+       /* Reserve space for the header. */
+       hdr = (void *)buf;
+       buf += sizeof(*hdr);
+       buf_len -= sizeof(*hdr);
 
-               ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc clock %s being disabled\n",
-                          clk_info->name);
+       hdr->region_type = cpu_to_le32(current_region->type);
+       hdr->start = cpu_to_le32((unsigned long)ar_snoc->qmi->msa_va);
+       hdr->length = cpu_to_le32(ar_snoc->qmi->msa_mem_size);
 
-               clk_disable_unprepare(clk_info->handle);
+       if (current_region->len < ar_snoc->qmi->msa_mem_size) {
+               memcpy(buf, ar_snoc->qmi->msa_va, current_region->len);
+               ath10k_warn(ar, "msa dump length is less than msa size %x, %x\n",
+                           current_region->len, ar_snoc->qmi->msa_mem_size);
+       } else {
+               memcpy(buf, ar_snoc->qmi->msa_va, ar_snoc->qmi->msa_mem_size);
        }
-
-       return 0;
 }
 
-static int ath10k_hw_power_on(struct ath10k *ar)
+void ath10k_snoc_fw_crashed_dump(struct ath10k *ar)
 {
-       int ret;
+       struct ath10k_fw_crash_data *crash_data;
+       char guid[UUID_STRING_LEN + 1];
 
-       ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power on\n");
+       mutex_lock(&ar->dump_mutex);
 
-       ret = ath10k_snoc_vreg_on(ar);
-       if (ret)
-               return ret;
+       spin_lock_bh(&ar->data_lock);
+       ar->stats.fw_crash_counter++;
+       spin_unlock_bh(&ar->data_lock);
 
-       ret = ath10k_snoc_clk_init(ar);
-       if (ret)
-               goto vreg_off;
+       crash_data = ath10k_coredump_new(ar);
 
-       return ret;
-
-vreg_off:
-       ath10k_snoc_vreg_off(ar);
-       return ret;
-}
-
-static int ath10k_hw_power_off(struct ath10k *ar)
-{
-       int ret;
-
-       ath10k_dbg(ar, ATH10K_DBG_SNOC, "soc power off\n");
-
-       ath10k_snoc_clk_deinit(ar);
-
-       ret = ath10k_snoc_vreg_off(ar);
+       if (crash_data)
+               scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
+       else
+               scnprintf(guid, sizeof(guid), "n/a");
 
-       return ret;
+       ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
+       ath10k_print_driver_info(ar);
+       ath10k_msa_dump_memory(ar, crash_data);
+       mutex_unlock(&ar->dump_mutex);
 }
 
 static const struct of_device_id ath10k_snoc_dt_match[] = {
@@ -1678,6 +1504,8 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
        ar->ce_priv = &ar_snoc->ce;
        msa_size = drv_data->msa_size;
 
+       ath10k_snoc_quirks_init(ar);
+
        ret = ath10k_snoc_resource_init(ar);
        if (ret) {
                ath10k_warn(ar, "failed to initialize resource: %d\n", ret);
@@ -1695,20 +1523,37 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
                goto err_release_resource;
        }
 
-       ar_snoc->vreg = vreg_cfg;
-       for (i = 0; i < ARRAY_SIZE(vreg_cfg); i++) {
-               ret = ath10k_get_vreg_info(ar, dev, &ar_snoc->vreg[i]);
-               if (ret)
-                       goto err_free_irq;
+       ar_snoc->num_vregs = ARRAY_SIZE(ath10k_regulators);
+       ar_snoc->vregs = devm_kcalloc(&pdev->dev, ar_snoc->num_vregs,
+                                     sizeof(*ar_snoc->vregs), GFP_KERNEL);
+       if (!ar_snoc->vregs) {
+               ret = -ENOMEM;
+               goto err_free_irq;
        }
+       for (i = 0; i < ar_snoc->num_vregs; i++)
+               ar_snoc->vregs[i].supply = ath10k_regulators[i];
 
-       ar_snoc->clk = clk_cfg;
-       for (i = 0; i < ARRAY_SIZE(clk_cfg); i++) {
-               ret = ath10k_get_clk_info(ar, dev, &ar_snoc->clk[i]);
-               if (ret)
-                       goto err_free_irq;
+       ret = devm_regulator_bulk_get(&pdev->dev, ar_snoc->num_vregs,
+                                     ar_snoc->vregs);
+       if (ret < 0)
+               goto err_free_irq;
+
+       ar_snoc->num_clks = ARRAY_SIZE(ath10k_clocks);
+       ar_snoc->clks = devm_kcalloc(&pdev->dev, ar_snoc->num_clks,
+                                    sizeof(*ar_snoc->clks), GFP_KERNEL);
+       if (!ar_snoc->clks) {
+               ret = -ENOMEM;
+               goto err_free_irq;
        }
 
+       for (i = 0; i < ar_snoc->num_clks; i++)
+               ar_snoc->clks[i].id = ath10k_clocks[i];
+
+       ret = devm_clk_bulk_get_optional(&pdev->dev, ar_snoc->num_clks,
+                                        ar_snoc->clks);
+       if (ret)
+               goto err_free_irq;
+
        ret = ath10k_hw_power_on(ar);
        if (ret) {
                ath10k_err(ar, "failed to power on device: %d\n", ret);
index d62f535..c05df45 100644 (file)
@@ -42,29 +42,16 @@ struct ath10k_snoc_ce_irq {
        u32 irq_line;
 };
 
-struct ath10k_vreg_info {
-       struct regulator *reg;
-       const char *name;
-       u32 min_v;
-       u32 max_v;
-       u32 load_ua;
-       unsigned long settle_delay;
-       bool required;
-};
-
-struct ath10k_clk_info {
-       struct clk *handle;
-       const char *name;
-       u32 freq;
-       bool required;
-};
-
 enum ath10k_snoc_flags {
        ATH10K_SNOC_FLAG_REGISTERED,
        ATH10K_SNOC_FLAG_UNREGISTERING,
        ATH10K_SNOC_FLAG_RECOVERY,
+       ATH10K_SNOC_FLAG_8BIT_HOST_CAP_QUIRK,
 };
 
+struct clk_bulk_data;
+struct regulator_bulk_data;
+
 struct ath10k_snoc {
        struct platform_device *dev;
        struct ath10k *ar;
@@ -76,10 +63,14 @@ struct ath10k_snoc {
        struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
        struct ath10k_ce ce;
        struct timer_list rx_post_retry;
-       struct ath10k_vreg_info *vreg;
-       struct ath10k_clk_info *clk;
+       struct regulator_bulk_data *vregs;
+       size_t num_vregs;
+       struct clk_bulk_data *clks;
+       size_t num_clks;
        struct ath10k_qmi *qmi;
        unsigned long flags;
+       bool xo_cal_supported;
+       u32 xo_cal_data;
 };
 
 static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
@@ -88,5 +79,6 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
 }
 
 int ath10k_snoc_fw_indication(struct ath10k *ar, u64 type);
+void ath10k_snoc_fw_crashed_dump(struct ath10k *ar);
 
 #endif /* _SNOC_H_ */
index e1420f6..730ed22 100644 (file)
@@ -435,6 +435,7 @@ static int ath10k_usb_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
                        ath10k_dbg(ar, ATH10K_DBG_USB_BULK,
                                   "usb bulk transmit failed: %d\n", ret);
                        usb_unanchor_urb(urb);
+                       usb_free_urb(urb);
                        ret = -EINVAL;
                        goto err_free_urb_to_pipe;
                }
index 4d5d10c..69a1ec5 100644 (file)
@@ -409,6 +409,49 @@ static int ath10k_wmi_tlv_event_tx_pause(struct ath10k *ar,
        return 0;
 }
 
+static void ath10k_wmi_tlv_event_rfkill_state_change(struct ath10k *ar,
+                                                    struct sk_buff *skb)
+{
+       const struct wmi_tlv_rfkill_state_change_ev *ev;
+       const void **tb;
+       bool radio;
+       int ret;
+
+       tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
+       if (IS_ERR(tb)) {
+               ret = PTR_ERR(tb);
+               ath10k_warn(ar,
+                           "failed to parse rfkill state change event: %d\n",
+                           ret);
+               return;
+       }
+
+       ev = tb[WMI_TLV_TAG_STRUCT_RFKILL_EVENT];
+       if (!ev) {
+               kfree(tb);
+               return;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_MAC,
+                  "wmi tlv rfkill state change gpio %d type %d radio_state %d\n",
+                  __le32_to_cpu(ev->gpio_pin_num),
+                  __le32_to_cpu(ev->int_type),
+                  __le32_to_cpu(ev->radio_state));
+
+       radio = (__le32_to_cpu(ev->radio_state) == WMI_TLV_RFKILL_RADIO_STATE_ON);
+
+       spin_lock_bh(&ar->data_lock);
+
+       if (!radio)
+               ar->hw_rfkill_on = true;
+
+       spin_unlock_bh(&ar->data_lock);
+
+       /* notify cfg80211 radio state change */
+       ath10k_mac_rfkill_enable_radio(ar, radio);
+       wiphy_rfkill_set_hw_state(ar->hw->wiphy, !radio);
+}
+
 static int ath10k_wmi_tlv_event_temperature(struct ath10k *ar,
                                            struct sk_buff *skb)
 {
@@ -629,6 +672,9 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
        case WMI_TLV_TX_PAUSE_EVENTID:
                ath10k_wmi_tlv_event_tx_pause(ar, skb);
                break;
+       case WMI_TLV_RFKILL_STATE_CHANGE_EVENTID:
+               ath10k_wmi_tlv_event_rfkill_state_change(ar, skb);
+               break;
        case WMI_TLV_PDEV_TEMPERATURE_EVENTID:
                ath10k_wmi_tlv_event_temperature(ar, skb);
                break;
@@ -1201,17 +1247,21 @@ static int ath10k_wmi_tlv_op_pull_svc_rdy_ev(struct ath10k *ar,
        arg->max_tx_power = ev->hw_max_tx_power;
        arg->ht_cap = ev->ht_cap_info;
        arg->vht_cap = ev->vht_cap_info;
+       arg->vht_supp_mcs = ev->vht_supp_mcs;
        arg->sw_ver0 = ev->abi.abi_ver0;
        arg->sw_ver1 = ev->abi.abi_ver1;
        arg->fw_build = ev->fw_build_vers;
        arg->phy_capab = ev->phy_capability;
        arg->num_rf_chains = ev->num_rf_chains;
        arg->eeprom_rd = reg->eeprom_rd;
+       arg->low_2ghz_chan = reg->low_2ghz_chan;
+       arg->high_2ghz_chan = reg->high_2ghz_chan;
        arg->low_5ghz_chan = reg->low_5ghz_chan;
        arg->high_5ghz_chan = reg->high_5ghz_chan;
        arg->num_mem_reqs = ev->num_mem_reqs;
        arg->service_map = svc_bmap;
        arg->service_map_len = ath10k_wmi_tlv_len(svc_bmap);
+       arg->sys_cap_info = ev->sys_cap_info;
 
        ret = ath10k_wmi_tlv_iter(ar, mem_reqs, ath10k_wmi_tlv_len(mem_reqs),
                                  ath10k_wmi_tlv_parse_mem_reqs, arg);
@@ -1649,8 +1699,9 @@ ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
 static void
 ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
 {
-       struct host_memory_chunk *chunk;
+       struct host_memory_chunk_tlv *chunk;
        struct wmi_tlv *tlv;
+       dma_addr_t paddr;
        int i;
        __le16 tlv_len, tlv_tag;
 
@@ -1666,6 +1717,12 @@ ath10k_wmi_tlv_put_host_mem_chunks(struct ath10k *ar, void *host_mem_chunks)
                chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
                chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
 
+               if (test_bit(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
+                            ar->wmi.svc_map)) {
+                       paddr = ar->wmi.mem_chunks[i].paddr;
+                       chunk->ptr_high = __cpu_to_le32(upper_32_bits(paddr));
+               }
+
                ath10k_dbg(ar, ATH10K_DBG_WMI,
                           "wmi-tlv chunk %d len %d, addr 0x%llx, id 0x%x\n",
                           i,
@@ -1689,7 +1746,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
        void *ptr;
 
        chunks_len = ar->wmi.num_mem_chunks *
-                    (sizeof(struct host_memory_chunk) + sizeof(*tlv));
+                    (sizeof(struct host_memory_chunk_tlv) + sizeof(*tlv));
        len = (sizeof(*tlv) + sizeof(*cmd)) +
              (sizeof(*tlv) + sizeof(*cfg)) +
              (sizeof(*tlv) + chunks_len);
@@ -4204,6 +4261,26 @@ static struct wmi_pdev_param_map wmi_tlv_pdev_param_map = {
        .wapi_mbssid_offset = WMI_PDEV_PARAM_UNSUPPORTED,
        .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
        .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+       .rfkill_config = WMI_TLV_PDEV_PARAM_HW_RFKILL_CONFIG,
+       .rfkill_enable = WMI_TLV_PDEV_PARAM_RFKILL_ENABLE,
+};
+
+static struct wmi_peer_param_map wmi_tlv_peer_param_map = {
+       .smps_state = WMI_TLV_PEER_SMPS_STATE,
+       .ampdu = WMI_TLV_PEER_AMPDU,
+       .authorize = WMI_TLV_PEER_AUTHORIZE,
+       .chan_width = WMI_TLV_PEER_CHAN_WIDTH,
+       .nss = WMI_TLV_PEER_NSS,
+       .use_4addr = WMI_TLV_PEER_USE_4ADDR,
+       .membership = WMI_TLV_PEER_MEMBERSHIP,
+       .user_pos = WMI_TLV_PEER_USERPOS,
+       .crit_proto_hint_enabled = WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED,
+       .tx_fail_cnt_thr = WMI_TLV_PEER_TX_FAIL_CNT_THR,
+       .set_hw_retry_cts2s = WMI_TLV_PEER_SET_HW_RETRY_CTS2S,
+       .ibss_atim_win_len = WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH,
+       .phymode = WMI_TLV_PEER_PHYMODE,
+       .use_fixed_power = WMI_TLV_PEER_USE_FIXED_PWR,
+       .dummy_var = WMI_TLV_PEER_DUMMY_VAR,
 };
 
 static struct wmi_vdev_param_map wmi_tlv_vdev_param_map = {
@@ -4394,6 +4471,7 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
        ar->wmi.cmd = &wmi_tlv_cmd_map;
        ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
        ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
+       ar->wmi.peer_param = &wmi_tlv_peer_param_map;
        ar->wmi.ops = &wmi_tlv_ops;
        ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
 }
index 649b229..4972dc1 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef _WMI_TLV_H
 #define _WMI_TLV_H
 
+#include <linux/bitops.h>
+
 #define WMI_TLV_CMD(grp_id) (((grp_id) << 12) | 0x1)
 #define WMI_TLV_EV(grp_id) (((grp_id) << 12) | 0x1)
 #define WMI_TLV_CMD_UNSUPPORTED 0
@@ -528,6 +530,24 @@ enum wmi_tlv_vdev_param {
        WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
 };
 
+enum wmi_tlv_peer_param {
+       WMI_TLV_PEER_SMPS_STATE = 0x1, /* see %wmi_peer_smps_state */
+       WMI_TLV_PEER_AMPDU      = 0x2,
+       WMI_TLV_PEER_AUTHORIZE  = 0x3,
+       WMI_TLV_PEER_CHAN_WIDTH = 0x4,
+       WMI_TLV_PEER_NSS        = 0x5,
+       WMI_TLV_PEER_USE_4ADDR  = 0x6,
+       WMI_TLV_PEER_MEMBERSHIP = 0x7,
+       WMI_TLV_PEER_USERPOS = 0x8,
+       WMI_TLV_PEER_CRIT_PROTO_HINT_ENABLED = 0x9,
+       WMI_TLV_PEER_TX_FAIL_CNT_THR = 0xa,
+       WMI_TLV_PEER_SET_HW_RETRY_CTS2S = 0xb,
+       WMI_TLV_PEER_IBSS_ATIM_WINDOW_LENGTH = 0xc,
+       WMI_TLV_PEER_PHYMODE = 0xd,
+       WMI_TLV_PEER_USE_FIXED_PWR = 0xe,
+       WMI_TLV_PEER_DUMMY_VAR = 0xff,
+};
+
 enum wmi_tlv_peer_flags {
        WMI_TLV_PEER_AUTH = 0x00000001,
        WMI_TLV_PEER_QOS = 0x00000002,
@@ -1409,6 +1429,11 @@ enum wmi_tlv_service {
        WMI_TLV_SERVICE_WLAN_HPCS_PULSE = 172,
        WMI_TLV_SERVICE_PER_VDEV_CHAINMASK_CONFIG_SUPPORT = 173,
        WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI = 174,
+       WMI_TLV_SERVICE_NAN_DISABLE_SUPPORT = 175,
+       WMI_TLV_SERVICE_HTT_H2T_NO_HTC_HDR_LEN_IN_MSG_LEN = 176,
+       WMI_TLV_SERVICE_COEX_SUPPORT_UNEQUAL_ISOLATION = 177,
+       WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT = 178,
+       WMI_TLV_SERVICE_SUPPORT_EXTEND_ADDRESS = 179,
 
        WMI_TLV_MAX_EXT_SERVICE = 256,
 };
@@ -1588,6 +1613,9 @@ wmi_tlv_svc_map_ext(const __le32 *in, unsigned long *out, size_t len)
               WMI_TLV_MAX_SERVICE);
        SVCMAP(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,
               WMI_SERVICE_TX_DATA_ACK_RSSI, WMI_TLV_MAX_SERVICE);
+       SVCMAP(WMI_TLV_SERVICE_SUPPORT_EXTEND_ADDRESS,
+              WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
+              WMI_TLV_MAX_SERVICE);
 }
 
 #undef SVCMAP
@@ -1743,6 +1771,21 @@ struct wmi_tlv_resource_config {
        __le32 host_capab;
 } __packed;
 
+/* structure describing host memory chunk. */
+struct host_memory_chunk_tlv {
+       /* id of the request that is passed up in service ready */
+       __le32 req_id;
+
+       /* the physical address the memory chunk */
+       __le32 ptr;
+
+       /* size of the chunk */
+       __le32 size;
+
+       /* the upper 32 bit address valid only for more than 32 bit target */
+       __le32 ptr_high;
+} __packed;
+
 struct wmi_tlv_init_cmd {
        struct wmi_tlv_abi_version abi;
        __le32 num_host_mem_chunks;
@@ -2235,6 +2278,31 @@ struct wmi_tlv_tdls_peer_event {
        __le32 vdev_id;
 } __packed;
 
+enum wmi_tlv_sys_cap_info_flags {
+       WMI_TLV_SYS_CAP_INFO_RXTX_LED   = BIT(0),
+       WMI_TLV_SYS_CAP_INFO_RFKILL     = BIT(1),
+};
+
+#define WMI_TLV_RFKILL_CFG_GPIO_PIN_NUM                GENMASK(5, 0)
+#define WMI_TLV_RFKILL_CFG_RADIO_LEVEL         BIT(6)
+#define WMI_TLV_RFKILL_CFG_PIN_AS_GPIO         GENMASK(10, 7)
+
+enum wmi_tlv_rfkill_enable_radio {
+       WMI_TLV_RFKILL_ENABLE_RADIO_ON  = 0,
+       WMI_TLV_RFKILL_ENABLE_RADIO_OFF = 1,
+};
+
+enum wmi_tlv_rfkill_radio_state {
+       WMI_TLV_RFKILL_RADIO_STATE_OFF  = 1,
+       WMI_TLV_RFKILL_RADIO_STATE_ON   = 2,
+};
+
+struct wmi_tlv_rfkill_state_change_ev {
+       __le32 gpio_pin_num;
+       __le32 int_type;
+       __le32 radio_state;
+};
+
 void ath10k_wmi_tlv_attach(struct ath10k *ar);
 
 enum wmi_nlo_auth_algorithm {
index 4f707c6..f0ab115 100644 (file)
@@ -742,6 +742,19 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
        .radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
 };
 
+static struct wmi_peer_param_map wmi_peer_param_map = {
+       .smps_state = WMI_PEER_SMPS_STATE,
+       .ampdu = WMI_PEER_AMPDU,
+       .authorize = WMI_PEER_AUTHORIZE,
+       .chan_width = WMI_PEER_CHAN_WIDTH,
+       .nss = WMI_PEER_NSS,
+       .use_4addr = WMI_PEER_USE_4ADDR,
+       .use_fixed_power = WMI_PEER_USE_FIXED_PWR,
+       .debug = WMI_PEER_DEBUG,
+       .phymode = WMI_PEER_PHYMODE,
+       .dummy_var = WMI_PEER_DUMMY_VAR,
+};
+
 /* MAIN WMI VDEV param map */
 static struct wmi_vdev_param_map wmi_vdev_param_map = {
        .rts_threshold = WMI_VDEV_PARAM_RTS_THRESHOLD,
@@ -5344,11 +5357,14 @@ ath10k_wmi_main_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
        arg->max_tx_power = ev->hw_max_tx_power;
        arg->ht_cap = ev->ht_cap_info;
        arg->vht_cap = ev->vht_cap_info;
+       arg->vht_supp_mcs = ev->vht_supp_mcs;
        arg->sw_ver0 = ev->sw_version;
        arg->sw_ver1 = ev->sw_version_1;
        arg->phy_capab = ev->phy_capability;
        arg->num_rf_chains = ev->num_rf_chains;
        arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+       arg->low_2ghz_chan = ev->hal_reg_capabilities.low_2ghz_chan;
+       arg->high_2ghz_chan = ev->hal_reg_capabilities.high_2ghz_chan;
        arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
        arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
        arg->num_mem_reqs = ev->num_mem_reqs;
@@ -5383,16 +5399,25 @@ ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
        arg->max_tx_power = ev->hw_max_tx_power;
        arg->ht_cap = ev->ht_cap_info;
        arg->vht_cap = ev->vht_cap_info;
+       arg->vht_supp_mcs = ev->vht_supp_mcs;
        arg->sw_ver0 = ev->sw_version;
        arg->phy_capab = ev->phy_capability;
        arg->num_rf_chains = ev->num_rf_chains;
        arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
+       arg->low_2ghz_chan = ev->hal_reg_capabilities.low_2ghz_chan;
+       arg->high_2ghz_chan = ev->hal_reg_capabilities.high_2ghz_chan;
        arg->low_5ghz_chan = ev->hal_reg_capabilities.low_5ghz_chan;
        arg->high_5ghz_chan = ev->hal_reg_capabilities.high_5ghz_chan;
        arg->num_mem_reqs = ev->num_mem_reqs;
        arg->service_map = ev->wmi_service_bitmap;
        arg->service_map_len = sizeof(ev->wmi_service_bitmap);
 
+       /* Deliberately skipping ev->sys_cap_info as WMI and WMI-TLV have
+        * different values. We would need a translation to handle that,
+        * but as we don't currently need anything from sys_cap_info from
+        * WMI interface (only from WMI-TLV) safest it to skip it.
+        */
+
        n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
                  ARRAY_SIZE(arg->mem_reqs));
        for (i = 0; i < n; i++)
@@ -5432,6 +5457,7 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
        ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
        ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
        ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
+       ar->vht_supp_mcs = __le32_to_cpu(arg.vht_supp_mcs);
        ar->fw_version_major =
                (__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
        ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
@@ -5441,11 +5467,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
        ar->phy_capability = __le32_to_cpu(arg.phy_capab);
        ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
        ar->hw_eeprom_rd = __le32_to_cpu(arg.eeprom_rd);
+       ar->low_2ghz_chan = __le32_to_cpu(arg.low_2ghz_chan);
+       ar->high_2ghz_chan = __le32_to_cpu(arg.high_2ghz_chan);
        ar->low_5ghz_chan = __le32_to_cpu(arg.low_5ghz_chan);
        ar->high_5ghz_chan = __le32_to_cpu(arg.high_5ghz_chan);
+       ar->sys_cap_info = __le32_to_cpu(arg.sys_cap_info);
 
        ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
                        arg.service_map, arg.service_map_len);
+       ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sys_cap_info 0x%x\n",
+                  ar->sys_cap_info);
 
        if (ar->num_rf_chains > ar->max_spatial_stream) {
                ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
@@ -5544,17 +5575,22 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
 
 skip_mem_alloc:
        ath10k_dbg(ar, ATH10K_DBG_WMI,
-                  "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
+                  "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_mcs 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x fw_build 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x low_2ghz_chan %d high_2ghz_chan %d low_5ghz_chan %d high_5ghz_chan %d num_mem_reqs 0x%08x\n",
                   __le32_to_cpu(arg.min_tx_power),
                   __le32_to_cpu(arg.max_tx_power),
                   __le32_to_cpu(arg.ht_cap),
                   __le32_to_cpu(arg.vht_cap),
+                  __le32_to_cpu(arg.vht_supp_mcs),
                   __le32_to_cpu(arg.sw_ver0),
                   __le32_to_cpu(arg.sw_ver1),
                   __le32_to_cpu(arg.fw_build),
                   __le32_to_cpu(arg.phy_capab),
                   __le32_to_cpu(arg.num_rf_chains),
                   __le32_to_cpu(arg.eeprom_rd),
+                  __le32_to_cpu(arg.low_2ghz_chan),
+                  __le32_to_cpu(arg.high_2ghz_chan),
+                  __le32_to_cpu(arg.low_5ghz_chan),
+                  __le32_to_cpu(arg.high_5ghz_chan),
                   __le32_to_cpu(arg.num_mem_reqs));
 
        dev_kfree_skb(skb);
@@ -5623,7 +5659,7 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
        }
 
        ath10k_dbg(ar, ATH10K_DBG_WMI,
-                  "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d\n",
+                  "wmi event ready sw_version 0x%08x abi_version %u mac_addr %pM status %d\n",
                   __le32_to_cpu(arg.sw_version),
                   __le32_to_cpu(arg.abi_version),
                   arg.mac_addr,
@@ -9332,6 +9368,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
                ar->wmi.cmd = &wmi_10_4_cmd_map;
                ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
+               ar->wmi.peer_param = &wmi_peer_param_map;
                ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                ar->wmi_key_cipher = wmi_key_cipher_suites;
                break;
@@ -9340,6 +9377,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
                ar->wmi.ops = &wmi_10_2_4_ops;
                ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
+               ar->wmi.peer_param = &wmi_peer_param_map;
                ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                ar->wmi_key_cipher = wmi_key_cipher_suites;
                break;
@@ -9348,6 +9386,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
                ar->wmi.ops = &wmi_10_2_ops;
                ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+               ar->wmi.peer_param = &wmi_peer_param_map;
                ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
                ar->wmi_key_cipher = wmi_key_cipher_suites;
                break;
@@ -9356,6 +9395,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
                ar->wmi.ops = &wmi_10_1_ops;
                ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
                ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+               ar->wmi.peer_param = &wmi_peer_param_map;
                ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
                ar->wmi_key_cipher = wmi_key_cipher_suites;
                break;
@@ -9364,6 +9404,7 @@ int ath10k_wmi_attach(struct ath10k *ar)
                ar->wmi.ops = &wmi_ops;
                ar->wmi.vdev_param = &wmi_vdev_param_map;
                ar->wmi.pdev_param = &wmi_pdev_param_map;
+               ar->wmi.peer_param = &wmi_peer_param_map;
                ar->wmi.peer_flags = &wmi_peer_flags_map;
                ar->wmi_key_cipher = wmi_key_cipher_suites;
                break;
index e80dbe7..74adce1 100644 (file)
@@ -202,6 +202,7 @@ enum wmi_service {
        WMI_SERVICE_REPORT_AIRTIME,
        WMI_SERVICE_SYNC_DELETE_CMDS,
        WMI_SERVICE_TX_PWR_PER_PEER,
+       WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
 
        /* Remember to add the new value to wmi_service_name()! */
 
@@ -496,6 +497,7 @@ static inline char *wmi_service_name(enum wmi_service service_id)
        SVCSTR(WMI_SERVICE_REPORT_AIRTIME);
        SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
        SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
+       SVCSTR(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS);
 
        case WMI_SERVICE_MAX:
                return NULL;
@@ -3786,6 +3788,8 @@ struct wmi_pdev_param_map {
        u32 arp_srcaddr;
        u32 arp_dstaddr;
        u32 enable_btcoex;
+       u32 rfkill_config;
+       u32 rfkill_enable;
 };
 
 #define WMI_PDEV_PARAM_UNSUPPORTED 0
@@ -5071,6 +5075,25 @@ enum wmi_rate_preamble {
 /* Value to disable fixed rate setting */
 #define WMI_FIXED_RATE_NONE    (0xff)
 
+struct wmi_peer_param_map {
+       u32 smps_state;
+       u32 ampdu;
+       u32 authorize;
+       u32 chan_width;
+       u32 nss;
+       u32 use_4addr;
+       u32 membership;
+       u32 use_fixed_power;
+       u32 user_pos;
+       u32 crit_proto_hint_enabled;
+       u32 tx_fail_cnt_thr;
+       u32 set_hw_retry_cts2s;
+       u32 ibss_atim_win_len;
+       u32 debug;
+       u32 phymode;
+       u32 dummy_var;
+};
+
 struct wmi_vdev_param_map {
        u32 rts_threshold;
        u32 fragmentation_threshold;
@@ -6842,6 +6865,7 @@ struct wmi_svc_rdy_ev_arg {
        __le32 max_tx_power;
        __le32 ht_cap;
        __le32 vht_cap;
+       __le32 vht_supp_mcs;
        __le32 sw_ver0;
        __le32 sw_ver1;
        __le32 fw_build;
@@ -6849,8 +6873,11 @@ struct wmi_svc_rdy_ev_arg {
        __le32 num_rf_chains;
        __le32 eeprom_rd;
        __le32 num_mem_reqs;
+       __le32 low_2ghz_chan;
+       __le32 high_2ghz_chan;
        __le32 low_5ghz_chan;
        __le32 high_5ghz_chan;
+       __le32 sys_cap_info;
        const __le32 *service_map;
        size_t service_map_len;
        const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
index d5ee32c..43b4ae8 100644 (file)
@@ -300,8 +300,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
 #ifdef CONFIG_PM_SLEEP
 static int ath5k_pci_suspend(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct ath5k_hw *ah = hw->priv;
 
        ath5k_led_off(ah);
index 2b29bf4..b4885a7 100644 (file)
@@ -4183,7 +4183,7 @@ static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
 
 static void ar9003_hw_thermo_cal_apply(struct ath_hw *ah)
 {
-       u32 data, ko, kg;
+       u32 data = 0, ko, kg;
 
        if (!AR_SREV_9462_20_OR_LATER(ah))
                return;
index 159490f..956fa78 100644 (file)
@@ -12,7 +12,6 @@
  * initialize the chip when the user-space is ready to extract the init code.
  */
 #include <linux/module.h>
-#include <linux/version.h>
 #include <linux/completion.h>
 #include <linux/etherdevice.h>
 #include <linux/firmware.h>
index 4e8e80a..9cec5c2 100644 (file)
@@ -973,6 +973,8 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
        struct ath_htc_rx_status *rxstatus;
        struct ath_rx_status rx_stats;
        bool decrypt_error = false;
+       __be16 rs_datalen;
+       bool is_phyerr;
 
        if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
                ath_err(common, "Corrupted RX frame, dropping (len: %d)\n",
@@ -982,11 +984,24 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 
        rxstatus = (struct ath_htc_rx_status *)skb->data;
 
-       if (be16_to_cpu(rxstatus->rs_datalen) -
-           (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
+       rs_datalen = be16_to_cpu(rxstatus->rs_datalen);
+       if (unlikely(rs_datalen -
+           (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0)) {
                ath_err(common,
                        "Corrupted RX data len, dropping (dlen: %d, skblen: %d)\n",
-                       rxstatus->rs_datalen, skb->len);
+                       rs_datalen, skb->len);
+               goto rx_next;
+       }
+
+       is_phyerr = rxstatus->rs_status & ATH9K_RXERR_PHY;
+       /*
+        * Discard zero-length packets and packets smaller than an ACK
+        * which are not PHY_ERROR (short radar pulses have a length of 3)
+        */
+       if (unlikely(!rs_datalen || (rs_datalen < 10 && !is_phyerr))) {
+               ath_warn(common,
+                        "Short RX data len, dropping (dlen: %d)\n",
+                        rs_datalen);
                goto rx_next;
        }
 
@@ -1011,7 +1026,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
         * Process PHY errors and return so that the packet
         * can be dropped.
         */
-       if (rx_stats.rs_status & ATH9K_RXERR_PHY) {
+       if (unlikely(is_phyerr)) {
                /* TODO: Not using DFS processing now. */
                if (ath_cmn_process_fft(&priv->spec_priv, hdr,
                                    &rx_stats, rx_status->mactime)) {
index 92b2dd3..f3461b1 100644 (file)
@@ -1021,13 +1021,12 @@ static void ath_pci_remove(struct pci_dev *pdev)
 
 static int ath_pci_suspend(struct device *device)
 {
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct ieee80211_hw *hw = dev_get_drvdata(device);
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
        if (test_bit(ATH_OP_WOW_ENABLED, &common->op_flags)) {
-               dev_info(&pdev->dev, "WOW is enabled, bypassing PCI suspend\n");
+               dev_info(device, "WOW is enabled, bypassing PCI suspend\n");
                return 0;
        }
 
index 18dd8b2..f1a2823 100644 (file)
@@ -629,8 +629,7 @@ static int __maybe_unused wil6210_pm_resume(struct device *dev)
 
 static int __maybe_unused wil6210_pm_runtime_idle(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct wil6210_priv *wil = pci_get_drvdata(pdev);
+       struct wil6210_priv *wil = dev_get_drvdata(dev);
 
        wil_dbg_pm(wil, "Runtime idle\n");
 
@@ -644,8 +643,7 @@ static int __maybe_unused wil6210_pm_runtime_resume(struct device *dev)
 
 static int __maybe_unused wil6210_pm_runtime_suspend(struct device *dev)
 {
-       struct pci_dev *pdev = to_pci_dev(dev);
-       struct wil6210_priv *wil = pci_get_drvdata(pdev);
+       struct wil6210_priv *wil = dev_get_drvdata(dev);
 
        if (test_bit(wil_status_suspended, wil->status)) {
                wil_dbg_pm(wil, "trying to suspend while suspended\n");
index 153b844..f9a006d 100644 (file)
@@ -2505,7 +2505,8 @@ int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie)
        cmd->mgmt_frm_type = type;
        /* BUG: FW API define ieLen as u8. Will fix FW */
        cmd->ie_len = cpu_to_le16(ie_len);
-       memcpy(cmd->ie_info, ie, ie_len);
+       if (ie_len)
+               memcpy(cmd->ie_info, ie, ie_len);
        rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
        kfree(cmd);
 out:
@@ -2541,7 +2542,8 @@ int wmi_update_ft_ies(struct wil6210_vif *vif, u16 ie_len, const void *ie)
        }
 
        cmd->ie_len = cpu_to_le16(ie_len);
-       memcpy(cmd->ie_info, ie, ie_len);
+       if (ie_len)
+               memcpy(cmd->ie_info, ie, ie_len);
        rc = wmi_send(wil, WMI_UPDATE_FT_IES_CMDID, vif->mid, cmd, len);
        kfree(cmd);
 
@@ -2715,7 +2717,7 @@ int wmi_get_all_temperatures(struct wil6210_priv *wil,
                return rc;
 
        if (reply.evt.status == WMI_FW_STATUS_FAILURE) {
-               wil_err(wil, "Failed geting TEMP_SENSE_ALL\n");
+               wil_err(wil, "Failed getting TEMP_SENSE_ALL\n");
                return -EINVAL;
        }