Merge ath-next from ath.git
authorKalle Valo <kvalo@codeaurora.org>
Thu, 7 Apr 2016 18:44:37 +0000 (21:44 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 7 Apr 2016 18:44:37 +0000 (21:44 +0300)
ath.git patches for 4.7. Major changes:

ath10k

* implement push-pull tx model using mac80211 software queuing support
* enable scan in AP mode (NL80211_FEATURE_AP_SCAN)

wil6210

* add basic PBSS (Personal Basic Service Set) support
* add initial P2P support
* add oob_mode module parameter

70 files changed:
Documentation/devicetree/bindings/net/wireless/qcom,ath10k.txt
drivers/net/wireless/ath/ath10k/ce.c
drivers/net/wireless/ath/ath10k/ce.h
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/debug.c
drivers/net/wireless/ath/ath10k/htt.c
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/htt_tx.c
drivers/net/wireless/ath/ath10k/hw.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/txrx.c
drivers/net/wireless/ath/ath10k/txrx.h
drivers/net/wireless/ath/ath10k/wmi-ops.h
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath5k/led.c
drivers/net/wireless/ath/ath5k/phy.c
drivers/net/wireless/ath/ath5k/reset.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_mci.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
drivers/net/wireless/ath/ath9k/ar9340_initvals.h
drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9462_2p1_initvals.h
drivers/net/wireless/ath/ath9k/ar9485_initvals.h
drivers/net/wireless/ath/ath9k/ar953x_initvals.h
drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ar956x_initvals.h
drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/btcoex.c
drivers/net/wireless/ath/ath9k/btcoex.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/ath/ath9k/rng.c
drivers/net/wireless/ath/wil6210/Makefile
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/ioctl.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/netdev.c
drivers/net/wireless/ath/wil6210/p2p.c [new file with mode: 0644]
drivers/net/wireless/ath/wil6210/pcie_bus.c
drivers/net/wireless/ath/wil6210/rx_reorder.c
drivers/net/wireless/ath/wil6210/trace.h
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/txrx.h
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/ath/wil6210/wil_platform.h
drivers/net/wireless/ath/wil6210/wmi.c
drivers/net/wireless/ath/wil6210/wmi.h
include/linux/ath9k_platform.h

index 96aae6b4f736802df34a6524202a5dd2653e4231..74d7f0af209c8178f078b99a9dd460d44d430f8c 100644 (file)
@@ -5,12 +5,18 @@ Required properties:
        * "qcom,ath10k"
        * "qcom,ipq4019-wifi"
 
-PCI based devices uses compatible string "qcom,ath10k" and takes only
-calibration data via "qcom,ath10k-calibration-data". Rest of the properties
-are not applicable for PCI based devices.
+PCI based devices uses compatible string "qcom,ath10k" and takes calibration
+data along with board specific data via "qcom,ath10k-calibration-data".
+Rest of the properties are not applicable for PCI based devices.
 
 AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi"
-and also uses most of the properties defined in this doc.
+and also uses most of the properties defined in this doc (except
+"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data"
+to carry pre calibration data.
+
+In general, entry "qcom,ath10k-pre-calibration-data" and
+"qcom,ath10k-calibration-data" conflict with each other and only one
+can be provided per device.
 
 Optional properties:
 - reg: Address and length of the register set for the device.
@@ -35,8 +41,11 @@ Optional properties:
 - qcom,msi_addr: MSI interrupt address.
 - qcom,msi_base: Base value to add before writing MSI data into
                MSI address register.
-- qcom,ath10k-calibration-data : calibration data as an array, the
-                                length can vary between hw versions
+- qcom,ath10k-calibration-data : calibration data + board specific data
+                                as an array, the length can vary between
+                                hw versions.
+- qcom,ath10k-pre-calibration-data : pre calibration data as an array,
+                                    the length can vary between hw versions.
 
 Example (to supply the calibration data alone):
 
@@ -105,5 +114,5 @@ wifi0: wifi@a000000 {
                          "legacy";
        qcom,msi_addr = <0x0b006040>;
        qcom,msi_base = <0x40>;
-       qcom,ath10k-calibration-data = [ 01 02 03 ... ];
+       qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ];
 };
index edf3629288bc49cb1832b41028efdd79b8b32546..7212802eb3274cfd5a4857666ef214efb1146bc7 100644 (file)
@@ -411,7 +411,8 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
 
        lockdep_assert_held(&ar_pci->ce_lock);
 
-       if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
+       if ((pipe->id != 5) &&
+           CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
                return -ENOSPC;
 
        desc->addr = __cpu_to_le32(paddr);
@@ -425,6 +426,19 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
        return 0;
 }
 
+void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries)
+{
+       struct ath10k *ar = pipe->ar;
+       struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
+       unsigned int nentries_mask = dest_ring->nentries_mask;
+       unsigned int write_index = dest_ring->write_index;
+       u32 ctrl_addr = pipe->ctrl_addr;
+
+       write_index = CE_RING_IDX_ADD(nentries_mask, write_index, nentries);
+       ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
+       dest_ring->write_index = write_index;
+}
+
 int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
 {
        struct ath10k *ar = pipe->ar;
@@ -444,14 +458,10 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
  */
 int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
                                         void **per_transfer_contextp,
-                                        u32 *bufferp,
-                                        unsigned int *nbytesp,
-                                        unsigned int *transfer_idp,
-                                        unsigned int *flagsp)
+                                        unsigned int *nbytesp)
 {
        struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
        unsigned int nentries_mask = dest_ring->nentries_mask;
-       struct ath10k *ar = ce_state->ar;
        unsigned int sw_index = dest_ring->sw_index;
 
        struct ce_desc *base = dest_ring->base_addr_owner_space;
@@ -476,21 +486,17 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
        desc->nbytes = 0;
 
        /* Return data from completed destination descriptor */
-       *bufferp = __le32_to_cpu(sdesc.addr);
        *nbytesp = nbytes;
-       *transfer_idp = MS(__le16_to_cpu(sdesc.flags), CE_DESC_FLAGS_META_DATA);
-
-       if (__le16_to_cpu(sdesc.flags) & CE_DESC_FLAGS_BYTE_SWAP)
-               *flagsp = CE_RECV_FLAG_SWAPPED;
-       else
-               *flagsp = 0;
 
        if (per_transfer_contextp)
                *per_transfer_contextp =
                        dest_ring->per_transfer_context[sw_index];
 
-       /* sanity */
-       dest_ring->per_transfer_context[sw_index] = NULL;
+       /* Copy engine 5 (HTT Rx) will reuse the same transfer context.
+        * So update transfer context all CEs except CE5.
+        */
+       if (ce_state->id != 5)
+               dest_ring->per_transfer_context[sw_index] = NULL;
 
        /* Update sw_index */
        sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
@@ -501,10 +507,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
 
 int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
                                  void **per_transfer_contextp,
-                                 u32 *bufferp,
-                                 unsigned int *nbytesp,
-                                 unsigned int *transfer_idp,
-                                 unsigned int *flagsp)
+                                 unsigned int *nbytesp)
 {
        struct ath10k *ar = ce_state->ar;
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -513,8 +516,7 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
        spin_lock_bh(&ar_pci->ce_lock);
        ret = ath10k_ce_completed_recv_next_nolock(ce_state,
                                                   per_transfer_contextp,
-                                                  bufferp, nbytesp,
-                                                  transfer_idp, flagsp);
+                                                  nbytesp);
        spin_unlock_bh(&ar_pci->ce_lock);
 
        return ret;
index 47b734ce7ecf42112a582eaa2756ec3d6aca3868..25cafcfd6b12750fc1f48ee4d36bf9365c622740 100644 (file)
@@ -22,7 +22,7 @@
 
 /* Maximum number of Copy Engine's supported */
 #define CE_COUNT_MAX 12
-#define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
+#define CE_HTT_H2T_MSG_SRC_NENTRIES 8192
 
 /* Descriptor rings must be aligned to this boundary */
 #define CE_DESC_RING_ALIGN     8
@@ -166,6 +166,7 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
 int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
 int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
 int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
+void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries);
 
 /* recv flags */
 /* Data is byte-swapped */
@@ -177,10 +178,7 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
  */
 int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
                                  void **per_transfer_contextp,
-                                 u32 *bufferp,
-                                 unsigned int *nbytesp,
-                                 unsigned int *transfer_idp,
-                                 unsigned int *flagsp);
+                                 unsigned int *nbytesp);
 /*
  * Supply data for the next completed unprocessed send descriptor.
  * Pops 1 completed send buffer from Source ring.
@@ -212,10 +210,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
 
 int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
                                         void **per_transfer_contextp,
-                                        u32 *bufferp,
-                                        unsigned int *nbytesp,
-                                        unsigned int *transfer_idp,
-                                        unsigned int *flagsp);
+                                        unsigned int *nbytesp);
 
 /*
  * Support clean shutdown by allowing the caller to cancel
@@ -416,6 +411,8 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
        (((int)(toidx)-(int)(fromidx)) & (nentries_mask))
 
 #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
+#define CE_RING_IDX_ADD(nentries_mask, idx, num) \
+               (((idx) + (num)) & (nentries_mask))
 
 #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \
                                ar->regs->ce_wrap_intr_sum_host_msi_lsb
index c84c2d30ef1f3f8c127eaca4baafee0d748f07d6..b2c7fe3d30a4e155a2218c93f82f6ba27408d230 100644 (file)
@@ -60,6 +60,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 2116,
                .fw = {
                        .dir = QCA988X_HW_2_0_FW_DIR,
                        .fw = QCA988X_HW_2_0_FW_FILE,
@@ -78,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
                        .fw = QCA6174_HW_2_1_FW_FILE,
@@ -97,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
                        .fw = QCA6174_HW_2_1_FW_FILE,
@@ -116,6 +119,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA6174_HW_3_0_FW_DIR,
                        .fw = QCA6174_HW_3_0_FW_FILE,
@@ -135,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 8124,
                .fw = {
                        /* uses same binaries as hw3.0 */
                        .dir = QCA6174_HW_3_0_FW_DIR,
@@ -156,11 +161,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 150000,
                .max_probe_resp_desc_thres = 24,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
-               .num_msdu_desc = 1424,
-               .qcache_active_peers = 50,
                .tx_chain_mask = 0xf,
                .rx_chain_mask = 0xf,
                .max_spatial_stream = 4,
+               .cal_data_len = 12064,
                .fw = {
                        .dir = QCA99X0_HW_2_0_FW_DIR,
                        .fw = QCA99X0_HW_2_0_FW_FILE,
@@ -179,6 +183,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA9377_HW_1_0_FW_DIR,
                        .fw = QCA9377_HW_1_0_FW_FILE,
@@ -197,6 +202,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA9377_HW_1_0_FW_DIR,
                        .fw = QCA9377_HW_1_0_FW_FILE,
@@ -217,11 +223,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 125000,
                .max_probe_resp_desc_thres = 24,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
-               .num_msdu_desc = 2500,
-               .qcache_active_peers = 35,
                .tx_chain_mask = 0x3,
                .rx_chain_mask = 0x3,
                .max_spatial_stream = 2,
+               .cal_data_len = 12064,
                .fw = {
                        .dir = QCA4019_HW_1_0_FW_DIR,
                        .fw = QCA4019_HW_1_0_FW_FILE,
@@ -466,18 +471,18 @@ exit:
        return ret;
 }
 
-static int ath10k_download_cal_file(struct ath10k *ar)
+static int ath10k_download_cal_file(struct ath10k *ar,
+                                   const struct firmware *file)
 {
        int ret;
 
-       if (!ar->cal_file)
+       if (!file)
                return -ENOENT;
 
-       if (IS_ERR(ar->cal_file))
-               return PTR_ERR(ar->cal_file);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
 
-       ret = ath10k_download_board_data(ar, ar->cal_file->data,
-                                        ar->cal_file->size);
+       ret = ath10k_download_board_data(ar, file->data, file->size);
        if (ret) {
                ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
                return ret;
@@ -488,7 +493,7 @@ static int ath10k_download_cal_file(struct ath10k *ar)
        return 0;
 }
 
-static int ath10k_download_cal_dt(struct ath10k *ar)
+static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
 {
        struct device_node *node;
        int data_len;
@@ -502,13 +507,12 @@ static int ath10k_download_cal_dt(struct ath10k *ar)
                 */
                return -ENOENT;
 
-       if (!of_get_property(node, "qcom,ath10k-calibration-data",
-                            &data_len)) {
+       if (!of_get_property(node, dt_name, &data_len)) {
                /* The calibration data node is optional */
                return -ENOENT;
        }
 
-       if (data_len != QCA988X_CAL_DATA_LEN) {
+       if (data_len != ar->hw_params.cal_data_len) {
                ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
                            data_len);
                ret = -EMSGSIZE;
@@ -521,8 +525,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar)
                goto out;
        }
 
-       ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data",
-                                       data, data_len);
+       ret = of_property_read_u8_array(node, dt_name, data, data_len);
        if (ret) {
                ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
                            ret);
@@ -726,6 +729,14 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
 {
        char filename[100];
 
+       /* pre-cal-<bus>-<id>.bin */
+       scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin",
+                 ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
+
+       ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
+       if (!IS_ERR(ar->pre_cal_file))
+               goto success;
+
        /* cal-<bus>-<id>.bin */
        scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
                  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
@@ -734,7 +745,7 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
        if (IS_ERR(ar->cal_file))
                /* calibration file is optional, don't print any warnings */
                return PTR_ERR(ar->cal_file);
-
+success:
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
                   ATH10K_FW_DIR, filename);
 
@@ -1258,11 +1269,77 @@ success:
        return 0;
 }
 
+static int ath10k_core_pre_cal_download(struct ath10k *ar)
+{
+       int ret;
+
+       ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
+       if (ret == 0) {
+               ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
+               goto success;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "boot did not find a pre calibration file, try DT next: %d\n",
+                  ret);
+
+       ret = ath10k_download_cal_dt(ar, "qcom,ath10k-pre-calibration-data");
+       if (ret) {
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "unable to load pre cal data from DT: %d\n", ret);
+               return ret;
+       }
+       ar->cal_mode = ATH10K_PRE_CAL_MODE_DT;
+
+success:
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
+                  ath10k_cal_mode_str(ar->cal_mode));
+
+       return 0;
+}
+
+static int ath10k_core_pre_cal_config(struct ath10k *ar)
+{
+       int ret;
+
+       ret = ath10k_core_pre_cal_download(ar);
+       if (ret) {
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "failed to load pre cal data: %d\n", ret);
+               return ret;
+       }
+
+       ret = ath10k_core_get_board_id_from_otp(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to get board id: %d\n", ret);
+               return ret;
+       }
+
+       ret = ath10k_download_and_run_otp(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to run otp: %d\n", ret);
+               return ret;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "pre cal configuration done successfully\n");
+
+       return 0;
+}
+
 static int ath10k_download_cal_data(struct ath10k *ar)
 {
        int ret;
 
-       ret = ath10k_download_cal_file(ar);
+       ret = ath10k_core_pre_cal_config(ar);
+       if (ret == 0)
+               return 0;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "pre cal download procedure failed, try cal file: %d\n",
+                  ret);
+
+       ret = ath10k_download_cal_file(ar, ar->cal_file);
        if (ret == 0) {
                ar->cal_mode = ATH10K_CAL_MODE_FILE;
                goto done;
@@ -1272,7 +1349,7 @@ static int ath10k_download_cal_data(struct ath10k *ar)
                   "boot did not find a calibration file, try DT next: %d\n",
                   ret);
 
-       ret = ath10k_download_cal_dt(ar);
+       ret = ath10k_download_cal_dt(ar, "qcom,ath10k-calibration-data");
        if (ret == 0) {
                ar->cal_mode = ATH10K_CAL_MODE_DT;
                goto done;
@@ -1509,7 +1586,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
        case ATH10K_FW_WMI_OP_VERSION_10_1:
        case ATH10K_FW_WMI_OP_VERSION_10_2:
        case ATH10K_FW_WMI_OP_VERSION_10_2_4:
-               if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
+               if (ath10k_peer_stats_enabled(ar)) {
                        ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
                        ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
                } else {
@@ -1538,9 +1615,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
                ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
                ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
-               ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc;
-               ar->fw_stats_req_mask = WMI_STAT_PEER;
+               ar->fw_stats_req_mask = WMI_10_4_STAT_PEER |
+                                       WMI_10_4_STAT_PEER_EXTD;
                ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
+
+               if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
+                            ar->fw_features))
+                       ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC;
+               else
+                       ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
                break;
        case ATH10K_FW_WMI_OP_VERSION_UNSET:
        case ATH10K_FW_WMI_OP_VERSION_MAX:
@@ -1578,6 +1661,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
 int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
 {
        int status;
+       u32 val;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -1698,6 +1782,21 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
                   ar->hw->wiphy->fw_version);
 
+       if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) {
+               val = 0;
+               if (ath10k_peer_stats_enabled(ar))
+                       val = WMI_10_4_PEER_STATS;
+
+               status = ath10k_wmi_ext_resource_config(ar,
+                                                       WMI_HOST_PLATFORM_HIGH_PERF, val);
+               if (status) {
+                       ath10k_err(ar,
+                                  "failed to send ext resource cfg command : %d\n",
+                                  status);
+                       goto err_hif_stop;
+               }
+       }
+
        status = ath10k_wmi_cmd_init(ar);
        if (status) {
                ath10k_err(ar, "could not send WMI init command (%d)\n",
@@ -1834,11 +1933,20 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
        ath10k_debug_print_hwfw_info(ar);
 
+       ret = ath10k_core_pre_cal_download(ar);
+       if (ret) {
+               /* pre calibration data download is not necessary
+                * for all the chipsets. Ignore failures and continue.
+                */
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "could not load pre cal data: %d\n", ret);
+       }
+
        ret = ath10k_core_get_board_id_from_otp(ar);
        if (ret && ret != -EOPNOTSUPP) {
                ath10k_err(ar, "failed to get board id from otp: %d\n",
                           ret);
-               return ret;
+               goto err_free_firmware_files;
        }
 
        ret = ath10k_core_fetch_board_file(ar);
@@ -2048,7 +2156,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 
        mutex_init(&ar->conf_mutex);
        spin_lock_init(&ar->data_lock);
+       spin_lock_init(&ar->txqs_lock);
 
+       INIT_LIST_HEAD(&ar->txqs);
        INIT_LIST_HEAD(&ar->peers);
        init_waitqueue_head(&ar->peer_mapping_wq);
        init_waitqueue_head(&ar->htt.empty_tx_wq);
index a62b62a6226687e4f1ee09b8ba721588b79cbb9f..d85b99164212f9750d16fbf004d449758ffd535d 100644 (file)
@@ -98,6 +98,7 @@ struct ath10k_skb_cb {
        u8 eid;
        u16 msdu_id;
        struct ieee80211_vif *vif;
+       struct ieee80211_txq *txq;
 } __packed;
 
 struct ath10k_skb_rxcb {
@@ -297,6 +298,9 @@ struct ath10k_dfs_stats {
 
 struct ath10k_peer {
        struct list_head list;
+       struct ieee80211_vif *vif;
+       struct ieee80211_sta *sta;
+
        int vdev_id;
        u8 addr[ETH_ALEN];
        DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
@@ -305,6 +309,12 @@ struct ath10k_peer {
        struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
 };
 
+struct ath10k_txq {
+       struct list_head list;
+       unsigned long num_fw_queued;
+       unsigned long num_push_allowed;
+};
+
 struct ath10k_sta {
        struct ath10k_vif *arvif;
 
@@ -313,6 +323,7 @@ struct ath10k_sta {
        u32 bw;
        u32 nss;
        u32 smps;
+       u16 peer_id;
 
        struct work_struct update_wk;
 
@@ -335,6 +346,7 @@ struct ath10k_vif {
        struct list_head list;
 
        u32 vdev_id;
+       u16 peer_id;
        enum wmi_vdev_type vdev_type;
        enum wmi_vdev_subtype vdev_subtype;
        u32 beacon_interval;
@@ -549,12 +561,17 @@ enum ath10k_dev_flags {
 
        /* Bluetooth coexistance enabled */
        ATH10K_FLAG_BTCOEX,
+
+       /* Per Station statistics service */
+       ATH10K_FLAG_PEER_STATS,
 };
 
 enum ath10k_cal_mode {
        ATH10K_CAL_MODE_FILE,
        ATH10K_CAL_MODE_OTP,
        ATH10K_CAL_MODE_DT,
+       ATH10K_PRE_CAL_MODE_FILE,
+       ATH10K_PRE_CAL_MODE_DT,
 };
 
 enum ath10k_crypt_mode {
@@ -573,6 +590,10 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
                return "otp";
        case ATH10K_CAL_MODE_DT:
                return "dt";
+       case ATH10K_PRE_CAL_MODE_FILE:
+               return "pre-cal-file";
+       case ATH10K_PRE_CAL_MODE_DT:
+               return "pre-cal-dt";
        }
 
        return "unknown";
@@ -680,11 +701,10 @@ struct ath10k {
                /* The padding bytes's location is different on various chips */
                enum ath10k_hw_4addr_pad hw_4addr_pad;
 
-               u32 num_msdu_desc;
-               u32 qcache_active_peers;
                u32 tx_chain_mask;
                u32 rx_chain_mask;
                u32 max_spatial_stream;
+               u32 cal_data_len;
 
                struct ath10k_hw_params_fw {
                        const char *dir;
@@ -708,6 +728,7 @@ struct ath10k {
        const void *firmware_data;
        size_t firmware_len;
 
+       const struct firmware *pre_cal_file;
        const struct firmware *cal_file;
 
        struct {
@@ -756,6 +777,9 @@ struct ath10k {
        /* current operating channel definition */
        struct cfg80211_chan_def chandef;
 
+       /* currently configured operating channel in firmware */
+       struct ieee80211_channel *tgt_oper_chan;
+
        unsigned long long free_vdev_map;
        struct ath10k_vif *monitor_arvif;
        bool monitor;
@@ -786,9 +810,13 @@ struct ath10k {
 
        /* protects shared structure data */
        spinlock_t data_lock;
+       /* protects: ar->txqs, artxq->list */
+       spinlock_t txqs_lock;
 
+       struct list_head txqs;
        struct list_head arvifs;
        struct list_head peers;
+       struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
        wait_queue_head_t peer_mapping_wq;
 
        /* protected by conf_mutex */
@@ -876,6 +904,15 @@ struct ath10k {
        u8 drv_priv[0] __aligned(sizeof(void *));
 };
 
+static inline bool ath10k_peer_stats_enabled(struct ath10k *ar)
+{
+       if (test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) &&
+           test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
+               return true;
+
+       return false;
+}
+
 struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
                                  enum ath10k_bus bus,
                                  enum ath10k_hw_rev hw_rev,
index 076d29b53ddff67a5b687dc6b722632db20d111c..76bbe17b25b6ae10e98b67fcea3fa47d0e6fcf6f 100644 (file)
@@ -127,6 +127,7 @@ EXPORT_SYMBOL(ath10k_info);
 void ath10k_debug_print_hwfw_info(struct ath10k *ar)
 {
        char fw_features[128] = {};
+       u32 crc = 0;
 
        ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
 
@@ -143,11 +144,14 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar)
                    config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
                    config_enabled(CONFIG_NL80211_TESTMODE));
 
+       if (ar->firmware)
+               crc = crc32_le(0, ar->firmware->data, ar->firmware->size);
+
        ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
                    ar->hw->wiphy->fw_version,
                    ar->fw_api,
                    fw_features,
-                   crc32_le(0, ar->firmware->data, ar->firmware->size));
+                   crc);
 }
 
 void ath10k_debug_print_board_info(struct ath10k *ar)
@@ -319,7 +323,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
 void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ath10k_fw_stats stats = {};
-       bool is_start, is_started, is_end, peer_stats_svc;
+       bool is_start, is_started, is_end;
        size_t num_peers;
        size_t num_vdevs;
        int ret;
@@ -346,13 +350,11 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
         *  b) consume stat update events until another one with pdev stats is
         *     delivered which is treated as end-of-data and is itself discarded
         */
-
-       peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map);
-       if (peer_stats_svc)
+       if (ath10k_peer_stats_enabled(ar))
                ath10k_sta_update_rx_duration(ar, &stats.peers);
 
        if (ar->debug.fw_stats_done) {
-               if (!peer_stats_svc)
+               if (!ath10k_peer_stats_enabled(ar))
                        ath10k_warn(ar, "received unsolicited stats update event\n");
 
                goto free;
@@ -1447,7 +1449,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
                goto err;
        }
 
-       buf = vmalloc(QCA988X_CAL_DATA_LEN);
+       buf = vmalloc(ar->hw_params.cal_data_len);
        if (!buf) {
                ret = -ENOMEM;
                goto err;
@@ -1462,7 +1464,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
        }
 
        ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
-                                  QCA988X_CAL_DATA_LEN);
+                                  ar->hw_params.cal_data_len);
        if (ret) {
                ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
                goto err_vfree;
@@ -1487,10 +1489,11 @@ static ssize_t ath10k_debug_cal_data_read(struct file *file,
                                          char __user *user_buf,
                                          size_t count, loff_t *ppos)
 {
+       struct ath10k *ar = file->private_data;
        void *buf = file->private_data;
 
        return simple_read_from_buffer(user_buf, count, ppos,
-                                      buf, QCA988X_CAL_DATA_LEN);
+                                      buf, ar->hw_params.cal_data_len);
 }
 
 static int ath10k_debug_cal_data_release(struct inode *inode,
@@ -2019,7 +2022,12 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file,
                goto out;
        }
 
-       if (filter && (filter != ar->debug.pktlog_filter)) {
+       if (filter == ar->debug.pktlog_filter) {
+               ret = count;
+               goto out;
+       }
+
+       if (filter) {
                ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
                if (ret) {
                        ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
@@ -2174,6 +2182,73 @@ static const struct file_operations fops_btcoex = {
        .open = simple_open
 };
 
+static ssize_t ath10k_write_peer_stats(struct file *file,
+                                      const char __user *ubuf,
+                                      size_t count, loff_t *ppos)
+{
+       struct ath10k *ar = file->private_data;
+       char buf[32];
+       size_t buf_size;
+       int ret = 0;
+       bool val;
+
+       buf_size = min(count, (sizeof(buf) - 1));
+       if (copy_from_user(buf, ubuf, buf_size))
+               return -EFAULT;
+
+       buf[buf_size] = '\0';
+
+       if (strtobool(buf, &val) != 0)
+               return -EINVAL;
+
+       mutex_lock(&ar->conf_mutex);
+
+       if (ar->state != ATH10K_STATE_ON &&
+           ar->state != ATH10K_STATE_RESTARTED) {
+               ret = -ENETDOWN;
+               goto exit;
+       }
+
+       if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val))
+               goto exit;
+
+       if (val)
+               set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
+       else
+               clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
+
+       ath10k_info(ar, "restarting firmware due to Peer stats change");
+
+       queue_work(ar->workqueue, &ar->restart_work);
+       ret = count;
+
+exit:
+       mutex_unlock(&ar->conf_mutex);
+       return ret;
+}
+
+static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
+                                     size_t count, loff_t *ppos)
+
+{
+       char buf[32];
+       struct ath10k *ar = file->private_data;
+       int len = 0;
+
+       mutex_lock(&ar->conf_mutex);
+       len = scnprintf(buf, sizeof(buf) - len, "%d\n",
+                       test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
+       mutex_unlock(&ar->conf_mutex);
+
+       return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_peer_stats = {
+       .read = ath10k_read_peer_stats,
+       .write = ath10k_write_peer_stats,
+       .open = simple_open
+};
+
 static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
                                              char __user *user_buf,
                                              size_t count, loff_t *ppos)
@@ -2337,6 +2412,11 @@ int ath10k_debug_register(struct ath10k *ar)
                debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
                                    ar->debug.debugfs_phy, ar, &fops_btcoex);
 
+       if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
+               debugfs_create_file("peer_stats", S_IRUGO | S_IWUSR,
+                                   ar->debug.debugfs_phy, ar,
+                                   &fops_peer_stats);
+
        debugfs_create_file("fw_checksums", S_IRUSR,
                            ar->debug.debugfs_phy, ar, &fops_fw_checksums);
 
index 7561f22f10f9c92266e4e73d6826f465acd0f361..17a3008d9ab16d6aa38f3cc03fda6ad840b92488 100644 (file)
@@ -149,7 +149,7 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
        memset(&conn_resp, 0, sizeof(conn_resp));
 
        conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete;
-       conn_req.ep_ops.ep_rx_complete = ath10k_htt_t2h_msg_handler;
+       conn_req.ep_ops.ep_rx_complete = ath10k_htt_htc_t2h_msg_handler;
 
        /* connect to control service */
        conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG;
index 13391ea4422d3f5acf0adf3d0e10ed35a3b535b1..60bd9fe4b2d931178233b85e5c59b3cc0acb49cb 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/interrupt.h>
 #include <linux/dmapool.h>
 #include <linux/hashtable.h>
+#include <linux/kfifo.h>
 #include <net/mac80211.h>
 
 #include "htc.h"
@@ -1461,6 +1462,14 @@ struct htt_tx_mode_switch_ind {
        struct htt_tx_mode_switch_record records[0];
 } __packed;
 
+struct htt_channel_change {
+       u8 pad[3];
+       __le32 freq;
+       __le32 center_freq1;
+       __le32 center_freq2;
+       __le32 phymode;
+} __packed;
+
 union htt_rx_pn_t {
        /* WEP: 24-bit PN */
        u32 pn24;
@@ -1511,16 +1520,22 @@ struct htt_resp {
                struct htt_tx_fetch_ind tx_fetch_ind;
                struct htt_tx_fetch_confirm tx_fetch_confirm;
                struct htt_tx_mode_switch_ind tx_mode_switch_ind;
+               struct htt_channel_change chan_change;
        };
 } __packed;
 
 /*** host side structures follow ***/
 
 struct htt_tx_done {
-       u32 msdu_id;
-       bool discard;
-       bool no_ack;
-       bool success;
+       u16 msdu_id;
+       u16 status;
+};
+
+enum htt_tx_compl_state {
+       HTT_TX_COMPL_STATE_NONE,
+       HTT_TX_COMPL_STATE_ACK,
+       HTT_TX_COMPL_STATE_NOACK,
+       HTT_TX_COMPL_STATE_DISCARD,
 };
 
 struct htt_peer_map_event {
@@ -1641,17 +1656,20 @@ struct ath10k_htt {
        struct idr pending_tx;
        wait_queue_head_t empty_tx_wq;
 
+       /* FIFO for storing tx done status {ack, no-ack, discard} and msdu id */
+       DECLARE_KFIFO_PTR(txdone_fifo, struct htt_tx_done);
+
        /* set if host-fw communication goes haywire
         * used to avoid further failures */
        bool rx_confused;
-       struct tasklet_struct rx_replenish_task;
+       atomic_t num_mpdus_ready;
 
        /* This is used to group tx/rx completions separately and process them
         * in batches to reduce cache stalls */
        struct tasklet_struct txrx_compl_task;
-       struct sk_buff_head tx_compl_q;
        struct sk_buff_head rx_compl_q;
        struct sk_buff_head rx_in_ord_compl_q;
+       struct sk_buff_head tx_fetch_ind_q;
 
        /* rx_status template */
        struct ieee80211_rx_status rx_status;
@@ -1667,10 +1685,13 @@ struct ath10k_htt {
        } txbuf;
 
        struct {
+               bool enabled;
                struct htt_q_state *vaddr;
                dma_addr_t paddr;
+               u16 num_push_allowed;
                u16 num_peers;
                u16 num_tids;
+               enum htt_tx_mode_switch_mode mode;
                enum htt_q_depth_type type;
        } tx_q_state;
 };
@@ -1715,7 +1736,7 @@ struct htt_rx_desc {
 
 /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle
  * aggregated traffic more nicely. */
-#define ATH10K_HTT_MAX_NUM_REFILL 16
+#define ATH10K_HTT_MAX_NUM_REFILL 100
 
 /*
  * DMA_MAP expects the buffer to be an integral number of cache lines.
@@ -1743,7 +1764,8 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar);
 void ath10k_htt_rx_free(struct ath10k_htt *htt);
 
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
-void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
+bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
 int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
 int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
 int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt);
@@ -1752,8 +1774,23 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
                                u8 max_subfrms_ampdu,
                                u8 max_subfrms_amsdu);
 void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb);
+int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
+                            __le32 token,
+                            __le16 fetch_seq_num,
+                            struct htt_tx_fetch_record *records,
+                            size_t num_records);
+
+void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
+                             struct ieee80211_txq *txq);
+void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
+                             struct ieee80211_txq *txq);
+void ath10k_htt_tx_txq_sync(struct ath10k *ar);
+void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
+int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt);
+void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt);
+int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
+                                  bool is_presp);
 
-void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
 int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
 void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
 int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
index ae9b686a4e912298723d32a022af479d5854c5f4..6a2d2643de420db2d93472b367a721bce40a34e8 100644 (file)
@@ -31,6 +31,8 @@
 /* when under memory pressure rx ring refill may fail and needs a retry */
 #define HTT_RX_RING_REFILL_RETRY_MS 50
 
+#define HTT_RX_RING_REFILL_RESCHED_MS 5
+
 static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
 static void ath10k_htt_txrx_compl_task(unsigned long ptr);
 
@@ -192,7 +194,8 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt)
                mod_timer(&htt->rx_ring.refill_retry_timer, jiffies +
                          msecs_to_jiffies(HTT_RX_RING_REFILL_RETRY_MS));
        } else if (num_deficit > 0) {
-               tasklet_schedule(&htt->rx_replenish_task);
+               mod_timer(&htt->rx_ring.refill_retry_timer, jiffies +
+                         msecs_to_jiffies(HTT_RX_RING_REFILL_RESCHED_MS));
        }
        spin_unlock_bh(&htt->rx_ring.lock);
 }
@@ -223,12 +226,11 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar)
 void ath10k_htt_rx_free(struct ath10k_htt *htt)
 {
        del_timer_sync(&htt->rx_ring.refill_retry_timer);
-       tasklet_kill(&htt->rx_replenish_task);
        tasklet_kill(&htt->txrx_compl_task);
 
-       skb_queue_purge(&htt->tx_compl_q);
        skb_queue_purge(&htt->rx_compl_q);
        skb_queue_purge(&htt->rx_in_ord_compl_q);
+       skb_queue_purge(&htt->tx_fetch_ind_q);
 
        ath10k_htt_rx_ring_free(htt);
 
@@ -281,7 +283,6 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
 
 /* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */
 static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
-                                  u8 **fw_desc, int *fw_desc_len,
                                   struct sk_buff_head *amsdu)
 {
        struct ath10k *ar = htt->ar;
@@ -323,48 +324,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
                        return -EIO;
                }
 
-               /*
-                * Copy the FW rx descriptor for this MSDU from the rx
-                * indication message into the MSDU's netbuf. HL uses the
-                * same rx indication message definition as LL, and simply
-                * appends new info (fields from the HW rx desc, and the
-                * MSDU payload itself). So, the offset into the rx
-                * indication message only has to account for the standard
-                * offset of the per-MSDU FW rx desc info within the
-                * message, and how many bytes of the per-MSDU FW rx desc
-                * info have already been consumed. (And the endianness of
-                * the host, since for a big-endian host, the rx ind
-                * message contents, including the per-MSDU rx desc bytes,
-                * were byteswapped during upload.)
-                */
-               if (*fw_desc_len > 0) {
-                       rx_desc->fw_desc.info0 = **fw_desc;
-                       /*
-                        * The target is expected to only provide the basic
-                        * per-MSDU rx descriptors. Just to be sure, verify
-                        * that the target has not attached extension data
-                        * (e.g. LRO flow ID).
-                        */
-
-                       /* or more, if there's extension data */
-                       (*fw_desc)++;
-                       (*fw_desc_len)--;
-               } else {
-                       /*
-                        * When an oversized AMSDU happened, FW will lost
-                        * some of MSDU status - in this case, the FW
-                        * descriptors provided will be less than the
-                        * actual MSDUs inside this MPDU. Mark the FW
-                        * descriptors so that it will still deliver to
-                        * upper stack, if no CRC error for this MPDU.
-                        *
-                        * FIX THIS - the FW descriptors are actually for
-                        * MSDUs in the end of this A-MSDU instead of the
-                        * beginning.
-                        */
-                       rx_desc->fw_desc.info0 = 0;
-               }
-
                msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags)
                                        & (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR |
                                           RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR));
@@ -423,13 +382,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
        return msdu_chaining;
 }
 
-static void ath10k_htt_rx_replenish_task(unsigned long ptr)
-{
-       struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
-
-       ath10k_htt_rx_msdu_buff_replenish(htt);
-}
-
 static struct sk_buff *ath10k_htt_rx_pop_paddr(struct ath10k_htt *htt,
                                               u32 paddr)
 {
@@ -563,12 +515,10 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
        htt->rx_ring.sw_rd_idx.msdu_payld = 0;
        hash_init(htt->rx_ring.skb_table);
 
-       tasklet_init(&htt->rx_replenish_task, ath10k_htt_rx_replenish_task,
-                    (unsigned long)htt);
-
-       skb_queue_head_init(&htt->tx_compl_q);
        skb_queue_head_init(&htt->rx_compl_q);
        skb_queue_head_init(&htt->rx_in_ord_compl_q);
+       skb_queue_head_init(&htt->tx_fetch_ind_q);
+       atomic_set(&htt->num_mpdus_ready, 0);
 
        tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task,
                     (unsigned long)htt);
@@ -860,6 +810,8 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
                ch = ath10k_htt_rx_h_vdev_channel(ar, vdev_id);
        if (!ch)
                ch = ath10k_htt_rx_h_any_channel(ar);
+       if (!ch)
+               ch = ar->tgt_oper_chan;
        spin_unlock_bh(&ar->data_lock);
 
        if (!ch)
@@ -1076,20 +1028,25 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
        hdr = (void *)msdu->data;
 
        /* Tail */
-       skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype));
+       if (status->flag & RX_FLAG_IV_STRIPPED)
+               skb_trim(msdu, msdu->len -
+                        ath10k_htt_rx_crypto_tail_len(ar, enctype));
 
        /* MMIC */
-       if (!ieee80211_has_morefrags(hdr->frame_control) &&
+       if ((status->flag & RX_FLAG_MMIC_STRIPPED) &&
+           !ieee80211_has_morefrags(hdr->frame_control) &&
            enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
                skb_trim(msdu, msdu->len - 8);
 
        /* Head */
-       hdr_len = ieee80211_hdrlen(hdr->frame_control);
-       crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
+       if (status->flag & RX_FLAG_IV_STRIPPED) {
+               hdr_len = ieee80211_hdrlen(hdr->frame_control);
+               crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
 
-       memmove((void *)msdu->data + crypto_len,
-               (void *)msdu->data, hdr_len);
-       skb_pull(msdu, crypto_len);
+               memmove((void *)msdu->data + crypto_len,
+                       (void *)msdu->data, hdr_len);
+               skb_pull(msdu, crypto_len);
+       }
 }
 
 static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
@@ -1343,6 +1300,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        bool has_tkip_err;
        bool has_peer_idx_invalid;
        bool is_decrypted;
+       bool is_mgmt;
        u32 attention;
 
        if (skb_queue_empty(amsdu))
@@ -1351,6 +1309,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        first = skb_peek(amsdu);
        rxd = (void *)first->data - sizeof(*rxd);
 
+       is_mgmt = !!(rxd->attention.flags &
+                    __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
+
        enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
                     RX_MPDU_START_INFO0_ENCRYPT_TYPE);
 
@@ -1392,6 +1353,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                          RX_FLAG_MMIC_ERROR |
                          RX_FLAG_DECRYPTED |
                          RX_FLAG_IV_STRIPPED |
+                         RX_FLAG_ONLY_MONITOR |
                          RX_FLAG_MMIC_STRIPPED);
 
        if (has_fcs_err)
@@ -1400,10 +1362,21 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        if (has_tkip_err)
                status->flag |= RX_FLAG_MMIC_ERROR;
 
-       if (is_decrypted)
-               status->flag |= RX_FLAG_DECRYPTED |
-                               RX_FLAG_IV_STRIPPED |
-                               RX_FLAG_MMIC_STRIPPED;
+       /* Firmware reports all necessary management frames via WMI already.
+        * They are not reported to monitor interfaces at all so pass the ones
+        * coming via HTT to monitor interfaces instead. This simplifies
+        * matters a lot.
+        */
+       if (is_mgmt)
+               status->flag |= RX_FLAG_ONLY_MONITOR;
+
+       if (is_decrypted) {
+               status->flag |= RX_FLAG_DECRYPTED;
+
+               if (likely(!is_mgmt))
+                       status->flag |= RX_FLAG_IV_STRIPPED |
+                                       RX_FLAG_MMIC_STRIPPED;
+}
 
        skb_queue_walk(amsdu, msdu) {
                ath10k_htt_rx_h_csum_offload(msdu);
@@ -1416,6 +1389,8 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                 */
                if (!is_decrypted)
                        continue;
+               if (is_mgmt)
+                       continue;
 
                hdr = (void *)msdu->data;
                hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
@@ -1516,14 +1491,6 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
                                        struct sk_buff_head *amsdu,
                                        struct ieee80211_rx_status *rx_status)
 {
-       struct sk_buff *msdu;
-       struct htt_rx_desc *rxd;
-       bool is_mgmt;
-       bool has_fcs_err;
-
-       msdu = skb_peek(amsdu);
-       rxd = (void *)msdu->data - sizeof(*rxd);
-
        /* FIXME: It might be a good idea to do some fuzzy-testing to drop
         * invalid/dangerous frames.
         */
@@ -1533,23 +1500,6 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
                return false;
        }
 
-       is_mgmt = !!(rxd->attention.flags &
-                    __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
-       has_fcs_err = !!(rxd->attention.flags &
-                        __cpu_to_le32(RX_ATTENTION_FLAGS_FCS_ERR));
-
-       /* Management frames are handled via WMI events. The pros of such
-        * approach is that channel is explicitly provided in WMI events
-        * whereas HTT doesn't provide channel information for Rxed frames.
-        *
-        * However some firmware revisions don't report corrupted frames via
-        * WMI so don't drop them.
-        */
-       if (is_mgmt && !has_fcs_err) {
-               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
-               return false;
-       }
-
        if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
                ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n");
                return false;
@@ -1571,25 +1521,49 @@ static void ath10k_htt_rx_h_filter(struct ath10k *ar,
        __skb_queue_purge(amsdu);
 }
 
-static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
-                                 struct htt_rx_indication *rx)
+static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
 {
        struct ath10k *ar = htt->ar;
-       struct ieee80211_rx_status *rx_status = &htt->rx_status;
-       struct htt_rx_indication_mpdu_range *mpdu_ranges;
+       static struct ieee80211_rx_status rx_status;
        struct sk_buff_head amsdu;
-       int num_mpdu_ranges;
-       int fw_desc_len;
-       u8 *fw_desc;
-       int i, ret, mpdu_count = 0;
+       int ret;
 
-       lockdep_assert_held(&htt->rx_ring.lock);
+       __skb_queue_head_init(&amsdu);
 
-       if (htt->rx_confused)
-               return;
+       spin_lock_bh(&htt->rx_ring.lock);
+       if (htt->rx_confused) {
+               spin_unlock_bh(&htt->rx_ring.lock);
+               return -EIO;
+       }
+       ret = ath10k_htt_rx_amsdu_pop(htt, &amsdu);
+       spin_unlock_bh(&htt->rx_ring.lock);
 
-       fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes);
-       fw_desc = (u8 *)&rx->fw_desc;
+       if (ret < 0) {
+               ath10k_warn(ar, "rx ring became corrupted: %d\n", ret);
+               __skb_queue_purge(&amsdu);
+               /* FIXME: It's probably a good idea to reboot the
+                * device instead of leaving it inoperable.
+                */
+               htt->rx_confused = true;
+               return ret;
+       }
+
+       ath10k_htt_rx_h_ppdu(ar, &amsdu, &rx_status, 0xffff);
+       ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
+       ath10k_htt_rx_h_filter(ar, &amsdu, &rx_status);
+       ath10k_htt_rx_h_mpdu(ar, &amsdu, &rx_status);
+       ath10k_htt_rx_h_deliver(ar, &amsdu, &rx_status);
+
+       return 0;
+}
+
+static void ath10k_htt_rx_proc_rx_ind(struct ath10k_htt *htt,
+                                     struct htt_rx_indication *rx)
+{
+       struct ath10k *ar = htt->ar;
+       struct htt_rx_indication_mpdu_range *mpdu_ranges;
+       int num_mpdu_ranges;
+       int i, mpdu_count = 0;
 
        num_mpdu_ranges = MS(__le32_to_cpu(rx->hdr.info1),
                             HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
@@ -1603,80 +1577,19 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
        for (i = 0; i < num_mpdu_ranges; i++)
                mpdu_count += mpdu_ranges[i].mpdu_count;
 
-       while (mpdu_count--) {
-               __skb_queue_head_init(&amsdu);
-               ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc,
-                                             &fw_desc_len, &amsdu);
-               if (ret < 0) {
-                       ath10k_warn(ar, "rx ring became corrupted: %d\n", ret);
-                       __skb_queue_purge(&amsdu);
-                       /* FIXME: It's probably a good idea to reboot the
-                        * device instead of leaving it inoperable.
-                        */
-                       htt->rx_confused = true;
-                       break;
-               }
+       atomic_add(mpdu_count, &htt->num_mpdus_ready);
 
-               ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
-               ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
-               ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-               ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
-               ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
-       }
-
-       tasklet_schedule(&htt->rx_replenish_task);
+       tasklet_schedule(&htt->txrx_compl_task);
 }
 
-static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
-                                      struct htt_rx_fragment_indication *frag)
+static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt)
 {
-       struct ath10k *ar = htt->ar;
-       struct ieee80211_rx_status *rx_status = &htt->rx_status;
-       struct sk_buff_head amsdu;
-       int ret;
-       u8 *fw_desc;
-       int fw_desc_len;
-
-       fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
-       fw_desc = (u8 *)frag->fw_msdu_rx_desc;
-
-       __skb_queue_head_init(&amsdu);
+       atomic_inc(&htt->num_mpdus_ready);
 
-       spin_lock_bh(&htt->rx_ring.lock);
-       ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
-                                     &amsdu);
-       spin_unlock_bh(&htt->rx_ring.lock);
-
-       tasklet_schedule(&htt->rx_replenish_task);
-
-       ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
-
-       if (ret) {
-               ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
-                           ret);
-               __skb_queue_purge(&amsdu);
-               return;
-       }
-
-       if (skb_queue_len(&amsdu) != 1) {
-               ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n");
-               __skb_queue_purge(&amsdu);
-               return;
-       }
-
-       ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status, 0xffff);
-       ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-       ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
-       ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
-
-       if (fw_desc_len > 0) {
-               ath10k_dbg(ar, ATH10K_DBG_HTT,
-                          "expecting more fragmented rx in one indication %d\n",
-                          fw_desc_len);
-       }
+       tasklet_schedule(&htt->txrx_compl_task);
 }
 
-static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
+static void ath10k_htt_rx_tx_compl_ind(struct ath10k *ar,
                                       struct sk_buff *skb)
 {
        struct ath10k_htt *htt = &ar->htt;
@@ -1688,19 +1601,19 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
 
        switch (status) {
        case HTT_DATA_TX_STATUS_NO_ACK:
-               tx_done.no_ack = true;
+               tx_done.status = HTT_TX_COMPL_STATE_NOACK;
                break;
        case HTT_DATA_TX_STATUS_OK:
-               tx_done.success = true;
+               tx_done.status = HTT_TX_COMPL_STATE_ACK;
                break;
        case HTT_DATA_TX_STATUS_DISCARD:
        case HTT_DATA_TX_STATUS_POSTPONE:
        case HTT_DATA_TX_STATUS_DOWNLOAD_FAIL:
-               tx_done.discard = true;
+               tx_done.status = HTT_TX_COMPL_STATE_DISCARD;
                break;
        default:
                ath10k_warn(ar, "unhandled tx completion status %d\n", status);
-               tx_done.discard = true;
+               tx_done.status = HTT_TX_COMPL_STATE_DISCARD;
                break;
        }
 
@@ -1710,7 +1623,20 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
        for (i = 0; i < resp->data_tx_completion.num_msdus; i++) {
                msdu_id = resp->data_tx_completion.msdus[i];
                tx_done.msdu_id = __le16_to_cpu(msdu_id);
-               ath10k_txrx_tx_unref(htt, &tx_done);
+
+               /* kfifo_put: In practice firmware shouldn't fire off per-CE
+                * interrupt and main interrupt (MSI/-X range case) for the same
+                * HTC service so it should be safe to use kfifo_put w/o lock.
+                *
+                * From kfifo_put() documentation:
+                *  Note that with only one concurrent reader and one concurrent
+                *  writer, you don't need extra locking to use these macro.
+                */
+               if (!kfifo_put(&htt->txdone_fifo, tx_done)) {
+                       ath10k_warn(ar, "txdone fifo overrun, msdu_id %d status %d\n",
+                                   tx_done.msdu_id, tx_done.status);
+                       ath10k_txrx_tx_unref(htt, &tx_done);
+               }
        }
 }
 
@@ -1978,11 +1904,324 @@ static void ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
                        return;
                }
        }
+       ath10k_htt_rx_msdu_buff_replenish(htt);
+}
+
+static void ath10k_htt_rx_tx_fetch_resp_id_confirm(struct ath10k *ar,
+                                                  const __le32 *resp_ids,
+                                                  int num_resp_ids)
+{
+       int i;
+       u32 resp_id;
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch confirm num_resp_ids %d\n",
+                  num_resp_ids);
+
+       for (i = 0; i < num_resp_ids; i++) {
+               resp_id = le32_to_cpu(resp_ids[i]);
+
+               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch confirm resp_id %u\n",
+                          resp_id);
+
+               /* TODO: free resp_id */
+       }
+}
+
+static void ath10k_htt_rx_tx_fetch_ind(struct ath10k *ar, struct sk_buff *skb)
+{
+       struct ieee80211_hw *hw = ar->hw;
+       struct ieee80211_txq *txq;
+       struct htt_resp *resp = (struct htt_resp *)skb->data;
+       struct htt_tx_fetch_record *record;
+       size_t len;
+       size_t max_num_bytes;
+       size_t max_num_msdus;
+       size_t num_bytes;
+       size_t num_msdus;
+       const __le32 *resp_ids;
+       u16 num_records;
+       u16 num_resp_ids;
+       u16 peer_id;
+       u8 tid;
+       int ret;
+       int i;
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind\n");
+
+       len = sizeof(resp->hdr) + sizeof(resp->tx_fetch_ind);
+       if (unlikely(skb->len < len)) {
+               ath10k_warn(ar, "received corrupted tx_fetch_ind event: buffer too short\n");
+               return;
+       }
+
+       num_records = le16_to_cpu(resp->tx_fetch_ind.num_records);
+       num_resp_ids = le16_to_cpu(resp->tx_fetch_ind.num_resp_ids);
+
+       len += sizeof(resp->tx_fetch_ind.records[0]) * num_records;
+       len += sizeof(resp->tx_fetch_ind.resp_ids[0]) * num_resp_ids;
+
+       if (unlikely(skb->len < len)) {
+               ath10k_warn(ar, "received corrupted tx_fetch_ind event: too many records/resp_ids\n");
+               return;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch ind num records %hu num resps %hu seq %hu\n",
+                  num_records, num_resp_ids,
+                  le16_to_cpu(resp->tx_fetch_ind.fetch_seq_num));
+
+       if (!ar->htt.tx_q_state.enabled) {
+               ath10k_warn(ar, "received unexpected tx_fetch_ind event: not enabled\n");
+               return;
+       }
+
+       if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH) {
+               ath10k_warn(ar, "received unexpected tx_fetch_ind event: in push mode\n");
+               return;
+       }
+
+       rcu_read_lock();
+
+       for (i = 0; i < num_records; i++) {
+               record = &resp->tx_fetch_ind.records[i];
+               peer_id = MS(le16_to_cpu(record->info),
+                            HTT_TX_FETCH_RECORD_INFO_PEER_ID);
+               tid = MS(le16_to_cpu(record->info),
+                        HTT_TX_FETCH_RECORD_INFO_TID);
+               max_num_msdus = le16_to_cpu(record->num_msdus);
+               max_num_bytes = le32_to_cpu(record->num_bytes);
+
+               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch record %i peer_id %hu tid %hhu msdus %zu bytes %zu\n",
+                          i, peer_id, tid, max_num_msdus, max_num_bytes);
+
+               if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) ||
+                   unlikely(tid >= ar->htt.tx_q_state.num_tids)) {
+                       ath10k_warn(ar, "received out of range peer_id %hu tid %hhu\n",
+                                   peer_id, tid);
+                       continue;
+               }
+
+               spin_lock_bh(&ar->data_lock);
+               txq = ath10k_mac_txq_lookup(ar, peer_id, tid);
+               spin_unlock_bh(&ar->data_lock);
+
+               /* It is okay to release the lock and use txq because RCU read
+                * lock is held.
+                */
+
+               if (unlikely(!txq)) {
+                       ath10k_warn(ar, "failed to lookup txq for peer_id %hu tid %hhu\n",
+                                   peer_id, tid);
+                       continue;
+               }
+
+               num_msdus = 0;
+               num_bytes = 0;
+
+               while (num_msdus < max_num_msdus &&
+                      num_bytes < max_num_bytes) {
+                       ret = ath10k_mac_tx_push_txq(hw, txq);
+                       if (ret < 0)
+                               break;
+
+                       num_msdus++;
+                       num_bytes += ret;
+               }
+
+               record->num_msdus = cpu_to_le16(num_msdus);
+               record->num_bytes = cpu_to_le32(num_bytes);
+
+               ath10k_htt_tx_txq_recalc(hw, txq);
+       }
+
+       rcu_read_unlock();
+
+       resp_ids = ath10k_htt_get_tx_fetch_ind_resp_ids(&resp->tx_fetch_ind);
+       ath10k_htt_rx_tx_fetch_resp_id_confirm(ar, resp_ids, num_resp_ids);
+
+       ret = ath10k_htt_tx_fetch_resp(ar,
+                                      resp->tx_fetch_ind.token,
+                                      resp->tx_fetch_ind.fetch_seq_num,
+                                      resp->tx_fetch_ind.records,
+                                      num_records);
+       if (unlikely(ret)) {
+               ath10k_warn(ar, "failed to submit tx fetch resp for token 0x%08x: %d\n",
+                           le32_to_cpu(resp->tx_fetch_ind.token), ret);
+               /* FIXME: request fw restart */
+       }
 
-       tasklet_schedule(&htt->rx_replenish_task);
+       ath10k_htt_tx_txq_sync(ar);
 }
 
-void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
+static void ath10k_htt_rx_tx_fetch_confirm(struct ath10k *ar,
+                                          struct sk_buff *skb)
+{
+       const struct htt_resp *resp = (void *)skb->data;
+       size_t len;
+       int num_resp_ids;
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx fetch confirm\n");
+
+       len = sizeof(resp->hdr) + sizeof(resp->tx_fetch_confirm);
+       if (unlikely(skb->len < len)) {
+               ath10k_warn(ar, "received corrupted tx_fetch_confirm event: buffer too short\n");
+               return;
+       }
+
+       num_resp_ids = le16_to_cpu(resp->tx_fetch_confirm.num_resp_ids);
+       len += sizeof(resp->tx_fetch_confirm.resp_ids[0]) * num_resp_ids;
+
+       if (unlikely(skb->len < len)) {
+               ath10k_warn(ar, "received corrupted tx_fetch_confirm event: resp_ids buffer overflow\n");
+               return;
+       }
+
+       ath10k_htt_rx_tx_fetch_resp_id_confirm(ar,
+                                              resp->tx_fetch_confirm.resp_ids,
+                                              num_resp_ids);
+}
+
+static void ath10k_htt_rx_tx_mode_switch_ind(struct ath10k *ar,
+                                            struct sk_buff *skb)
+{
+       const struct htt_resp *resp = (void *)skb->data;
+       const struct htt_tx_mode_switch_record *record;
+       struct ieee80211_txq *txq;
+       struct ath10k_txq *artxq;
+       size_t len;
+       size_t num_records;
+       enum htt_tx_mode_switch_mode mode;
+       bool enable;
+       u16 info0;
+       u16 info1;
+       u16 threshold;
+       u16 peer_id;
+       u8 tid;
+       int i;
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx tx mode switch ind\n");
+
+       len = sizeof(resp->hdr) + sizeof(resp->tx_mode_switch_ind);
+       if (unlikely(skb->len < len)) {
+               ath10k_warn(ar, "received corrupted tx_mode_switch_ind event: buffer too short\n");
+               return;
+       }
+
+       info0 = le16_to_cpu(resp->tx_mode_switch_ind.info0);
+       info1 = le16_to_cpu(resp->tx_mode_switch_ind.info1);
+
+       enable = !!(info0 & HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE);
+       num_records = MS(info0, HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD);
+       mode = MS(info1, HTT_TX_MODE_SWITCH_IND_INFO1_MODE);
+       threshold = MS(info1, HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD);
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT,
+                  "htt rx tx mode switch ind info0 0x%04hx info1 0x%04hx enable %d num records %zd mode %d threshold %hu\n",
+                  info0, info1, enable, num_records, mode, threshold);
+
+       len += sizeof(resp->tx_mode_switch_ind.records[0]) * num_records;
+
+       if (unlikely(skb->len < len)) {
+               ath10k_warn(ar, "received corrupted tx_mode_switch_mode_ind event: too many records\n");
+               return;
+       }
+
+       switch (mode) {
+       case HTT_TX_MODE_SWITCH_PUSH:
+       case HTT_TX_MODE_SWITCH_PUSH_PULL:
+               break;
+       default:
+               ath10k_warn(ar, "received invalid tx_mode_switch_mode_ind mode %d, ignoring\n",
+                           mode);
+               return;
+       }
+
+       if (!enable)
+               return;
+
+       ar->htt.tx_q_state.enabled = enable;
+       ar->htt.tx_q_state.mode = mode;
+       ar->htt.tx_q_state.num_push_allowed = threshold;
+
+       rcu_read_lock();
+
+       for (i = 0; i < num_records; i++) {
+               record = &resp->tx_mode_switch_ind.records[i];
+               info0 = le16_to_cpu(record->info0);
+               peer_id = MS(info0, HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID);
+               tid = MS(info0, HTT_TX_MODE_SWITCH_RECORD_INFO0_TID);
+
+               if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) ||
+                   unlikely(tid >= ar->htt.tx_q_state.num_tids)) {
+                       ath10k_warn(ar, "received out of range peer_id %hu tid %hhu\n",
+                                   peer_id, tid);
+                       continue;
+               }
+
+               spin_lock_bh(&ar->data_lock);
+               txq = ath10k_mac_txq_lookup(ar, peer_id, tid);
+               spin_unlock_bh(&ar->data_lock);
+
+               /* It is okay to release the lock and use txq because RCU read
+                * lock is held.
+                */
+
+               if (unlikely(!txq)) {
+                       ath10k_warn(ar, "failed to lookup txq for peer_id %hu tid %hhu\n",
+                                   peer_id, tid);
+                       continue;
+               }
+
+               spin_lock_bh(&ar->htt.tx_lock);
+               artxq = (void *)txq->drv_priv;
+               artxq->num_push_allowed = le16_to_cpu(record->num_max_msdus);
+               spin_unlock_bh(&ar->htt.tx_lock);
+       }
+
+       rcu_read_unlock();
+
+       ath10k_mac_tx_push_pending(ar);
+}
+
+static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode)
+{
+       enum ieee80211_band band;
+
+       switch (phy_mode) {
+       case MODE_11A:
+       case MODE_11NA_HT20:
+       case MODE_11NA_HT40:
+       case MODE_11AC_VHT20:
+       case MODE_11AC_VHT40:
+       case MODE_11AC_VHT80:
+               band = IEEE80211_BAND_5GHZ;
+               break;
+       case MODE_11G:
+       case MODE_11B:
+       case MODE_11GONLY:
+       case MODE_11NG_HT20:
+       case MODE_11NG_HT40:
+       case MODE_11AC_VHT20_2G:
+       case MODE_11AC_VHT40_2G:
+       case MODE_11AC_VHT80_2G:
+       default:
+               band = IEEE80211_BAND_2GHZ;
+       }
+
+       return band;
+}
+
+void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
+{
+       bool release;
+
+       release = ath10k_htt_t2h_msg_handler(ar, skb);
+
+       /* Free the indication buffer */
+       if (release)
+               dev_kfree_skb_any(skb);
+}
+
+bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ath10k_htt *htt = &ar->htt;
        struct htt_resp *resp = (struct htt_resp *)skb->data;
@@ -1998,8 +2237,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
        if (resp->hdr.msg_type >= ar->htt.t2h_msg_types_max) {
                ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx, unsupported msg_type: 0x%0X\n max: 0x%0X",
                           resp->hdr.msg_type, ar->htt.t2h_msg_types_max);
-               dev_kfree_skb_any(skb);
-               return;
+               return true;
        }
        type = ar->htt.t2h_msg_types[resp->hdr.msg_type];
 
@@ -2011,9 +2249,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                break;
        }
        case HTT_T2H_MSG_TYPE_RX_IND:
-               skb_queue_tail(&htt->rx_compl_q, skb);
-               tasklet_schedule(&htt->txrx_compl_task);
-               return;
+               ath10k_htt_rx_proc_rx_ind(htt, &resp->rx_ind);
+               break;
        case HTT_T2H_MSG_TYPE_PEER_MAP: {
                struct htt_peer_map_event ev = {
                        .vdev_id = resp->peer_map.vdev_id,
@@ -2034,28 +2271,33 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                struct htt_tx_done tx_done = {};
                int status = __le32_to_cpu(resp->mgmt_tx_completion.status);
 
-               tx_done.msdu_id =
-                       __le32_to_cpu(resp->mgmt_tx_completion.desc_id);
+               tx_done.msdu_id = __le32_to_cpu(resp->mgmt_tx_completion.desc_id);
 
                switch (status) {
                case HTT_MGMT_TX_STATUS_OK:
-                       tx_done.success = true;
+                       tx_done.status = HTT_TX_COMPL_STATE_ACK;
                        break;
                case HTT_MGMT_TX_STATUS_RETRY:
-                       tx_done.no_ack = true;
+                       tx_done.status = HTT_TX_COMPL_STATE_NOACK;
                        break;
                case HTT_MGMT_TX_STATUS_DROP:
-                       tx_done.discard = true;
+                       tx_done.status = HTT_TX_COMPL_STATE_DISCARD;
                        break;
                }
 
-               ath10k_txrx_tx_unref(htt, &tx_done);
+               status = ath10k_txrx_tx_unref(htt, &tx_done);
+               if (!status) {
+                       spin_lock_bh(&htt->tx_lock);
+                       ath10k_htt_tx_mgmt_dec_pending(htt);
+                       spin_unlock_bh(&htt->tx_lock);
+               }
+               ath10k_mac_tx_push_pending(ar);
                break;
        }
        case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
-               skb_queue_tail(&htt->tx_compl_q, skb);
+               ath10k_htt_rx_tx_compl_ind(htt->ar, skb);
                tasklet_schedule(&htt->txrx_compl_task);
-               return;
+               break;
        case HTT_T2H_MSG_TYPE_SEC_IND: {
                struct ath10k *ar = htt->ar;
                struct htt_security_indication *ev = &resp->security_indication;
@@ -2071,7 +2313,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
        case HTT_T2H_MSG_TYPE_RX_FRAG_IND: {
                ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
                                skb->data, skb->len);
-               ath10k_htt_rx_frag_handler(htt, &resp->rx_frag_ind);
+               ath10k_htt_rx_frag_handler(htt);
                break;
        }
        case HTT_T2H_MSG_TYPE_TEST:
@@ -2111,18 +2353,39 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
        case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
                skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
                tasklet_schedule(&htt->txrx_compl_task);
-               return;
+               return false;
        }
        case HTT_T2H_MSG_TYPE_TX_CREDIT_UPDATE_IND:
                break;
-       case HTT_T2H_MSG_TYPE_CHAN_CHANGE:
+       case HTT_T2H_MSG_TYPE_CHAN_CHANGE: {
+               u32 phymode = __le32_to_cpu(resp->chan_change.phymode);
+               u32 freq = __le32_to_cpu(resp->chan_change.freq);
+
+               ar->tgt_oper_chan =
+                       __ieee80211_get_channel(ar->hw->wiphy, freq);
+               ath10k_dbg(ar, ATH10K_DBG_HTT,
+                          "htt chan change freq %u phymode %s\n",
+                          freq, ath10k_wmi_phymode_str(phymode));
                break;
+       }
        case HTT_T2H_MSG_TYPE_AGGR_CONF:
                break;
-       case HTT_T2H_MSG_TYPE_TX_FETCH_IND:
+       case HTT_T2H_MSG_TYPE_TX_FETCH_IND: {
+               struct sk_buff *tx_fetch_ind = skb_copy(skb, GFP_ATOMIC);
+
+               if (!tx_fetch_ind) {
+                       ath10k_warn(ar, "failed to copy htt tx fetch ind\n");
+                       break;
+               }
+               skb_queue_tail(&htt->tx_fetch_ind_q, tx_fetch_ind);
+               tasklet_schedule(&htt->txrx_compl_task);
+               break;
+       }
        case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM:
+               ath10k_htt_rx_tx_fetch_confirm(ar, skb);
+               break;
        case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND:
-               /* TODO: Implement pull-push logic */
+               ath10k_htt_rx_tx_mode_switch_ind(ar, skb);
                break;
        case HTT_T2H_MSG_TYPE_EN_STATS:
        default:
@@ -2132,9 +2395,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
                                skb->data, skb->len);
                break;
        };
-
-       /* Free the indication buffer */
-       dev_kfree_skb_any(skb);
+       return true;
 }
 EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
 
@@ -2150,40 +2411,47 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
 {
        struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
        struct ath10k *ar = htt->ar;
-       struct sk_buff_head tx_q;
-       struct sk_buff_head rx_q;
+       struct htt_tx_done tx_done = {};
        struct sk_buff_head rx_ind_q;
-       struct htt_resp *resp;
+       struct sk_buff_head tx_ind_q;
        struct sk_buff *skb;
        unsigned long flags;
+       int num_mpdus;
 
-       __skb_queue_head_init(&tx_q);
-       __skb_queue_head_init(&rx_q);
        __skb_queue_head_init(&rx_ind_q);
-
-       spin_lock_irqsave(&htt->tx_compl_q.lock, flags);
-       skb_queue_splice_init(&htt->tx_compl_q, &tx_q);
-       spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags);
-
-       spin_lock_irqsave(&htt->rx_compl_q.lock, flags);
-       skb_queue_splice_init(&htt->rx_compl_q, &rx_q);
-       spin_unlock_irqrestore(&htt->rx_compl_q.lock, flags);
+       __skb_queue_head_init(&tx_ind_q);
 
        spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags);
        skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q);
        spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags);
 
-       while ((skb = __skb_dequeue(&tx_q))) {
-               ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
+       spin_lock_irqsave(&htt->tx_fetch_ind_q.lock, flags);
+       skb_queue_splice_init(&htt->tx_fetch_ind_q, &tx_ind_q);
+       spin_unlock_irqrestore(&htt->tx_fetch_ind_q.lock, flags);
+
+       /* kfifo_get: called only within txrx_tasklet so it's neatly serialized.
+        * From kfifo_get() documentation:
+        *  Note that with only one concurrent reader and one concurrent writer,
+        *  you don't need extra locking to use these macro.
+        */
+       while (kfifo_get(&htt->txdone_fifo, &tx_done))
+               ath10k_txrx_tx_unref(htt, &tx_done);
+
+       while ((skb = __skb_dequeue(&tx_ind_q))) {
+               ath10k_htt_rx_tx_fetch_ind(ar, skb);
                dev_kfree_skb_any(skb);
        }
 
-       while ((skb = __skb_dequeue(&rx_q))) {
-               resp = (struct htt_resp *)skb->data;
-               spin_lock_bh(&htt->rx_ring.lock);
-               ath10k_htt_rx_handler(htt, &resp->rx_ind);
-               spin_unlock_bh(&htt->rx_ring.lock);
-               dev_kfree_skb_any(skb);
+       ath10k_mac_tx_push_pending(ar);
+
+       num_mpdus = atomic_read(&htt->num_mpdus_ready);
+
+       while (num_mpdus) {
+               if (ath10k_htt_rx_handle_amsdu(htt))
+                       break;
+
+               num_mpdus--;
+               atomic_dec(&htt->num_mpdus_ready);
        }
 
        while ((skb = __skb_dequeue(&rx_ind_q))) {
@@ -2192,4 +2460,6 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
                spin_unlock_bh(&htt->rx_ring.lock);
                dev_kfree_skb_any(skb);
        }
+
+       ath10k_htt_rx_msdu_buff_replenish(htt);
 }
index 95acb727c068f242f1324a39f04c540291071126..9baa2e677f8adcfb4263878fca58d7e85313f1c6 100644 (file)
 #include "txrx.h"
 #include "debug.h"
 
-void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc)
+static u8 ath10k_htt_tx_txq_calc_size(size_t count)
 {
-       if (limit_mgmt_desc)
-               htt->num_pending_mgmt_tx--;
+       int exp;
+       int factor;
+
+       exp = 0;
+       factor = count >> 7;
+
+       while (factor >= 64 && exp < 4) {
+               factor >>= 3;
+               exp++;
+       }
+
+       if (exp == 4)
+               return 0xff;
+
+       if (count > 0)
+               factor = max(1, factor);
+
+       return SM(exp, HTT_TX_Q_STATE_ENTRY_EXP) |
+              SM(factor, HTT_TX_Q_STATE_ENTRY_FACTOR);
+}
+
+static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
+                                      struct ieee80211_txq *txq)
+{
+       struct ath10k *ar = hw->priv;
+       struct ath10k_sta *arsta = (void *)txq->sta->drv_priv;
+       struct ath10k_vif *arvif = (void *)txq->vif->drv_priv;
+       unsigned long frame_cnt;
+       unsigned long byte_cnt;
+       int idx;
+       u32 bit;
+       u16 peer_id;
+       u8 tid;
+       u8 count;
+
+       lockdep_assert_held(&ar->htt.tx_lock);
+
+       if (!ar->htt.tx_q_state.enabled)
+               return;
+
+       if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
+               return;
+
+       if (txq->sta)
+               peer_id = arsta->peer_id;
+       else
+               peer_id = arvif->peer_id;
+
+       tid = txq->tid;
+       bit = BIT(peer_id % 32);
+       idx = peer_id / 32;
+
+       ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
+       count = ath10k_htt_tx_txq_calc_size(byte_cnt);
+
+       if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) ||
+           unlikely(tid >= ar->htt.tx_q_state.num_tids)) {
+               ath10k_warn(ar, "refusing to update txq for peer_id %hu tid %hhu due to out of bounds\n",
+                           peer_id, tid);
+               return;
+       }
+
+       ar->htt.tx_q_state.vaddr->count[tid][peer_id] = count;
+       ar->htt.tx_q_state.vaddr->map[tid][idx] &= ~bit;
+       ar->htt.tx_q_state.vaddr->map[tid][idx] |= count ? bit : 0;
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update peer_id %hu tid %hhu count %hhu\n",
+                  peer_id, tid, count);
+}
+
+static void __ath10k_htt_tx_txq_sync(struct ath10k *ar)
+{
+       u32 seq;
+       size_t size;
+
+       lockdep_assert_held(&ar->htt.tx_lock);
+
+       if (!ar->htt.tx_q_state.enabled)
+               return;
+
+       if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
+               return;
+
+       seq = le32_to_cpu(ar->htt.tx_q_state.vaddr->seq);
+       seq++;
+       ar->htt.tx_q_state.vaddr->seq = cpu_to_le32(seq);
+
+       ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update commit seq %u\n",
+                  seq);
+
+       size = sizeof(*ar->htt.tx_q_state.vaddr);
+       dma_sync_single_for_device(ar->dev,
+                                  ar->htt.tx_q_state.paddr,
+                                  size,
+                                  DMA_TO_DEVICE);
+}
+
+void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
+                             struct ieee80211_txq *txq)
+{
+       struct ath10k *ar = hw->priv;
+
+       spin_lock_bh(&ar->htt.tx_lock);
+       __ath10k_htt_tx_txq_recalc(hw, txq);
+       spin_unlock_bh(&ar->htt.tx_lock);
+}
+
+void ath10k_htt_tx_txq_sync(struct ath10k *ar)
+{
+       spin_lock_bh(&ar->htt.tx_lock);
+       __ath10k_htt_tx_txq_sync(ar);
+       spin_unlock_bh(&ar->htt.tx_lock);
+}
+
+void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
+                             struct ieee80211_txq *txq)
+{
+       struct ath10k *ar = hw->priv;
+
+       spin_lock_bh(&ar->htt.tx_lock);
+       __ath10k_htt_tx_txq_recalc(hw, txq);
+       __ath10k_htt_tx_txq_sync(ar);
+       spin_unlock_bh(&ar->htt.tx_lock);
+}
+
+void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
+{
+       lockdep_assert_held(&htt->tx_lock);
 
        htt->num_pending_tx--;
        if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
                ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
 }
 
-static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt,
-                                     bool limit_mgmt_desc)
+int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
 {
-       spin_lock_bh(&htt->tx_lock);
-       __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
-       spin_unlock_bh(&htt->tx_lock);
+       lockdep_assert_held(&htt->tx_lock);
+
+       if (htt->num_pending_tx >= htt->max_num_pending_tx)
+               return -EBUSY;
+
+       htt->num_pending_tx++;
+       if (htt->num_pending_tx == htt->max_num_pending_tx)
+               ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
+
+       return 0;
 }
 
-static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt,
-                                    bool limit_mgmt_desc, bool is_probe_resp)
+int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
+                                  bool is_presp)
 {
        struct ath10k *ar = htt->ar;
-       int ret = 0;
 
-       spin_lock_bh(&htt->tx_lock);
+       lockdep_assert_held(&htt->tx_lock);
 
-       if (htt->num_pending_tx >= htt->max_num_pending_tx) {
-               ret = -EBUSY;
-               goto exit;
-       }
+       if (!is_mgmt || !ar->hw_params.max_probe_resp_desc_thres)
+               return 0;
 
-       if (limit_mgmt_desc) {
-               if (is_probe_resp && (htt->num_pending_mgmt_tx >
-                   ar->hw_params.max_probe_resp_desc_thres)) {
-                       ret = -EBUSY;
-                       goto exit;
-               }
-               htt->num_pending_mgmt_tx++;
-       }
+       if (is_presp &&
+           ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx)
+               return -EBUSY;
 
-       htt->num_pending_tx++;
-       if (htt->num_pending_tx == htt->max_num_pending_tx)
-               ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
+       htt->num_pending_mgmt_tx++;
 
-exit:
-       spin_unlock_bh(&htt->tx_lock);
-       return ret;
+       return 0;
+}
+
+void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt)
+{
+       lockdep_assert_held(&htt->tx_lock);
+
+       if (!htt->ar->hw_params.max_probe_resp_desc_thres)
+               return;
+
+       htt->num_pending_mgmt_tx--;
 }
 
 int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
@@ -209,8 +339,18 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
                goto free_frag_desc;
        }
 
+       size = roundup_pow_of_two(htt->max_num_pending_tx);
+       ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL);
+       if (ret) {
+               ath10k_err(ar, "failed to alloc txdone fifo: %d\n", ret);
+               goto free_txq;
+       }
+
        return 0;
 
+free_txq:
+       ath10k_htt_tx_free_txq(htt);
+
 free_frag_desc:
        ath10k_htt_tx_free_cont_frag_desc(htt);
 
@@ -234,8 +374,8 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
 
        ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id);
 
-       tx_done.discard = 1;
        tx_done.msdu_id = msdu_id;
+       tx_done.status = HTT_TX_COMPL_STATE_DISCARD;
 
        ath10k_txrx_tx_unref(htt, &tx_done);
 
@@ -258,6 +398,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
 
        ath10k_htt_tx_free_txq(htt);
        ath10k_htt_tx_free_cont_frag_desc(htt);
+       WARN_ON(!kfifo_is_empty(&htt->txdone_fifo));
+       kfifo_free(&htt->txdone_fifo);
 }
 
 void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
@@ -535,6 +677,55 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
        return 0;
 }
 
+int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
+                            __le32 token,
+                            __le16 fetch_seq_num,
+                            struct htt_tx_fetch_record *records,
+                            size_t num_records)
+{
+       struct sk_buff *skb;
+       struct htt_cmd *cmd;
+       const u16 resp_id = 0;
+       int len = 0;
+       int ret;
+
+       /* Response IDs are echo-ed back only for host driver convienence
+        * purposes. They aren't used for anything in the driver yet so use 0.
+        */
+
+       len += sizeof(cmd->hdr);
+       len += sizeof(cmd->tx_fetch_resp);
+       len += sizeof(cmd->tx_fetch_resp.records[0]) * num_records;
+
+       skb = ath10k_htc_alloc_skb(ar, len);
+       if (!skb)
+               return -ENOMEM;
+
+       skb_put(skb, len);
+       cmd = (struct htt_cmd *)skb->data;
+       cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FETCH_RESP;
+       cmd->tx_fetch_resp.resp_id = cpu_to_le16(resp_id);
+       cmd->tx_fetch_resp.fetch_seq_num = fetch_seq_num;
+       cmd->tx_fetch_resp.num_records = cpu_to_le16(num_records);
+       cmd->tx_fetch_resp.token = token;
+
+       memcpy(cmd->tx_fetch_resp.records, records,
+              sizeof(records[0]) * num_records);
+
+       ret = ath10k_htc_send(&ar->htc, ar->htt.eid, skb);
+       if (ret) {
+               ath10k_warn(ar, "failed to submit htc command: %d\n", ret);
+               goto err_free_skb;
+       }
+
+       return 0;
+
+err_free_skb:
+       dev_kfree_skb_any(skb);
+
+       return ret;
+}
+
 static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -576,20 +767,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
        int msdu_id = -1;
        int res;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
-       bool limit_mgmt_desc = false;
-       bool is_probe_resp = false;
-
-       if (ar->hw_params.max_probe_resp_desc_thres) {
-               limit_mgmt_desc = true;
-
-               if (ieee80211_is_probe_resp(hdr->frame_control))
-                       is_probe_resp = true;
-       }
-
-       res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
-
-       if (res)
-               goto err;
 
        len += sizeof(cmd->hdr);
        len += sizeof(cmd->mgmt_tx);
@@ -598,7 +775,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
        res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
        spin_unlock_bh(&htt->tx_lock);
        if (res < 0)
-               goto err_tx_dec;
+               goto err;
 
        msdu_id = res;
 
@@ -649,8 +826,6 @@ err_free_msdu_id:
        spin_lock_bh(&htt->tx_lock);
        ath10k_htt_tx_free_msdu_id(htt, msdu_id);
        spin_unlock_bh(&htt->tx_lock);
-err_tx_dec:
-       ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
 err:
        return res;
 }
@@ -677,26 +852,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
        u32 frags_paddr = 0;
        u32 txbuf_paddr;
        struct htt_msdu_ext_desc *ext_desc = NULL;
-       bool limit_mgmt_desc = false;
-       bool is_probe_resp = false;
-
-       if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) &&
-           ar->hw_params.max_probe_resp_desc_thres) {
-               limit_mgmt_desc = true;
-
-               if (ieee80211_is_probe_resp(hdr->frame_control))
-                       is_probe_resp = true;
-       }
-
-       res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
-       if (res)
-               goto err;
 
        spin_lock_bh(&htt->tx_lock);
        res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
        spin_unlock_bh(&htt->tx_lock);
        if (res < 0)
-               goto err_tx_dec;
+               goto err;
 
        msdu_id = res;
 
@@ -862,11 +1023,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
 err_unmap_msdu:
        dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
 err_free_msdu_id:
-       spin_lock_bh(&htt->tx_lock);
        ath10k_htt_tx_free_msdu_id(htt, msdu_id);
-       spin_unlock_bh(&htt->tx_lock);
-err_tx_dec:
-       ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
 err:
        return res;
 }
index f0cfbc745c97dea91d368e5de4ef72bdb00702e2..c0179bc4af29941b6354fe8bbecdd6ecc17d55d9 100644 (file)
@@ -134,8 +134,6 @@ enum qca9377_chip_id_rev {
 
 #define REG_DUMP_COUNT_QCA988X 60
 
-#define QCA988X_CAL_DATA_LEN           2116
-
 struct ath10k_fw_ie {
        __le32 id;
        __le32 len;
@@ -431,10 +429,14 @@ enum ath10k_hw_4addr_pad {
 #define TARGET_10_4_ACTIVE_PEERS               0
 
 #define TARGET_10_4_NUM_QCACHE_PEERS_MAX       512
+#define TARGET_10_4_QCACHE_ACTIVE_PEERS                50
+#define TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC    35
 #define TARGET_10_4_NUM_OFFLOAD_PEERS          0
 #define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS  0
 #define TARGET_10_4_NUM_PEER_KEYS              2
 #define TARGET_10_4_TGT_NUM_TIDS               ((TARGET_10_4_NUM_PEERS) * 2)
+#define TARGET_10_4_NUM_MSDU_DESC              (1024 + 400)
+#define TARGET_10_4_NUM_MSDU_DESC_PFC          2500
 #define TARGET_10_4_AST_SKID_LIMIT             32
 
 /* 100 ms for video, best-effort, and background */
index 78999c9de23b350a7cc871ee446792a2825b77f2..b0e613bc10a5000f8249a388fc0174d5f82b5371 100644 (file)
@@ -618,10 +618,15 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
        *def = &conf->def;
 }
 
-static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr,
+static int ath10k_peer_create(struct ath10k *ar,
+                             struct ieee80211_vif *vif,
+                             struct ieee80211_sta *sta,
+                             u32 vdev_id,
+                             const u8 *addr,
                              enum wmi_peer_type peer_type)
 {
        struct ath10k_vif *arvif;
+       struct ath10k_peer *peer;
        int num_peers = 0;
        int ret;
 
@@ -650,6 +655,22 @@ static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr,
                return ret;
        }
 
+       spin_lock_bh(&ar->data_lock);
+
+       peer = ath10k_peer_find(ar, vdev_id, addr);
+       if (!peer) {
+               ath10k_warn(ar, "failed to find peer %pM on vdev %i after creation\n",
+                           addr, vdev_id);
+               ath10k_wmi_peer_delete(ar, vdev_id, addr);
+               spin_unlock_bh(&ar->data_lock);
+               return -ENOENT;
+       }
+
+       peer->vif = vif;
+       peer->sta = sta;
+
+       spin_unlock_bh(&ar->data_lock);
+
        ar->num_peers++;
 
        return 0;
@@ -731,6 +752,7 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
 static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 {
        struct ath10k_peer *peer, *tmp;
+       int peer_id;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -742,6 +764,11 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
                ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n",
                            peer->addr, vdev_id);
 
+               for_each_set_bit(peer_id, peer->peer_ids,
+                                ATH10K_MAX_NUM_PEER_IDS) {
+                       ar->peer_map[peer_id] = NULL;
+               }
+
                list_del(&peer->list);
                kfree(peer);
                ar->num_peers--;
@@ -2994,6 +3021,13 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
 /* TX handlers */
 /***************/
 
+enum ath10k_mac_tx_path {
+       ATH10K_MAC_TX_HTT,
+       ATH10K_MAC_TX_HTT_MGMT,
+       ATH10K_MAC_TX_WMI_MGMT,
+       ATH10K_MAC_TX_UNKNOWN,
+};
+
 void ath10k_mac_tx_lock(struct ath10k *ar, int reason)
 {
        lockdep_assert_held(&ar->htt.tx_lock);
@@ -3271,6 +3305,28 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
        }
 }
 
+static void ath10k_mac_tx_h_fill_cb(struct ath10k *ar,
+                                   struct ieee80211_vif *vif,
+                                   struct ieee80211_txq *txq,
+                                   struct sk_buff *skb)
+{
+       struct ieee80211_hdr *hdr = (void *)skb->data;
+       struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
+
+       cb->flags = 0;
+       if (!ath10k_tx_h_use_hwcrypto(vif, skb))
+               cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
+
+       if (ieee80211_is_mgmt(hdr->frame_control))
+               cb->flags |= ATH10K_SKB_F_MGMT;
+
+       if (ieee80211_is_data_qos(hdr->frame_control))
+               cb->flags |= ATH10K_SKB_F_QOS;
+
+       cb->vif = vif;
+       cb->txq = txq;
+}
+
 bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
 {
        /* FIXME: Not really sure since when the behaviour changed. At some
@@ -3306,26 +3362,50 @@ unlock:
        return ret;
 }
 
-static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode,
-                         struct sk_buff *skb)
+static enum ath10k_mac_tx_path
+ath10k_mac_tx_h_get_txpath(struct ath10k *ar,
+                          struct sk_buff *skb,
+                          enum ath10k_hw_txrx_mode txmode)
 {
-       struct ath10k_htt *htt = &ar->htt;
-       int ret = 0;
-
        switch (txmode) {
        case ATH10K_HW_TXRX_RAW:
        case ATH10K_HW_TXRX_NATIVE_WIFI:
        case ATH10K_HW_TXRX_ETHERNET:
-               ret = ath10k_htt_tx(htt, txmode, skb);
-               break;
+               return ATH10K_MAC_TX_HTT;
        case ATH10K_HW_TXRX_MGMT:
                if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
                             ar->fw_features))
-                       ret = ath10k_mac_tx_wmi_mgmt(ar, skb);
+                       return ATH10K_MAC_TX_WMI_MGMT;
                else if (ar->htt.target_version_major >= 3)
-                       ret = ath10k_htt_tx(htt, txmode, skb);
+                       return ATH10K_MAC_TX_HTT;
                else
-                       ret = ath10k_htt_mgmt_tx(htt, skb);
+                       return ATH10K_MAC_TX_HTT_MGMT;
+       }
+
+       return ATH10K_MAC_TX_UNKNOWN;
+}
+
+static int ath10k_mac_tx_submit(struct ath10k *ar,
+                               enum ath10k_hw_txrx_mode txmode,
+                               enum ath10k_mac_tx_path txpath,
+                               struct sk_buff *skb)
+{
+       struct ath10k_htt *htt = &ar->htt;
+       int ret = -EINVAL;
+
+       switch (txpath) {
+       case ATH10K_MAC_TX_HTT:
+               ret = ath10k_htt_tx(htt, txmode, skb);
+               break;
+       case ATH10K_MAC_TX_HTT_MGMT:
+               ret = ath10k_htt_mgmt_tx(htt, skb);
+               break;
+       case ATH10K_MAC_TX_WMI_MGMT:
+               ret = ath10k_mac_tx_wmi_mgmt(ar, skb);
+               break;
+       case ATH10K_MAC_TX_UNKNOWN:
+               WARN_ON_ONCE(1);
+               ret = -EINVAL;
                break;
        }
 
@@ -3334,6 +3414,64 @@ static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode,
                            ret);
                ieee80211_free_txskb(ar->hw, skb);
        }
+
+       return ret;
+}
+
+/* This function consumes the sk_buff regardless of return value as far as
+ * caller is concerned so no freeing is necessary afterwards.
+ */
+static int ath10k_mac_tx(struct ath10k *ar,
+                        struct ieee80211_vif *vif,
+                        struct ieee80211_sta *sta,
+                        enum ath10k_hw_txrx_mode txmode,
+                        enum ath10k_mac_tx_path txpath,
+                        struct sk_buff *skb)
+{
+       struct ieee80211_hw *hw = ar->hw;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       int ret;
+
+       /* We should disable CCK RATE due to P2P */
+       if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
+               ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
+
+       switch (txmode) {
+       case ATH10K_HW_TXRX_MGMT:
+       case ATH10K_HW_TXRX_NATIVE_WIFI:
+               ath10k_tx_h_nwifi(hw, skb);
+               ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
+               ath10k_tx_h_seq_no(vif, skb);
+               break;
+       case ATH10K_HW_TXRX_ETHERNET:
+               ath10k_tx_h_8023(skb);
+               break;
+       case ATH10K_HW_TXRX_RAW:
+               if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
+                       WARN_ON_ONCE(1);
+                       ieee80211_free_txskb(hw, skb);
+                       return -ENOTSUPP;
+               }
+       }
+
+       if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
+               if (!ath10k_mac_tx_frm_has_freq(ar)) {
+                       ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
+                                  skb);
+
+                       skb_queue_tail(&ar->offchan_tx_queue, skb);
+                       ieee80211_queue_work(hw, &ar->offchan_tx_work);
+                       return 0;
+               }
+       }
+
+       ret = ath10k_mac_tx_submit(ar, txmode, txpath, skb);
+       if (ret) {
+               ath10k_warn(ar, "failed to submit frame: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
 }
 
 void ath10k_offchan_tx_purge(struct ath10k *ar)
@@ -3354,12 +3492,13 @@ void ath10k_offchan_tx_work(struct work_struct *work)
        struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work);
        struct ath10k_peer *peer;
        struct ath10k_vif *arvif;
+       enum ath10k_hw_txrx_mode txmode;
+       enum ath10k_mac_tx_path txpath;
        struct ieee80211_hdr *hdr;
        struct ieee80211_vif *vif;
        struct ieee80211_sta *sta;
        struct sk_buff *skb;
        const u8 *peer_addr;
-       enum ath10k_hw_txrx_mode txmode;
        int vdev_id;
        int ret;
        unsigned long time_left;
@@ -3396,7 +3535,8 @@ void ath10k_offchan_tx_work(struct work_struct *work)
                                   peer_addr, vdev_id);
 
                if (!peer) {
-                       ret = ath10k_peer_create(ar, vdev_id, peer_addr,
+                       ret = ath10k_peer_create(ar, NULL, NULL, vdev_id,
+                                                peer_addr,
                                                 WMI_PEER_TYPE_DEFAULT);
                        if (ret)
                                ath10k_warn(ar, "failed to create peer %pM on vdev %d: %d\n",
@@ -3423,8 +3563,14 @@ 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);
 
-               ath10k_mac_tx(ar, txmode, skb);
+               ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb);
+               if (ret) {
+                       ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
+                                   ret);
+                       /* not serious */
+               }
 
                time_left =
                wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
@@ -3476,6 +3622,175 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
        }
 }
 
+static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
+{
+       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+
+       if (!txq)
+               return;
+
+       INIT_LIST_HEAD(&artxq->list);
+}
+
+static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
+{
+       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+       struct ath10k_skb_cb *cb;
+       struct sk_buff *msdu;
+       int msdu_id;
+
+       if (!txq)
+               return;
+
+       spin_lock_bh(&ar->txqs_lock);
+       if (!list_empty(&artxq->list))
+               list_del_init(&artxq->list);
+       spin_unlock_bh(&ar->txqs_lock);
+
+       spin_lock_bh(&ar->htt.tx_lock);
+       idr_for_each_entry(&ar->htt.pending_tx, msdu, msdu_id) {
+               cb = ATH10K_SKB_CB(msdu);
+               if (cb->txq == txq)
+                       cb->txq = NULL;
+       }
+       spin_unlock_bh(&ar->htt.tx_lock);
+}
+
+struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
+                                           u16 peer_id,
+                                           u8 tid)
+{
+       struct ath10k_peer *peer;
+
+       lockdep_assert_held(&ar->data_lock);
+
+       peer = ar->peer_map[peer_id];
+       if (!peer)
+               return NULL;
+
+       if (peer->sta)
+               return peer->sta->txq[tid];
+       else if (peer->vif)
+               return peer->vif->txq;
+       else
+               return NULL;
+}
+
+static bool ath10k_mac_tx_can_push(struct ieee80211_hw *hw,
+                                  struct ieee80211_txq *txq)
+{
+       struct ath10k *ar = hw->priv;
+       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+
+       /* No need to get locks */
+
+       if (ar->htt.tx_q_state.mode == HTT_TX_MODE_SWITCH_PUSH)
+               return true;
+
+       if (ar->htt.num_pending_tx < ar->htt.tx_q_state.num_push_allowed)
+               return true;
+
+       if (artxq->num_fw_queued < artxq->num_push_allowed)
+               return true;
+
+       return false;
+}
+
+int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
+                          struct ieee80211_txq *txq)
+{
+       struct ath10k *ar = hw->priv;
+       struct ath10k_htt *htt = &ar->htt;
+       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+       struct ieee80211_vif *vif = txq->vif;
+       struct ieee80211_sta *sta = txq->sta;
+       enum ath10k_hw_txrx_mode txmode;
+       enum ath10k_mac_tx_path txpath;
+       struct sk_buff *skb;
+       size_t skb_len;
+       int ret;
+
+       spin_lock_bh(&ar->htt.tx_lock);
+       ret = ath10k_htt_tx_inc_pending(htt);
+       spin_unlock_bh(&ar->htt.tx_lock);
+
+       if (ret)
+               return ret;
+
+       skb = ieee80211_tx_dequeue(hw, txq);
+       if (!skb) {
+               spin_lock_bh(&ar->htt.tx_lock);
+               ath10k_htt_tx_dec_pending(htt);
+               spin_unlock_bh(&ar->htt.tx_lock);
+
+               return -ENOENT;
+       }
+
+       ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb);
+
+       skb_len = skb->len;
+       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, sta, txmode, txpath, skb);
+       if (unlikely(ret)) {
+               ath10k_warn(ar, "failed to push frame: %d\n", ret);
+
+               spin_lock_bh(&ar->htt.tx_lock);
+               ath10k_htt_tx_dec_pending(htt);
+               spin_unlock_bh(&ar->htt.tx_lock);
+
+               return ret;
+       }
+
+       spin_lock_bh(&ar->htt.tx_lock);
+       artxq->num_fw_queued++;
+       spin_unlock_bh(&ar->htt.tx_lock);
+
+       return skb_len;
+}
+
+void ath10k_mac_tx_push_pending(struct ath10k *ar)
+{
+       struct ieee80211_hw *hw = ar->hw;
+       struct ieee80211_txq *txq;
+       struct ath10k_txq *artxq;
+       struct ath10k_txq *last;
+       int ret;
+       int max;
+
+       spin_lock_bh(&ar->txqs_lock);
+       rcu_read_lock();
+
+       last = list_last_entry(&ar->txqs, struct ath10k_txq, list);
+       while (!list_empty(&ar->txqs)) {
+               artxq = list_first_entry(&ar->txqs, struct ath10k_txq, list);
+               txq = container_of((void *)artxq, struct ieee80211_txq,
+                                  drv_priv);
+
+               /* Prevent aggressive sta/tid taking over tx queue */
+               max = 16;
+               ret = 0;
+               while (ath10k_mac_tx_can_push(hw, txq) && max--) {
+                       ret = ath10k_mac_tx_push_txq(hw, txq);
+                       if (ret < 0)
+                               break;
+               }
+
+               list_del_init(&artxq->list);
+               if (ret != -ENOENT)
+                       list_add_tail(&artxq->list, &ar->txqs);
+
+               ath10k_htt_tx_txq_update(hw, txq);
+
+               if (artxq == last || (ret < 0 && ret != -ENOENT))
+                       break;
+       }
+
+       rcu_read_unlock();
+       spin_unlock_bh(&ar->txqs_lock);
+}
+
 /************/
 /* Scanning */
 /************/
@@ -3638,66 +3953,86 @@ static int ath10k_start_scan(struct ath10k *ar,
 /* mac80211 callbacks */
 /**********************/
 
-static void ath10k_tx(struct ieee80211_hw *hw,
-                     struct ieee80211_tx_control *control,
-                     struct sk_buff *skb)
+static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
+                            struct ieee80211_tx_control *control,
+                            struct sk_buff *skb)
 {
        struct ath10k *ar = hw->priv;
-       struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
+       struct ath10k_htt *htt = &ar->htt;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_vif *vif = info->control.vif;
        struct ieee80211_sta *sta = control->sta;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       struct ieee80211_txq *txq = NULL;
+       struct ieee80211_hdr *hdr = (void *)skb->data;
        enum ath10k_hw_txrx_mode txmode;
+       enum ath10k_mac_tx_path txpath;
+       bool is_htt;
+       bool is_mgmt;
+       bool is_presp;
+       int ret;
 
-       /* We should disable CCK RATE due to P2P */
-       if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
-               ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
+       ath10k_mac_tx_h_fill_cb(ar, vif, txq, skb);
 
        txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
+       txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
+       is_htt = (txpath == ATH10K_MAC_TX_HTT ||
+                 txpath == ATH10K_MAC_TX_HTT_MGMT);
+       is_mgmt = (txpath == ATH10K_MAC_TX_HTT_MGMT);
 
-       skb_cb->flags = 0;
-       if (!ath10k_tx_h_use_hwcrypto(vif, skb))
-               skb_cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
+       if (is_htt) {
+               spin_lock_bh(&ar->htt.tx_lock);
+               is_presp = ieee80211_is_probe_resp(hdr->frame_control);
 
-       if (ieee80211_is_mgmt(hdr->frame_control))
-               skb_cb->flags |= ATH10K_SKB_F_MGMT;
-
-       if (ieee80211_is_data_qos(hdr->frame_control))
-               skb_cb->flags |= ATH10K_SKB_F_QOS;
-
-       skb_cb->vif = vif;
+               ret = ath10k_htt_tx_inc_pending(htt);
+               if (ret) {
+                       ath10k_warn(ar, "failed to increase tx pending count: %d, dropping\n",
+                                   ret);
+                       spin_unlock_bh(&ar->htt.tx_lock);
+                       ieee80211_free_txskb(ar->hw, skb);
+                       return;
+               }
 
-       switch (txmode) {
-       case ATH10K_HW_TXRX_MGMT:
-       case ATH10K_HW_TXRX_NATIVE_WIFI:
-               ath10k_tx_h_nwifi(hw, skb);
-               ath10k_tx_h_add_p2p_noa_ie(ar, vif, skb);
-               ath10k_tx_h_seq_no(vif, skb);
-               break;
-       case ATH10K_HW_TXRX_ETHERNET:
-               ath10k_tx_h_8023(skb);
-               break;
-       case ATH10K_HW_TXRX_RAW:
-               if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
-                       WARN_ON_ONCE(1);
-                       ieee80211_free_txskb(hw, skb);
+               ret = ath10k_htt_tx_mgmt_inc_pending(htt, is_mgmt, is_presp);
+               if (ret) {
+                       ath10k_dbg(ar, ATH10K_DBG_MAC, "failed to increase tx mgmt pending count: %d, dropping\n",
+                                  ret);
+                       ath10k_htt_tx_dec_pending(htt);
+                       spin_unlock_bh(&ar->htt.tx_lock);
+                       ieee80211_free_txskb(ar->hw, skb);
                        return;
                }
+               spin_unlock_bh(&ar->htt.tx_lock);
        }
 
-       if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
-               if (!ath10k_mac_tx_frm_has_freq(ar)) {
-                       ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
-                                  skb);
-
-                       skb_queue_tail(&ar->offchan_tx_queue, skb);
-                       ieee80211_queue_work(hw, &ar->offchan_tx_work);
-                       return;
+       ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb);
+       if (ret) {
+               ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
+               if (is_htt) {
+                       spin_lock_bh(&ar->htt.tx_lock);
+                       ath10k_htt_tx_dec_pending(htt);
+                       if (is_mgmt)
+                               ath10k_htt_tx_mgmt_dec_pending(htt);
+                       spin_unlock_bh(&ar->htt.tx_lock);
                }
+               return;
        }
+}
+
+static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
+                                       struct ieee80211_txq *txq)
+{
+       struct ath10k *ar = hw->priv;
+       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+
+       spin_lock_bh(&ar->txqs_lock);
+       if (list_empty(&artxq->list))
+               list_add_tail(&artxq->list, &ar->txqs);
+       spin_unlock_bh(&ar->txqs_lock);
+
+       if (ath10k_mac_tx_can_push(hw, txq))
+               tasklet_schedule(&ar->htt.txrx_compl_task);
 
-       ath10k_mac_tx(ar, txmode, skb);
+       ath10k_htt_tx_txq_update(hw, txq);
 }
 
 /* Must not be called with conf_mutex held as workers can use that also. */
@@ -4100,7 +4435,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
 
        ar->ani_enabled = true;
 
-       if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
+       if (ath10k_peer_stats_enabled(ar)) {
                param = ar->wmi.pdev_param->peer_stats_update_period;
                ret = ath10k_wmi_pdev_set_param(ar, param,
                                                PEER_DEFAULT_STATS_UPDATE_PERIOD);
@@ -4313,6 +4648,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 {
        struct ath10k *ar = hw->priv;
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+       struct ath10k_peer *peer;
        enum wmi_sta_powersave_param param;
        int ret = 0;
        u32 value;
@@ -4325,6 +4661,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        mutex_lock(&ar->conf_mutex);
 
        memset(arvif, 0, sizeof(*arvif));
+       ath10k_mac_txq_init(vif->txq);
 
        arvif->ar = ar;
        arvif->vif = vif;
@@ -4489,7 +4826,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
                goto err_vdev_delete;
        }
 
-       if (ar->cfg_tx_chainmask) {
+       /* Configuring number of spatial stream for monitor interface is causing
+        * target assert in qca9888 and qca6174.
+        */
+       if (ar->cfg_tx_chainmask && (vif->type != NL80211_IFTYPE_MONITOR)) {
                u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
 
                vdev_param = ar->wmi.vdev_param->nss;
@@ -4505,13 +4845,31 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
 
        if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
            arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
-               ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr,
-                                        WMI_PEER_TYPE_DEFAULT);
+               ret = ath10k_peer_create(ar, vif, NULL, arvif->vdev_id,
+                                        vif->addr, WMI_PEER_TYPE_DEFAULT);
                if (ret) {
                        ath10k_warn(ar, "failed to create vdev %i peer for AP/IBSS: %d\n",
                                    arvif->vdev_id, ret);
                        goto err_vdev_delete;
                }
+
+               spin_lock_bh(&ar->data_lock);
+
+               peer = ath10k_peer_find(ar, arvif->vdev_id, vif->addr);
+               if (!peer) {
+                       ath10k_warn(ar, "failed to lookup peer %pM on vdev %i\n",
+                                   vif->addr, arvif->vdev_id);
+                       spin_unlock_bh(&ar->data_lock);
+                       ret = -ENOENT;
+                       goto err_peer_delete;
+               }
+
+               arvif->peer_id = find_first_bit(peer->peer_ids,
+                                               ATH10K_MAX_NUM_PEER_IDS);
+
+               spin_unlock_bh(&ar->data_lock);
+       } else {
+               arvif->peer_id = HTT_INVALID_PEERID;
        }
 
        if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
@@ -4622,7 +4980,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
 {
        struct ath10k *ar = hw->priv;
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+       struct ath10k_peer *peer;
        int ret;
+       int i;
 
        cancel_work_sync(&arvif->ap_csa_work);
        cancel_delayed_work_sync(&arvif->connection_loss_work);
@@ -4676,7 +5036,22 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
                spin_unlock_bh(&ar->data_lock);
        }
 
+       spin_lock_bh(&ar->data_lock);
+       for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+               peer = ar->peer_map[i];
+               if (!peer)
+                       continue;
+
+               if (peer->vif == vif) {
+                       ath10k_warn(ar, "found vif peer %pM entry on vdev %i after it was supposedly removed\n",
+                                   vif->addr, arvif->vdev_id);
+                       peer->vif = NULL;
+               }
+       }
+       spin_unlock_bh(&ar->data_lock);
+
        ath10k_peer_cleanup(ar, arvif->vdev_id);
+       ath10k_mac_txq_unref(ar, vif->txq);
 
        if (vif->type == NL80211_IFTYPE_MONITOR) {
                ar->monitor_arvif = NULL;
@@ -4689,6 +5064,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
        ath10k_mac_vif_tx_unlock_all(arvif);
        spin_unlock_bh(&ar->htt.tx_lock);
 
+       ath10k_mac_txq_unref(ar, vif->txq);
+
        mutex_unlock(&ar->conf_mutex);
 }
 
@@ -5393,13 +5770,18 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
        struct ath10k *ar = hw->priv;
        struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
        struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+       struct ath10k_peer *peer;
        int ret = 0;
+       int i;
 
        if (old_state == IEEE80211_STA_NOTEXIST &&
            new_state == IEEE80211_STA_NONE) {
                memset(arsta, 0, sizeof(*arsta));
                arsta->arvif = arvif;
                INIT_WORK(&arsta->update_wk, ath10k_sta_rc_update_wk);
+
+               for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
+                       ath10k_mac_txq_init(sta->txq[i]);
        }
 
        /* cancel must be done outside the mutex to avoid deadlock */
@@ -5434,8 +5816,8 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
                if (sta->tdls)
                        peer_type = WMI_PEER_TYPE_TDLS;
 
-               ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr,
-                                        peer_type);
+               ret = ath10k_peer_create(ar, vif, sta, arvif->vdev_id,
+                                        sta->addr, peer_type);
                if (ret) {
                        ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n",
                                    sta->addr, arvif->vdev_id, ret);
@@ -5443,6 +5825,24 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
                        goto exit;
                }
 
+               spin_lock_bh(&ar->data_lock);
+
+               peer = ath10k_peer_find(ar, arvif->vdev_id, sta->addr);
+               if (!peer) {
+                       ath10k_warn(ar, "failed to lookup peer %pM on vdev %i\n",
+                                   vif->addr, arvif->vdev_id);
+                       spin_unlock_bh(&ar->data_lock);
+                       ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
+                       ath10k_mac_dec_num_stations(arvif, sta);
+                       ret = -ENOENT;
+                       goto exit;
+               }
+
+               arsta->peer_id = find_first_bit(peer->peer_ids,
+                                               ATH10K_MAX_NUM_PEER_IDS);
+
+               spin_unlock_bh(&ar->data_lock);
+
                if (!sta->tdls)
                        goto exit;
 
@@ -5505,6 +5905,23 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
 
                ath10k_mac_dec_num_stations(arvif, sta);
 
+               spin_lock_bh(&ar->data_lock);
+               for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+                       peer = ar->peer_map[i];
+                       if (!peer)
+                               continue;
+
+                       if (peer->sta == sta) {
+                               ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n",
+                                           sta->addr, arvif->vdev_id);
+                               peer->sta = NULL;
+                       }
+               }
+               spin_unlock_bh(&ar->data_lock);
+
+               for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
+                       ath10k_mac_txq_unref(ar, sta->txq[i]);
+
                if (!sta->tdls)
                        goto exit;
 
@@ -6807,7 +7224,8 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 }
 
 static const struct ieee80211_ops ath10k_ops = {
-       .tx                             = ath10k_tx,
+       .tx                             = ath10k_mac_op_tx,
+       .wake_tx_queue                  = ath10k_mac_op_wake_tx_queue,
        .start                          = ath10k_start,
        .stop                           = ath10k_stop,
        .config                         = ath10k_config,
@@ -7262,6 +7680,7 @@ int ath10k_mac_register(struct ath10k *ar)
 
        ar->hw->vif_data_size = sizeof(struct ath10k_vif);
        ar->hw->sta_data_size = sizeof(struct ath10k_sta);
+       ar->hw->txq_data_size = sizeof(struct ath10k_txq);
 
        ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
 
@@ -7286,7 +7705,8 @@ int ath10k_mac_register(struct ath10k *ar)
        ar->hw->wiphy->max_remain_on_channel_duration = 5000;
 
        ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
-       ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
+       ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
+                                  NL80211_FEATURE_AP_SCAN;
 
        ar->hw->wiphy->max_ap_assoc_sta = ar->max_num_stations;
 
index 53091588090d0c5645989a347c1d5a95a5033ecb..2c3327beb44551bc6a7283dd3a7846f0687d0ee9 100644 (file)
@@ -75,6 +75,12 @@ void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
 void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason);
 void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason);
 bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar);
+void ath10k_mac_tx_push_pending(struct ath10k *ar);
+int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
+                          struct ieee80211_txq *txq);
+struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
+                                           u16 peer_id,
+                                           u8 tid);
 
 static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
 {
index b3cff1d3364aad85151b4abd54d05bee0d2e02a3..0b305efe6c946fd900cae31a8020cc89a292f178 100644 (file)
@@ -809,7 +809,8 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
        spin_lock_bh(&ar_pci->ce_lock);
        num = __ath10k_ce_rx_num_free_bufs(ce_pipe);
        spin_unlock_bh(&ar_pci->ce_lock);
-       while (num--) {
+
+       while (num >= 0) {
                ret = __ath10k_pci_rx_post_buf(pipe);
                if (ret) {
                        if (ret == -ENOSPC)
@@ -819,6 +820,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
                                  ATH10K_PCI_RX_POST_RETRY_MS);
                        break;
                }
+               num--;
        }
 }
 
@@ -870,10 +872,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret = 0;
-       u32 buf;
+       u32 *buf;
        unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
-       unsigned int id;
-       unsigned int flags;
        struct ath10k_ce_pipe *ce_diag;
        /* Host buffer address in CE space */
        u32 ce_data;
@@ -909,7 +909,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
                nbytes = min_t(unsigned int, remaining_bytes,
                               DIAG_TRANSFER_LIMIT);
 
-               ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
+               ret = __ath10k_ce_rx_post_buf(ce_diag, &ce_data, ce_data);
                if (ret != 0)
                        goto done;
 
@@ -940,9 +940,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
                }
 
                i = 0;
-               while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
-                                                           &completed_nbytes,
-                                                           &id, &flags) != 0) {
+               while (ath10k_ce_completed_recv_next_nolock(ce_diag,
+                                                           (void **)&buf,
+                                                           &completed_nbytes)
+                                                               != 0) {
                        mdelay(1);
 
                        if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -956,7 +957,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
                        goto done;
                }
 
-               if (buf != ce_data) {
+               if (*buf != ce_data) {
                        ret = -EIO;
                        goto done;
                }
@@ -1026,10 +1027,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
 {
        struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
        int ret = 0;
-       u32 buf;
+       u32 *buf;
        unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
-       unsigned int id;
-       unsigned int flags;
        struct ath10k_ce_pipe *ce_diag;
        void *data_buf = NULL;
        u32 ce_data;    /* Host buffer address in CE space */
@@ -1078,7 +1077,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
                nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
 
                /* Set up to receive directly into Target(!) address */
-               ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
+               ret = __ath10k_ce_rx_post_buf(ce_diag, &address, address);
                if (ret != 0)
                        goto done;
 
@@ -1103,9 +1102,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
                }
 
                i = 0;
-               while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
-                                                           &completed_nbytes,
-                                                           &id, &flags) != 0) {
+               while (ath10k_ce_completed_recv_next_nolock(ce_diag,
+                                                           (void **)&buf,
+                                                           &completed_nbytes)
+                                                               != 0) {
                        mdelay(1);
 
                        if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -1119,7 +1119,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
                        goto done;
                }
 
-               if (buf != address) {
+               if (*buf != address) {
                        ret = -EIO;
                        goto done;
                }
@@ -1181,15 +1181,11 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state,
        struct sk_buff *skb;
        struct sk_buff_head list;
        void *transfer_context;
-       u32 ce_data;
        unsigned int nbytes, max_nbytes;
-       unsigned int transfer_id;
-       unsigned int flags;
 
        __skb_queue_head_init(&list);
        while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
-                                            &ce_data, &nbytes, &transfer_id,
-                                            &flags) == 0) {
+                                            &nbytes) == 0) {
                skb = transfer_context;
                max_nbytes = skb->len + skb_tailroom(skb);
                dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
@@ -1218,6 +1214,63 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state,
        ath10k_pci_rx_post_pipe(pipe_info);
 }
 
+static void ath10k_pci_process_htt_rx_cb(struct ath10k_ce_pipe *ce_state,
+                                        void (*callback)(struct ath10k *ar,
+                                                         struct sk_buff *skb))
+{
+       struct ath10k *ar = ce_state->ar;
+       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+       struct ath10k_pci_pipe *pipe_info =  &ar_pci->pipe_info[ce_state->id];
+       struct ath10k_ce_pipe *ce_pipe = pipe_info->ce_hdl;
+       struct sk_buff *skb;
+       struct sk_buff_head list;
+       void *transfer_context;
+       unsigned int nbytes, max_nbytes, nentries;
+       int orig_len;
+
+       /* No need to aquire ce_lock for CE5, since this is the only place CE5
+        * is processed other than init and deinit. Before releasing CE5
+        * buffers, interrupts are disabled. Thus CE5 access is serialized.
+        */
+       __skb_queue_head_init(&list);
+       while (ath10k_ce_completed_recv_next_nolock(ce_state, &transfer_context,
+                                                   &nbytes) == 0) {
+               skb = transfer_context;
+               max_nbytes = skb->len + skb_tailroom(skb);
+
+               if (unlikely(max_nbytes < nbytes)) {
+                       ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)",
+                                   nbytes, max_nbytes);
+                       continue;
+               }
+
+               dma_sync_single_for_cpu(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
+                                       max_nbytes, DMA_FROM_DEVICE);
+               skb_put(skb, nbytes);
+               __skb_queue_tail(&list, skb);
+       }
+
+       nentries = skb_queue_len(&list);
+       while ((skb = __skb_dequeue(&list))) {
+               ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
+                          ce_state->id, skb->len);
+               ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
+                               skb->data, skb->len);
+
+               orig_len = skb->len;
+               callback(ar, skb);
+               skb_push(skb, orig_len - skb->len);
+               skb_reset_tail_pointer(skb);
+               skb_trim(skb, 0);
+
+               /*let device gain the buffer again*/
+               dma_sync_single_for_device(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
+                                          skb->len + skb_tailroom(skb),
+                                          DMA_FROM_DEVICE);
+       }
+       ath10k_ce_rx_update_write_idx(ce_pipe, nentries);
+}
+
 /* Called by lower (CE) layer when data is received from the Target. */
 static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
 {
@@ -1274,7 +1327,7 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state)
         */
        ath10k_ce_per_engine_service(ce_state->ar, 4);
 
-       ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver);
+       ath10k_pci_process_htt_rx_cb(ce_state, ath10k_pci_htt_rx_deliver);
 }
 
 int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
@@ -1835,13 +1888,10 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
 {
        struct ath10k *ar = ce_state->ar;
        struct bmi_xfer *xfer;
-       u32 ce_data;
        unsigned int nbytes;
-       unsigned int transfer_id;
-       unsigned int flags;
 
-       if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer, &ce_data,
-                                         &nbytes, &transfer_id, &flags))
+       if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer,
+                                         &nbytes))
                return;
 
        if (WARN_ON_ONCE(!xfer))
index fbfb608e48abe3dce52ccd1868068f9db86593bc..9369411a9ac0b2450da88f5e1b59ccafca96b7ba 100644 (file)
@@ -49,25 +49,25 @@ out:
        spin_unlock_bh(&ar->data_lock);
 }
 
-void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
-                         const struct htt_tx_done *tx_done)
+int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
+                        const struct htt_tx_done *tx_done)
 {
        struct ath10k *ar = htt->ar;
        struct device *dev = ar->dev;
        struct ieee80211_tx_info *info;
+       struct ieee80211_txq *txq;
        struct ath10k_skb_cb *skb_cb;
+       struct ath10k_txq *artxq;
        struct sk_buff *msdu;
-       bool limit_mgmt_desc = false;
 
        ath10k_dbg(ar, ATH10K_DBG_HTT,
-                  "htt tx completion msdu_id %u discard %d no_ack %d success %d\n",
-                  tx_done->msdu_id, !!tx_done->discard,
-                  !!tx_done->no_ack, !!tx_done->success);
+                  "htt tx completion msdu_id %u status %d\n",
+                  tx_done->msdu_id, tx_done->status);
 
        if (tx_done->msdu_id >= htt->max_num_pending_tx) {
                ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n",
                            tx_done->msdu_id);
-               return;
+               return -EINVAL;
        }
 
        spin_lock_bh(&htt->tx_lock);
@@ -76,17 +76,18 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
                ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
                            tx_done->msdu_id);
                spin_unlock_bh(&htt->tx_lock);
-               return;
+               return -ENOENT;
        }
 
        skb_cb = ATH10K_SKB_CB(msdu);
+       txq = skb_cb->txq;
+       artxq = (void *)txq->drv_priv;
 
-       if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) &&
-           ar->hw_params.max_probe_resp_desc_thres)
-               limit_mgmt_desc = true;
+       if (txq)
+               artxq->num_fw_queued--;
 
        ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
-       __ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
+       ath10k_htt_tx_dec_pending(htt);
        if (htt->num_pending_tx == 0)
                wake_up(&htt->empty_tx_wq);
        spin_unlock_bh(&htt->tx_lock);
@@ -99,22 +100,24 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
        memset(&info->status, 0, sizeof(info->status));
        trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
 
-       if (tx_done->discard) {
+       if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
                ieee80211_free_txskb(htt->ar->hw, msdu);
-               return;
+               return 0;
        }
 
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
                info->flags |= IEEE80211_TX_STAT_ACK;
 
-       if (tx_done->no_ack)
+       if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
                info->flags &= ~IEEE80211_TX_STAT_ACK;
 
-       if (tx_done->success && (info->flags & IEEE80211_TX_CTL_NO_ACK))
+       if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
+           (info->flags & IEEE80211_TX_CTL_NO_ACK))
                info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
 
        ieee80211_tx_status(htt->ar->hw, msdu);
        /* we do not own the msdu anymore */
+       return 0;
 }
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
@@ -203,6 +206,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
        ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
                   ev->vdev_id, ev->addr, ev->peer_id);
 
+       ar->peer_map[ev->peer_id] = peer;
        set_bit(ev->peer_id, peer->peer_ids);
 exit:
        spin_unlock_bh(&ar->data_lock);
@@ -225,6 +229,7 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
        ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
                   peer->vdev_id, peer->addr, ev->peer_id);
 
+       ar->peer_map[ev->peer_id] = NULL;
        clear_bit(ev->peer_id, peer->peer_ids);
 
        if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) {
index a90e09f5c7f2f180370e118175991bea68018d32..e7ea1ae1c438de06331d2fc0f3db86d4329d31fe 100644 (file)
@@ -19,8 +19,8 @@
 
 #include "htt.h"
 
-void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
-                         const struct htt_tx_done *tx_done);
+int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
+                        const struct htt_tx_done *tx_done);
 
 struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
                                     const u8 *addr);
index 32ab34edceb54927fa4f668ac7c37ec4f728226a..7fb00dcc03b81eb07117f8c61fe1fc5ea8791aba 100644 (file)
@@ -186,6 +186,9 @@ struct wmi_ops {
                                                        u8 enable,
                                                        u32 detect_level,
                                                        u32 detect_margin);
+       struct sk_buff *(*ext_resource_config)(struct ath10k *ar,
+                                              enum wmi_host_platform_type type,
+                                              u32 fw_feature_bitmap);
        int (*get_vdev_subtype)(struct ath10k *ar,
                                enum wmi_vdev_subtype subtype);
 };
@@ -1329,6 +1332,26 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
                                   ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
 }
 
+static inline int
+ath10k_wmi_ext_resource_config(struct ath10k *ar,
+                              enum wmi_host_platform_type type,
+                              u32 fw_feature_bitmap)
+{
+       struct sk_buff *skb;
+
+       if (!ar->wmi.ops->ext_resource_config)
+               return -EOPNOTSUPP;
+
+       skb = ar->wmi.ops->ext_resource_config(ar, type,
+                                              fw_feature_bitmap);
+
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       return ath10k_wmi_cmd_send(ar, skb,
+                                  ar->wmi.cmd->ext_resource_cfg_cmdid);
+}
+
 static inline int
 ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype)
 {
index 70261387d1a5733a6069e9274222d49ec9a8cb99..f7ec65f263a0e13a291fe4fbbaa7999d5c854ea6 100644 (file)
@@ -705,6 +705,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
        .set_cca_params_cmdid = WMI_10_4_SET_CCA_PARAMS_CMDID,
        .pdev_bss_chan_info_request_cmdid =
                        WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
+       .ext_resource_cfg_cmdid = WMI_10_4_EXT_RESOURCE_CFG_CMDID,
 };
 
 /* MAIN WMI VDEV param map */
@@ -2099,34 +2100,6 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
        return 0;
 }
 
-static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode)
-{
-       enum ieee80211_band band;
-
-       switch (phy_mode) {
-       case MODE_11A:
-       case MODE_11NA_HT20:
-       case MODE_11NA_HT40:
-       case MODE_11AC_VHT20:
-       case MODE_11AC_VHT40:
-       case MODE_11AC_VHT80:
-               band = IEEE80211_BAND_5GHZ;
-               break;
-       case MODE_11G:
-       case MODE_11B:
-       case MODE_11GONLY:
-       case MODE_11NG_HT20:
-       case MODE_11NG_HT40:
-       case MODE_11AC_VHT20_2G:
-       case MODE_11AC_VHT40_2G:
-       case MODE_11AC_VHT80_2G:
-       default:
-               band = IEEE80211_BAND_2GHZ;
-       }
-
-       return band;
-}
-
 /* If keys are configured, HW decrypts all frames
  * with protected bit set. Mark such frames as decrypted.
  */
@@ -2167,8 +2140,10 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
        struct wmi_mgmt_rx_event_v1 *ev_v1;
        struct wmi_mgmt_rx_event_v2 *ev_v2;
        struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
+       struct wmi_mgmt_rx_ext_info *ext_info;
        size_t pull_len;
        u32 msdu_len;
+       u32 len;
 
        if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
                ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
@@ -2195,6 +2170,12 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
        if (skb->len < msdu_len)
                return -EPROTO;
 
+       if (le32_to_cpu(arg->status) & WMI_RX_STATUS_EXT_INFO) {
+               len = ALIGN(le32_to_cpu(arg->buf_len), 4);
+               ext_info = (struct wmi_mgmt_rx_ext_info *)(skb->data + len);
+               memcpy(&arg->ext_info, ext_info,
+                      sizeof(struct wmi_mgmt_rx_ext_info));
+       }
        /* the WMI buffer might've ended up being padded to 4 bytes due to HTC
         * trailer with credit update. Trim the excess garbage.
         */
@@ -2211,6 +2192,8 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
        struct wmi_10_4_mgmt_rx_hdr *ev_hdr;
        size_t pull_len;
        u32 msdu_len;
+       struct wmi_mgmt_rx_ext_info *ext_info;
+       u32 len;
 
        ev = (struct wmi_10_4_mgmt_rx_event *)skb->data;
        ev_hdr = &ev->hdr;
@@ -2231,6 +2214,13 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
        if (skb->len < msdu_len)
                return -EPROTO;
 
+       if (le32_to_cpu(arg->status) & WMI_RX_STATUS_EXT_INFO) {
+               len = ALIGN(le32_to_cpu(arg->buf_len), 4);
+               ext_info = (struct wmi_mgmt_rx_ext_info *)(skb->data + len);
+               memcpy(&arg->ext_info, ext_info,
+                      sizeof(struct wmi_mgmt_rx_ext_info));
+       }
+
        /* Make sure bytes added for padding are removed. */
        skb_trim(skb, msdu_len);
 
@@ -2281,6 +2271,11 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        if (rx_status & WMI_RX_STATUS_ERR_MIC)
                status->flag |= RX_FLAG_MMIC_ERROR;
 
+       if (rx_status & WMI_RX_STATUS_EXT_INFO) {
+               status->mactime =
+                       __le64_to_cpu(arg.ext_info.rx_mac_timestamp);
+               status->flag |= RX_FLAG_MACTIME_END;
+       }
        /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to
         * MODE_11B. This means phy_mode is not a reliable source for the band
         * of mgmt rx.
@@ -2310,6 +2305,12 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        hdr = (struct ieee80211_hdr *)skb->data;
        fc = le16_to_cpu(hdr->frame_control);
 
+       /* Firmware is guaranteed to report all essential management frames via
+        * WMI while it can deliver some extra via HTT. Since there can be
+        * duplicates split the reporting wrt monitor/sniffing.
+        */
+       status->flag |= RX_FLAG_SKIP_MONITOR;
+
        ath10k_wmi_handle_wep_reauth(ar, skb, status);
 
        /* FW delivers WEP Shared Auth frame with Protected Bit set and
@@ -2612,6 +2613,16 @@ void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
        dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
 }
 
+static void
+ath10k_wmi_10_4_pull_peer_stats(const struct wmi_10_4_peer_stats *src,
+                               struct ath10k_fw_stats_peer *dst)
+{
+       ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
+       dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
+       dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
+       dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
+}
+
 static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
                                            struct sk_buff *skb,
                                            struct ath10k_fw_stats *stats)
@@ -2865,11 +2876,8 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
                const struct wmi_10_2_4_ext_peer_stats *src;
                struct ath10k_fw_stats_peer *dst;
                int stats_len;
-               bool ext_peer_stats_support;
 
-               ext_peer_stats_support = test_bit(WMI_SERVICE_PEER_STATS,
-                                                 ar->wmi.svc_map);
-               if (ext_peer_stats_support)
+               if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
                        stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats);
                else
                        stats_len = sizeof(struct wmi_10_2_4_peer_stats);
@@ -2886,7 +2894,7 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
 
                dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate);
 
-               if (ext_peer_stats_support)
+               if (ath10k_peer_stats_enabled(ar))
                        dst->rx_duration = __le32_to_cpu(src->rx_duration);
                /* FIXME: expose 10.2 specific values */
 
@@ -2905,6 +2913,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
        u32 num_pdev_ext_stats;
        u32 num_vdev_stats;
        u32 num_peer_stats;
+       u32 stats_id;
        int i;
 
        if (!skb_pull(skb, sizeof(*ev)))
@@ -2914,6 +2923,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
        num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
        num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
        num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
+       stats_id = __le32_to_cpu(ev->stats_id);
 
        for (i = 0; i < num_pdev_stats; i++) {
                const struct wmi_10_4_pdev_stats *src;
@@ -2953,22 +2963,28 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
        /* fw doesn't implement vdev stats */
 
        for (i = 0; i < num_peer_stats; i++) {
-               const struct wmi_10_4_peer_stats *src;
+               const struct wmi_10_4_peer_extd_stats *src;
                struct ath10k_fw_stats_peer *dst;
+               int stats_len;
+               bool extd_peer_stats = !!(stats_id & WMI_10_4_STAT_PEER_EXTD);
+
+               if (extd_peer_stats)
+                       stats_len = sizeof(struct wmi_10_4_peer_extd_stats);
+               else
+                       stats_len = sizeof(struct wmi_10_4_peer_stats);
 
                src = (void *)skb->data;
-               if (!skb_pull(skb, sizeof(*src)))
+               if (!skb_pull(skb, stats_len))
                        return -EPROTO;
 
                dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
                if (!dst)
                        continue;
 
-               ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
-               dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
-               dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
-               dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
+               ath10k_wmi_10_4_pull_peer_stats(&src->common, dst);
                /* FIXME: expose 10.4 specific values */
+               if (extd_peer_stats)
+                       dst->rx_duration = __le32_to_cpu(src->rx_duration);
 
                list_add_tail(&dst->list, &stats->peers);
        }
@@ -4617,10 +4633,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
        }
 
        if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) {
+               if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
+                            ar->fw_features))
+                       ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC +
+                                              ar->max_num_vdevs;
+               else
+                       ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS +
+                                              ar->max_num_vdevs;
+
                ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX +
                                    ar->max_num_vdevs;
-               ar->num_active_peers = ar->hw_params.qcache_active_peers +
-                                      ar->max_num_vdevs;
                ar->num_tids = ar->num_active_peers * 2;
                ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX;
        }
@@ -5517,7 +5539,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
 
        config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
        config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
-       if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
+
+       if (ath10k_peer_stats_enabled(ar)) {
                config.num_peers = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_PEERS);
                config.num_tids = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_TIDS);
        } else {
@@ -5579,7 +5602,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
            test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
                features |= WMI_10_2_COEX_GPIO;
 
-       if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
+       if (ath10k_peer_stats_enabled(ar))
                features |= WMI_10_2_PEER_STATS;
 
        cmd->resource_config.feature_mask = __cpu_to_le32(features);
@@ -7484,6 +7507,28 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar,
        return -ENOTSUPP;
 }
 
+static struct sk_buff *
+ath10k_wmi_10_4_ext_resource_config(struct ath10k *ar,
+                                   enum wmi_host_platform_type type,
+                                   u32 fw_feature_bitmap)
+{
+       struct wmi_ext_resource_config_10_4_cmd *cmd;
+       struct sk_buff *skb;
+
+       skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+       if (!skb)
+               return ERR_PTR(-ENOMEM);
+
+       cmd = (struct wmi_ext_resource_config_10_4_cmd *)skb->data;
+       cmd->host_platform_config = __cpu_to_le32(type);
+       cmd->fw_feature_bitmap = __cpu_to_le32(fw_feature_bitmap);
+
+       ath10k_dbg(ar, ATH10K_DBG_WMI,
+                  "wmi ext resource config host type %d firmware feature bitmap %08x\n",
+                  type, fw_feature_bitmap);
+       return skb;
+}
+
 static const struct wmi_ops wmi_ops = {
        .rx = ath10k_wmi_op_rx,
        .map_svc = wmi_main_svc_map,
@@ -7810,6 +7855,7 @@ static const struct wmi_ops wmi_10_4_ops = {
        .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
        .gen_delba_send = ath10k_wmi_op_gen_delba_send,
        .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
+       .ext_resource_config = ath10k_wmi_10_4_ext_resource_config,
 
        /* shared with 10.2 */
        .gen_request_stats = ath10k_wmi_op_gen_request_stats,
index 4d3cbc44fcd27851ec46a7178e42d04f69ed3701..feebd19ff08cb979c03081538669af02ad9d020a 100644 (file)
@@ -816,6 +816,7 @@ struct wmi_cmd_map {
        u32 set_cca_params_cmdid;
        u32 pdev_bss_chan_info_request_cmdid;
        u32 pdev_enable_adaptive_cca_cmdid;
+       u32 ext_resource_cfg_cmdid;
 };
 
 /*
@@ -2667,6 +2668,31 @@ struct wmi_resource_config_10_4 {
        __le32 qwrap_config;
 } __packed;
 
+/**
+ * enum wmi_10_4_feature_mask - WMI 10.4 feature enable/disable flags
+ * @WMI_10_4_LTEU_SUPPORT: LTEU config
+ * @WMI_10_4_COEX_GPIO_SUPPORT: COEX GPIO config
+ * @WMI_10_4_AUX_RADIO_SPECTRAL_INTF: AUX Radio Enhancement for spectral scan
+ * @WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF: AUX Radio Enhancement for chan load scan
+ * @WMI_10_4_BSS_CHANNEL_INFO_64: BSS channel info stats
+ * @WMI_10_4_PEER_STATS: Per station stats
+ */
+enum wmi_10_4_feature_mask {
+       WMI_10_4_LTEU_SUPPORT                   = BIT(0),
+       WMI_10_4_COEX_GPIO_SUPPORT              = BIT(1),
+       WMI_10_4_AUX_RADIO_SPECTRAL_INTF        = BIT(2),
+       WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF       = BIT(3),
+       WMI_10_4_BSS_CHANNEL_INFO_64            = BIT(4),
+       WMI_10_4_PEER_STATS                     = BIT(5),
+};
+
+struct wmi_ext_resource_config_10_4_cmd {
+       /* contains enum wmi_host_platform_type */
+       __le32 host_platform_config;
+       /* see enum wmi_10_4_feature_mask */
+       __le32 fw_feature_bitmap;
+};
+
 /* strucutre describing host memory chunk. */
 struct host_memory_chunk {
        /* id of the request that is passed up in service ready */
@@ -3037,11 +3063,17 @@ struct wmi_10_4_mgmt_rx_event {
        u8 buf[0];
 } __packed;
 
+struct wmi_mgmt_rx_ext_info {
+       __le64 rx_mac_timestamp;
+} __packed __aligned(4);
+
 #define WMI_RX_STATUS_OK                       0x00
 #define WMI_RX_STATUS_ERR_CRC                  0x01
 #define WMI_RX_STATUS_ERR_DECRYPT              0x08
 #define WMI_RX_STATUS_ERR_MIC                  0x10
 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS       0x20
+/* Extension data at the end of mgmt frame */
+#define WMI_RX_STATUS_EXT_INFO         0x40
 
 #define PHY_ERROR_GEN_SPECTRAL_SCAN            0x26
 #define PHY_ERROR_GEN_FALSE_RADAR_EXT          0x24
@@ -4072,6 +4104,13 @@ enum wmi_stats_id {
        WMI_STAT_VDEV_RATE = BIT(5),
 };
 
+enum wmi_10_4_stats_id {
+       WMI_10_4_STAT_PEER              = BIT(0),
+       WMI_10_4_STAT_AP                = BIT(1),
+       WMI_10_4_STAT_INST              = BIT(2),
+       WMI_10_4_STAT_PEER_EXTD         = BIT(3),
+};
+
 struct wlan_inst_rssi_args {
        __le16 cfg_retry_count;
        __le16 retry_count;
@@ -4271,6 +4310,15 @@ struct wmi_10_4_peer_stats {
        __le32 peer_rssi_changed;
 } __packed;
 
+struct wmi_10_4_peer_extd_stats {
+       struct wmi_10_4_peer_stats common;
+       struct wmi_mac_addr peer_macaddr;
+       __le32 inactive_time;
+       __le32 peer_chain_rssi;
+       __le32 rx_duration;
+       __le32 reserved[10];
+} __packed;
+
 struct wmi_10_2_pdev_ext_stats {
        __le32 rx_rssi_comb;
        __le32 rx_rssi[4];
@@ -6116,6 +6164,7 @@ struct wmi_mgmt_rx_ev_arg {
        __le32 phy_mode;
        __le32 buf_len;
        __le32 status; /* %WMI_RX_STATUS_ */
+       struct wmi_mgmt_rx_ext_info ext_info;
 };
 
 struct wmi_ch_info_ev_arg {
@@ -6401,6 +6450,11 @@ struct wmi_pdev_set_adaptive_cca_params {
        __le32 cca_detect_margin;
 } __packed;
 
+enum wmi_host_platform_type {
+       WMI_HOST_PLATFORM_HIGH_PERF,
+       WMI_HOST_PLATFORM_LOW_PERF,
+};
+
 struct ath10k;
 struct ath10k_vif;
 struct ath10k_fw_stats_pdev;
index 803030fd17d3b9203dd74535da40fe1de08284d6..6a2a168567630fdbf8ea47818c3a336876b04df4 100644 (file)
@@ -77,7 +77,7 @@ static const struct pci_device_id ath5k_led_devices[] = {
        /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */
        { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
        /* HP Compaq C700 (nitrousnrg@gmail.com) */
-       { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
+       { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 0) },
        /* LiteOn AR5BXB63 (magooz@salug.it) */
        { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
        /* IBM-specific AR5212 (all others) */
index 0fce1c76638e9c9ae103e01ac6752dced8b1670d..98ee8545632189824d4d4a3fc660d947e6da0f5c 100644 (file)
@@ -1446,7 +1446,7 @@ ath5k_hw_channel(struct ath5k_hw *ah,
                        "channel frequency (%u MHz) out of supported "
                        "band range\n",
                        channel->center_freq);
-                       return -EINVAL;
+               return -EINVAL;
        }
 
        /*
index 99e62f99a182db5c205a7dca60492b4e312f6f84..4b1c87fa15ac2637c3f02645ec2aab8ded74ad34 100644 (file)
@@ -634,7 +634,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah)
                ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
                        AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
                        AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
-                       usleep_range(2000, 2500);
+               usleep_range(2000, 2500);
        } else {
                ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
                        AR5K_RESET_CTL_BASEBAND | bus_flags);
@@ -699,7 +699,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
                ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
                        AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
                        AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
-                       usleep_range(2000, 2500);
+               usleep_range(2000, 2500);
        } else {
                if (ath5k_get_bus_type(ah) == ATH_AHB)
                        ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
index a5e1de75a4a3d1517ef25e9ac77591c8adee31f3..0b3e9c0293e03c9f0f53cbad1faff774b5ac4009 100644 (file)
@@ -1584,6 +1584,11 @@ static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len,
        if (len < sizeof(*ev))
                return -EINVAL;
 
+       if (vif->nw_type != INFRA_NETWORK ||
+           !test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
+                     vif->ar->fw_capabilities))
+               return -EOPNOTSUPP;
+
        if (vif->sme_state != SME_CONNECTED)
                return -ENOTCONN;
 
index c38399bc9aa96e84fce4929319599e1d4db694c7..c07866a2fdf96bb9dd8f77d6bc0f9e8c3e44edfc 100644 (file)
@@ -331,7 +331,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -351,7 +351,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index 0c391997a2f77709cf5f7531dbcdeadc338b4aed..518e649ecff383898288f3f154f9fe7af32897f5 100644 (file)
@@ -1203,12 +1203,12 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
 static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
 {
        int offset[8] = {0}, total = 0, test;
-       int agc_out, i, peak_detect_threshold;
+       int agc_out, i, peak_detect_threshold = 0;
 
        if (AR_SREV_9550(ah) || AR_SREV_9531(ah))
                peak_detect_threshold = 8;
-       else
-               peak_detect_threshold = 0;
+       else if (AR_SREV_9561(ah))
+               peak_detect_threshold = 11;
 
        /*
         * Turn off LNA/SW.
@@ -1249,17 +1249,14 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
                REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
                              AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
 
-       if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
-           AR_SREV_9561(ah)) {
-               if (is_2g)
-                       REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
-                                     AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
-                                     peak_detect_threshold);
-               else
-                       REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
-                                     AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
-                                     peak_detect_threshold);
-       }
+       if (is_2g)
+               REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+                             AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
+                             peak_detect_threshold);
+       else
+               REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
+                             AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
+                             peak_detect_threshold);
 
        for (i = 6; i > 0; i--) {
                offset[i] = BIT(i - 1);
@@ -1311,9 +1308,6 @@ static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah,
        struct ath9k_hw_cal_data *caldata = ah->caldata;
        int i;
 
-       if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
-               return;
-
        if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal)
                return;
 
@@ -1641,14 +1635,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
 
 skip_tx_iqcal:
        if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
-               if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) ||
-                   AR_SREV_9561(ah)) {
-                       for (i = 0; i < AR9300_MAX_CHAINS; i++) {
-                               if (!(ah->rxchainmask & (1 << i)))
-                                       continue;
-                               ar9003_hw_manual_peak_cal(ah, i,
-                                                         IS_CHAN_2GHZ(chan));
-                       }
+               for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+                       if (!(ah->rxchainmask & (1 << i)))
+                               continue;
+
+                       ar9003_hw_manual_peak_cal(ah, i,
+                                                 IS_CHAN_2GHZ(chan));
                }
 
                /*
@@ -1709,7 +1701,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
        struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
        struct ath_hw_ops *ops = ath9k_hw_ops(ah);
 
-       if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah))
+       if (AR_SREV_9003_PCOEM(ah))
                priv_ops->init_cal = ar9003_hw_init_cal_pcoem;
        else
                priv_ops->init_cal = ar9003_hw_init_cal_soc;
index a049f8d34f9964039e62392420ff35d00c312654..f68098284c43be41562b3f126cbe1409134a1868 100644 (file)
@@ -3590,8 +3590,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
                else
                        gpio = AR9300_EXT_LNA_CTL_GPIO_AR9485;
 
-               ath9k_hw_cfg_output(ah, gpio,
-                                   AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
+               ath9k_hw_gpio_request_out(ah, gpio, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
        }
 
        value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
index af5ee416a560dab726805c58850cddfe65291e03..0fe9c8378249ff62ecef303251c29091e0b1c655 100644 (file)
@@ -427,21 +427,34 @@ static void ar9003_mci_observation_set_up(struct ath_hw *ah)
        struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
 
        if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) {
-               ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
-               ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
-               ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
-               ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
+               ath9k_hw_gpio_request_out(ah, 3, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
+               ath9k_hw_gpio_request_out(ah, 2, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
+               ath9k_hw_gpio_request_out(ah, 1, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
+               ath9k_hw_gpio_request_out(ah, 0, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
        } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) {
-               ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
-               ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
-               ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
-               ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
-               ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+               ath9k_hw_gpio_request_out(ah, 3, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
+               ath9k_hw_gpio_request_out(ah, 2, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
+               ath9k_hw_gpio_request_out(ah, 1, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
+               ath9k_hw_gpio_request_out(ah, 0, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
+               ath9k_hw_gpio_request_out(ah, 5, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
        } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) {
-               ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
-               ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
-               ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
-               ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
+               ath9k_hw_gpio_request_out(ah, 3, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
+               ath9k_hw_gpio_request_out(ah, 2, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
+               ath9k_hw_gpio_request_out(ah, 1, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
+               ath9k_hw_gpio_request_out(ah, 0, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
        } else
                return;
 
index 06c1ca6e829053efbd2d8c8620649792324f394d..be14a8e019167b9e21e6b7c98dfab4b9ab52c418 100644 (file)
@@ -1337,11 +1337,11 @@ skip_ws_det:
                                chan->channel,
                                aniState->mrcCCK ? "on" : "off",
                                is_on ? "on" : "off");
-               if (is_on)
-                       ah->stats.ast_ani_ccklow++;
-               else
-                       ah->stats.ast_ani_cckhigh++;
-               aniState->mrcCCK = is_on;
+                       if (is_on)
+                               ah->stats.ast_ani_ccklow++;
+                       else
+                               ah->stats.ast_ani_cckhigh++;
+                       aniState->mrcCCK = is_on;
                }
        break;
        }
index 2c42ff05efa38f507cdd0f54905d8b79c0c77d32..29479afbc4f10fd2da4822bc16bb254d2daadce5 100644 (file)
@@ -40,7 +40,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
-       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -59,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982},
        {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index 2154efcd3900514af944619a174db08d2514a140..c4a6ffa55e8cbb76a5dcc4b00571180137cfd546 100644 (file)
@@ -345,7 +345,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
-       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -364,7 +364,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
        {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index b995ffe88b33bb8af6ca6a7aaa47e23adee34857..2eb163fc1c18f23fb7c7f54056653fcd92c7fabf 100644 (file)
@@ -245,7 +245,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -265,7 +265,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
        {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00041983, 0x00041983, 0x00041982, 0x00041982},
        {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index 1b6b4d0cfa97a5df8c2a7e0d631c417377ba17b2..b00dd649453dfd97080d4c2b5f9e1e33f8e8e996 100644 (file)
@@ -59,7 +59,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c780, 0xcfd5c280},
        {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -79,7 +79,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index dc3adda46e8b92700ee1c274ba734fc2c4ec7a4f..0f8745ec73b1ddabdc223bdc95d24de7de16be29 100644 (file)
@@ -239,7 +239,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c780, 0xcfd5c280},
        {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -259,7 +259,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index ce83ce47a1ca9b7b28dc68e6b414f21236392117..bdf6f107f6f1e25082377e203e0d1a60c046625f 100644 (file)
@@ -1026,7 +1026,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
        {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
        {0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53},
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
        {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
@@ -1044,7 +1044,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
        {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
        {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index c0b90daa3e3d8646f2e064e0f9bbe561d1f5a7d7..924ae6bde7f1200bbeea3b6798b680831fca70da 100644 (file)
@@ -988,7 +988,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946220, 0xcf946220},
        {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -1008,7 +1008,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
        {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
        {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
index 148562addd38fd03e5884ffaa37be7b9503e9c4b..67edf344b4273280f7b3f3a4dd64556647b30bd5 100644 (file)
@@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
        {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
index 10d4a6cb1c3b96730d3056a70aa27124ebd8c5b0..35c1bbb2fa8a273be6594031ad78f4dfec984839 100644 (file)
@@ -347,7 +347,7 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a4, 0x000003a4},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946220, 0xcf946220},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
index c3a47eaaf0c08062da110be5c745495437b57dfc..db051071c6765a466f9c6ab08689d83684f50591 100644 (file)
@@ -220,7 +220,7 @@ static const u32 qca956x_1p0_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a6, 0x000003a6},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946220, 0xcf946220},
        {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
index 5d4629f96c15ab582d359f78105d17fc0258316b..f4c9befb39493da8d80c6be68c945782968196d3 100644 (file)
@@ -1290,7 +1290,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = {
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
        {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
-       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+       {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
        {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
        {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
        {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
@@ -1310,7 +1310,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = {
        {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
        {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
        {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
-       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
        {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982},
        {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
        {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
index 5294595da5a7eb45a63e14a0bbceeae1b2ef343a..93b3793cce2f9a865b5898de8e5a28b6302c6b43 100644 (file)
@@ -813,7 +813,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
 #ifdef CONFIG_MAC80211_LEDS
 void ath_init_leds(struct ath_softc *sc);
 void ath_deinit_leds(struct ath_softc *sc);
-void ath_fill_led_pin(struct ath_softc *sc);
 #else
 static inline void ath_init_leds(struct ath_softc *sc)
 {
@@ -822,9 +821,6 @@ static inline void ath_init_leds(struct ath_softc *sc)
 static inline void ath_deinit_leds(struct ath_softc *sc)
 {
 }
-static inline void ath_fill_led_pin(struct ath_softc *sc)
-{
-}
 #endif
 
 /************************/
index 5a084d94ed90793f22d5964bee6114a63a26f605..618c9df35fc1f30eb4ef1a3f9b4aaaa4b6aaab87 100644 (file)
@@ -15,6 +15,8 @@
  */
 
 #include <linux/export.h>
+#include <linux/types.h>
+#include <linux/ath9k_platform.h>
 #include "hw.h"
 
 enum ath_bt_mode {
@@ -34,6 +36,8 @@ struct ath_btcoex_config {
        u8 bt_priority_time;
        u8 bt_first_slot_time;
        bool bt_hold_rx_clear;
+       u8 wl_active_time;
+       u8 wl_qc_time;
 };
 
 static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX]
@@ -65,31 +69,71 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
                .bt_priority_time = 2,
                .bt_first_slot_time = 5,
                .bt_hold_rx_clear = true,
+               .wl_active_time = 0x20,
+               .wl_qc_time = 0x20,
        };
        bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
+       u8 time_extend = ath_bt_config.bt_time_extend;
+       u8 first_slot_time = ath_bt_config.bt_first_slot_time;
 
        if (AR_SREV_9300_20_OR_LATER(ah))
                rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
 
+       if (AR_SREV_SOC(ah)) {
+               first_slot_time = 0x1d;
+               time_extend = 0xa;
+
+               btcoex_hw->bt_coex_mode3 =
+                       SM(ath_bt_config.wl_active_time, AR_BT_WL_ACTIVE_TIME) |
+                       SM(ath_bt_config.wl_qc_time, AR_BT_WL_QC_TIME);
+
+               btcoex_hw->bt_coex_mode2 =
+                       AR_BT_PROTECT_BT_AFTER_WAKEUP |
+                       AR_BT_PHY_ERR_BT_COLL_ENABLE;
+       }
+
        btcoex_hw->bt_coex_mode =
                (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
-               SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) |
+               SM(time_extend, AR_BT_TIME_EXTEND) |
                SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
                SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
                SM(ath_bt_config.bt_mode, AR_BT_MODE) |
                SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) |
                SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) |
                SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) |
-               SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) |
+               SM(first_slot_time, AR_BT_FIRST_SLOT_TIME) |
                SM(qnum, AR_BT_QCU_THRESH);
 
-       btcoex_hw->bt_coex_mode2 =
+       btcoex_hw->bt_coex_mode2 |=
                SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
                SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
                AR_BT_DISABLE_BT_ANT;
 }
 EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
 
+static void ath9k_hw_btcoex_pin_init(struct ath_hw *ah, u8 wlanactive_gpio,
+                                    u8 btactive_gpio, u8 btpriority_gpio)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+       struct ath9k_platform_data *pdata = ah->dev->platform_data;
+
+       if (btcoex_hw->scheme != ATH_BTCOEX_CFG_2WIRE &&
+           btcoex_hw->scheme != ATH_BTCOEX_CFG_3WIRE)
+               return;
+
+       /* bt priority GPIO will be ignored by 2 wire scheme */
+       if (pdata && (pdata->bt_active_pin || pdata->bt_priority_pin ||
+                     pdata->wlan_active_pin)) {
+               btcoex_hw->btactive_gpio = pdata->bt_active_pin;
+               btcoex_hw->wlanactive_gpio = pdata->wlan_active_pin;
+               btcoex_hw->btpriority_gpio = pdata->bt_priority_pin;
+       } else {
+               btcoex_hw->btactive_gpio = btactive_gpio;
+               btcoex_hw->wlanactive_gpio = wlanactive_gpio;
+               btcoex_hw->btpriority_gpio = btpriority_gpio;
+       }
+}
+
 void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
 {
        struct ath_common *common = ath9k_hw_common(ah);
@@ -107,19 +151,19 @@ void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
                btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI;
        } else if (AR_SREV_9300_20_OR_LATER(ah)) {
                btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
-               btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300;
-               btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300;
-               btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300;
-       } else if (AR_SREV_9280_20_OR_LATER(ah)) {
-               btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280;
-               btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280;
 
-               if (AR_SREV_9285(ah)) {
+               ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9300,
+                                        ATH_BTACTIVE_GPIO_9300,
+                                        ATH_BTPRIORITY_GPIO_9300);
+       } else if (AR_SREV_9280_20_OR_LATER(ah)) {
+               if (AR_SREV_9285(ah))
                        btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
-                       btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9285;
-               } else {
+               else
                        btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE;
-               }
+
+               ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9280,
+                                        ATH_BTACTIVE_GPIO_9280,
+                                        ATH_BTPRIORITY_GPIO_9285);
        }
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_init_scheme);
@@ -137,12 +181,14 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
                    AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
 
        /* Set input mux for bt_active to gpio pin */
-       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
-                     AR_GPIO_INPUT_MUX1_BT_ACTIVE,
-                     btcoex_hw->btactive_gpio);
+       if (!AR_SREV_SOC(ah))
+               REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                             AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+                             btcoex_hw->btactive_gpio);
 
        /* Configure the desired gpio port for input */
-       ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
+       ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio,
+                                "ath9k-btactive");
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire);
 
@@ -157,21 +203,33 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
 
        /* Set input mux for bt_prority_async and
         *                  bt_active_async to GPIO pins */
-       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
-                       AR_GPIO_INPUT_MUX1_BT_ACTIVE,
-                       btcoex_hw->btactive_gpio);
-
-       REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
-                       AR_GPIO_INPUT_MUX1_BT_PRIORITY,
-                       btcoex_hw->btpriority_gpio);
+       if (!AR_SREV_SOC(ah)) {
+               REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                             AR_GPIO_INPUT_MUX1_BT_ACTIVE,
+                             btcoex_hw->btactive_gpio);
+               REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
+                             AR_GPIO_INPUT_MUX1_BT_PRIORITY,
+                             btcoex_hw->btpriority_gpio);
+       }
 
        /* Configure the desired GPIO ports for input */
-
-       ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio);
-       ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio);
+       ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio,
+                                "ath9k-btactive");
+       ath9k_hw_gpio_request_in(ah, btcoex_hw->btpriority_gpio,
+                                "ath9k-btpriority");
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire);
 
+void ath9k_hw_btcoex_deinit(struct ath_hw *ah)
+{
+       struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
+
+       ath9k_hw_gpio_free(ah, btcoex_hw->btactive_gpio);
+       ath9k_hw_gpio_free(ah, btcoex_hw->btpriority_gpio);
+       ath9k_hw_gpio_free(ah, btcoex_hw->wlanactive_gpio);
+}
+EXPORT_SYMBOL(ath9k_hw_btcoex_deinit);
+
 void ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
 {
        ah->btcoex_hw.mci.ready = false;
@@ -201,8 +259,9 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
        struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
 
        /* Configure the desired GPIO port for TX_FRAME output */
-       ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
-                           AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
+       ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio,
+                                 "ath9k-wlanactive",
+                                 AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
 }
 
 /*
@@ -247,13 +306,13 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
                                 txprio_shift[i-1]);
                }
        }
+
        /* Last WLAN weight has to be adjusted wrt tx priority */
        if (concur_tx) {
                btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]);
                btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type]
                                                      << txprio_shift[i-1]);
        }
-
 }
 EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
 
@@ -268,9 +327,14 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
         * Program coex mode and weight registers to
         * enable coex 3-wire
         */
+       if (AR_SREV_SOC(ah))
+               REG_CLR_BIT(ah, AR_BT_COEX_MODE2, AR_BT_PHY_ERR_BT_COLL_ENABLE);
+
        REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode);
        REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
 
+       if (AR_SREV_SOC(ah))
+               REG_WRITE(ah, AR_BT_COEX_MODE3, btcoex->bt_coex_mode3);
 
        if (AR_SREV_9300_20_OR_LATER(ah)) {
                REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]);
@@ -281,8 +345,6 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
        } else
                REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights);
 
-
-
        if (AR_SREV_9271(ah)) {
                val = REG_READ(ah, 0x50040);
                val &= 0xFFFFFEFF;
@@ -292,8 +354,9 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
        REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
        REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
 
-       ath9k_hw_cfg_output(ah, btcoex->wlanactive_gpio,
-                           AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
+       ath9k_hw_gpio_request_out(ah, btcoex->wlanactive_gpio,
+                                 "ath9k-wlanactive",
+                                 AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
 }
 
 static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah)
@@ -339,7 +402,8 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah)
                break;
        }
 
-       if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI) {
+       if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI &&
+           !AR_SREV_SOC(ah)) {
                REG_RMW(ah, AR_GPIO_PDPU,
                        (0x2 << (btcoex_hw->btactive_gpio * 2)),
                        (0x3 << (btcoex_hw->btactive_gpio * 2)));
@@ -364,8 +428,8 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
        if (!AR_SREV_9300_20_OR_LATER(ah))
                ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
 
-       ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
-                       AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio,
+                                 NULL, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 
        if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
                REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
index cd2f0a2373cb92f7eeb47f0fa0ab21e5a78c3a9e..1bdfa8465b9260df85345431d29711793f5722e5 100644 (file)
@@ -115,6 +115,7 @@ struct ath_btcoex_hw {
        u32 bt_coex_mode;       /* Register setting for AR_BT_COEX_MODE */
        u32 bt_coex_weights;    /* Register setting for AR_BT_COEX_WEIGHT */
        u32 bt_coex_mode2;      /* Register setting for AR_BT_COEX_MODE2 */
+       u32 bt_coex_mode3;      /* Register setting for AR_BT_COEX_MODE3 */
        u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
        u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
        u8 tx_prio[ATH_BTCOEX_STOMP_MAX];
@@ -123,6 +124,7 @@ struct ath_btcoex_hw {
 void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
 void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
 void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
+void ath9k_hw_btcoex_deinit(struct ath_hw *ah);
 void ath9k_hw_btcoex_init_mci(struct ath_hw *ah);
 void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum);
 void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
index 6de64cface3c26d3ff4dba5c9b0b99305a8dd348..c56e40ff35e5fafcaa58433ede46bc53de9d4c69 100644 (file)
@@ -916,10 +916,21 @@ static int open_file_regdump(struct inode *inode, struct file *file)
        struct ath_softc *sc = inode->i_private;
        unsigned int len = 0;
        u8 *buf;
-       int i;
+       int i, j = 0;
        unsigned long num_regs, regdump_len, max_reg_offset;
+       const struct reg_hole {
+               u32 start;
+               u32 end;
+       } reg_hole_list[] = {
+               {0x0200, 0x07fc},
+               {0x0c00, 0x0ffc},
+               {0x2000, 0x3ffc},
+               {0x4100, 0x6ffc},
+               {0x705c, 0x7ffc},
+               {0x0000, 0x0000}
+       };
 
-       max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500;
+       max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x8800 : 0xb500;
        num_regs = max_reg_offset / 4 + 1;
        regdump_len = num_regs * REGDUMP_LINE_SIZE + 1;
        buf = vmalloc(regdump_len);
@@ -927,9 +938,16 @@ static int open_file_regdump(struct inode *inode, struct file *file)
                return -ENOMEM;
 
        ath9k_ps_wakeup(sc);
-       for (i = 0; i < num_regs; i++)
+       for (i = 0; i < num_regs; i++) {
+               if (reg_hole_list[j].start == i << 2) {
+                       i = reg_hole_list[j].end >> 2;
+                       j++;
+                       continue;
+               }
+
                len += scnprintf(buf + len, regdump_len - len,
                        "0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2));
+       }
        ath9k_ps_restore(sc);
 
        file->private_data = buf;
index 284706798c71deda9ecc8a400bcff6e26b8999c5..490f74d9ddf0a62c39cdd65b6f053248979f03fe 100644 (file)
 /********************************/
 
 #ifdef CONFIG_MAC80211_LEDS
+
+void ath_fill_led_pin(struct ath_softc *sc)
+{
+       struct ath_hw *ah = sc->sc_ah;
+
+       /* Set default led pin if invalid */
+       if (ah->led_pin < 0) {
+               if (AR_SREV_9287(ah))
+                       ah->led_pin = ATH_LED_PIN_9287;
+               else if (AR_SREV_9485(ah))
+                       ah->led_pin = ATH_LED_PIN_9485;
+               else if (AR_SREV_9300(ah))
+                       ah->led_pin = ATH_LED_PIN_9300;
+               else if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
+                       ah->led_pin = ATH_LED_PIN_9462;
+               else
+                       ah->led_pin = ATH_LED_PIN_DEF;
+       }
+
+       /* Configure gpio for output */
+       ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
+                                 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+
+       /* LED off, active low */
+       ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
+}
+
 static void ath_led_brightness(struct led_classdev *led_cdev,
                               enum led_brightness brightness)
 {
@@ -40,6 +67,8 @@ void ath_deinit_leds(struct ath_softc *sc)
 
        ath_led_brightness(&sc->led_cdev, LED_OFF);
        led_classdev_unregister(&sc->led_cdev);
+
+       ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
 }
 
 void ath_init_leds(struct ath_softc *sc)
@@ -49,6 +78,8 @@ void ath_init_leds(struct ath_softc *sc)
        if (AR_SREV_9100(sc->sc_ah))
                return;
 
+       ath_fill_led_pin(sc);
+
        if (!ath9k_led_blink)
                sc->led_cdev.default_trigger =
                        ieee80211_get_radio_led_name(sc->hw);
@@ -64,37 +95,6 @@ void ath_init_leds(struct ath_softc *sc)
 
        sc->led_registered = true;
 }
-
-void ath_fill_led_pin(struct ath_softc *sc)
-{
-       struct ath_hw *ah = sc->sc_ah;
-
-       if (AR_SREV_9100(ah))
-               return;
-
-       if (ah->led_pin >= 0) {
-               if (!((1 << ah->led_pin) & AR_GPIO_OE_OUT_MASK))
-                       ath9k_hw_request_gpio(ah, ah->led_pin, "ath9k-led");
-               return;
-       }
-
-       if (AR_SREV_9287(ah))
-               ah->led_pin = ATH_LED_PIN_9287;
-       else if (AR_SREV_9485(sc->sc_ah))
-               ah->led_pin = ATH_LED_PIN_9485;
-       else if (AR_SREV_9300(sc->sc_ah))
-               ah->led_pin = ATH_LED_PIN_9300;
-       else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah))
-               ah->led_pin = ATH_LED_PIN_9462;
-       else
-               ah->led_pin = ATH_LED_PIN_DEF;
-
-       /* Configure gpio 1 for output */
-       ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
-
-       /* LED off, active low */
-       ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
-}
 #endif
 
 /*******************/
@@ -402,6 +402,13 @@ void ath9k_deinit_btcoex(struct ath_softc *sc)
 
        if (ath9k_hw_mci_is_enabled(ah))
                ath_mci_cleanup(sc);
+       else {
+               enum ath_btcoex_scheme scheme = ath9k_hw_get_btcoex_scheme(ah);
+
+               if (scheme == ATH_BTCOEX_CFG_2WIRE ||
+                   scheme == ATH_BTCOEX_CFG_3WIRE)
+                       ath9k_hw_btcoex_deinit(sc->sc_ah);
+       }
 }
 
 int ath9k_init_btcoex(struct ath_softc *sc)
index 2aabcbdaba4e15f93cd4f8924c922e480fa8d8dd..ecb848b60725461a2cfd810b25aa226ec74b69c8 100644 (file)
@@ -253,17 +253,19 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
        ath9k_led_brightness(&priv->led_cdev, LED_OFF);
        led_classdev_unregister(&priv->led_cdev);
        cancel_work_sync(&priv->led_work);
+
+       ath9k_hw_gpio_free(priv->ah, priv->ah->led_pin);
 }
 
 
 void ath9k_configure_leds(struct ath9k_htc_priv *priv)
 {
        /* Configure gpio 1 for output */
-       ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin,
-                           AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       ath9k_hw_gpio_request_out(priv->ah, priv->ah->led_pin,
+                                 "ath9k-led",
+                                 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
        /* LED off, active low */
        ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
-
 }
 
 void ath9k_init_leds(struct ath9k_htc_priv *priv)
index 8647ab77c019a30e7b8044b6147a62493626529b..c2249ad54085477f2a60361a9b48767748b3873f 100644 (file)
@@ -262,11 +262,11 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
        __be32 tmpval[8];
        int i, ret;
 
-       for (i = 0; i < count; i++) {
-              tmpaddr[i] = cpu_to_be32(addr[i]);
-       }
+       for (i = 0; i < count; i++) {
+               tmpaddr[i] = cpu_to_be32(addr[i]);
+       }
 
-       ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
+       ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
                           (u8 *)tmpaddr , sizeof(u32) * count,
                           (u8 *)tmpval, sizeof(u32) * count,
                           100);
@@ -275,9 +275,9 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
                        "Multiple REGISTER READ FAILED (count: %d)\n", count);
        }
 
-       for (i = 0; i < count; i++) {
-              val[i] = be32_to_cpu(tmpval[i]);
-       }
+       for (i = 0; i < count; i++) {
+               val[i] = be32_to_cpu(tmpval[i]);
+       }
 }
 
 static void ath9k_regwrite_multi(struct ath_common *common)
index e7a31016f370ade654f6e4fcd05e3adc4595a13e..42009065e234ed3f151597dd8cda060f1be724c6 100644 (file)
@@ -1582,8 +1582,10 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
                if (!(gpio_mask & 1))
                        continue;
 
-               ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+               ath9k_hw_gpio_request_out(ah, i, NULL,
+                                         AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
                ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i)));
+               ath9k_hw_gpio_free(ah, i);
        }
 }
 
@@ -1958,7 +1960,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        ath9k_hw_init_qos(ah);
 
        if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
-               ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
+               ath9k_hw_gpio_request_in(ah, ah->rfkill_gpio, "ath9k-rfkill");
 
        ath9k_hw_init_global_settings(ah);
 
@@ -2385,6 +2387,61 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
        }
 }
 
+static void ath9k_gpio_cap_init(struct ath_hw *ah)
+{
+       struct ath9k_hw_capabilities *pCap = &ah->caps;
+
+       if (AR_SREV_9271(ah)) {
+               pCap->num_gpio_pins = AR9271_NUM_GPIO;
+               pCap->gpio_mask = AR9271_GPIO_MASK;
+       } else if (AR_DEVID_7010(ah)) {
+               pCap->num_gpio_pins = AR7010_NUM_GPIO;
+               pCap->gpio_mask = AR7010_GPIO_MASK;
+       } else if (AR_SREV_9287(ah)) {
+               pCap->num_gpio_pins = AR9287_NUM_GPIO;
+               pCap->gpio_mask = AR9287_GPIO_MASK;
+       } else if (AR_SREV_9285(ah)) {
+               pCap->num_gpio_pins = AR9285_NUM_GPIO;
+               pCap->gpio_mask = AR9285_GPIO_MASK;
+       } else if (AR_SREV_9280(ah)) {
+               pCap->num_gpio_pins = AR9280_NUM_GPIO;
+               pCap->gpio_mask = AR9280_GPIO_MASK;
+       } else if (AR_SREV_9300(ah)) {
+               pCap->num_gpio_pins = AR9300_NUM_GPIO;
+               pCap->gpio_mask = AR9300_GPIO_MASK;
+       } else if (AR_SREV_9330(ah)) {
+               pCap->num_gpio_pins = AR9330_NUM_GPIO;
+               pCap->gpio_mask = AR9330_GPIO_MASK;
+       } else if (AR_SREV_9340(ah)) {
+               pCap->num_gpio_pins = AR9340_NUM_GPIO;
+               pCap->gpio_mask = AR9340_GPIO_MASK;
+       } else if (AR_SREV_9462(ah)) {
+               pCap->num_gpio_pins = AR9462_NUM_GPIO;
+               pCap->gpio_mask = AR9462_GPIO_MASK;
+       } else if (AR_SREV_9485(ah)) {
+               pCap->num_gpio_pins = AR9485_NUM_GPIO;
+               pCap->gpio_mask = AR9485_GPIO_MASK;
+       } else if (AR_SREV_9531(ah)) {
+               pCap->num_gpio_pins = AR9531_NUM_GPIO;
+               pCap->gpio_mask = AR9531_GPIO_MASK;
+       } else if (AR_SREV_9550(ah)) {
+               pCap->num_gpio_pins = AR9550_NUM_GPIO;
+               pCap->gpio_mask = AR9550_GPIO_MASK;
+       } else if (AR_SREV_9561(ah)) {
+               pCap->num_gpio_pins = AR9561_NUM_GPIO;
+               pCap->gpio_mask = AR9561_GPIO_MASK;
+       } else if (AR_SREV_9565(ah)) {
+               pCap->num_gpio_pins = AR9565_NUM_GPIO;
+               pCap->gpio_mask = AR9565_GPIO_MASK;
+       } else if (AR_SREV_9580(ah)) {
+               pCap->num_gpio_pins = AR9580_NUM_GPIO;
+               pCap->gpio_mask = AR9580_GPIO_MASK;
+       } else {
+               pCap->num_gpio_pins = AR_NUM_GPIO;
+               pCap->gpio_mask = AR_GPIO_MASK;
+       }
+}
+
 int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 {
        struct ath9k_hw_capabilities *pCap = &ah->caps;
@@ -2478,20 +2535,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        else
                pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
 
-       if (AR_SREV_9271(ah))
-               pCap->num_gpio_pins = AR9271_NUM_GPIO;
-       else if (AR_DEVID_7010(ah))
-               pCap->num_gpio_pins = AR7010_NUM_GPIO;
-       else if (AR_SREV_9300_20_OR_LATER(ah))
-               pCap->num_gpio_pins = AR9300_NUM_GPIO;
-       else if (AR_SREV_9287_11_OR_LATER(ah))
-               pCap->num_gpio_pins = AR9287_NUM_GPIO;
-       else if (AR_SREV_9285_12_OR_LATER(ah))
-               pCap->num_gpio_pins = AR9285_NUM_GPIO;
-       else if (AR_SREV_9280_20_OR_LATER(ah))
-               pCap->num_gpio_pins = AR928X_NUM_GPIO;
-       else
-               pCap->num_gpio_pins = AR_NUM_GPIO;
+       ath9k_gpio_cap_init(ah);
 
        if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah))
                pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
@@ -2612,8 +2656,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 /* GPIO / RFKILL / Antennae */
 /****************************/
 
-static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
-                                        u32 gpio, u32 type)
+static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, u32 gpio, u32 type)
 {
        int addr;
        u32 gpio_shift, tmp;
@@ -2627,8 +2670,8 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
 
        gpio_shift = (gpio % 6) * 5;
 
-       if (AR_SREV_9280_20_OR_LATER(ah)
-           || (addr != AR_GPIO_OUTPUT_MUX1)) {
+       if (AR_SREV_9280_20_OR_LATER(ah) ||
+           (addr != AR_GPIO_OUTPUT_MUX1)) {
                REG_RMW(ah, addr, (type << gpio_shift),
                        (0x1f << gpio_shift));
        } else {
@@ -2640,106 +2683,144 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
        }
 }
 
-void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
+/* BSP should set the corresponding MUX register correctly.
+ */
+static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
+                                 const char *label)
 {
-       u32 gpio_shift;
+       if (ah->caps.gpio_requested & BIT(gpio))
+               return;
 
-       BUG_ON(gpio >= ah->caps.num_gpio_pins);
+       /* may be requested by BSP, free anyway */
+       gpio_free(gpio);
 
-       if (AR_DEVID_7010(ah)) {
-               gpio_shift = gpio;
-               REG_RMW(ah, AR7010_GPIO_OE,
-                       (AR7010_GPIO_OE_AS_INPUT << gpio_shift),
-                       (AR7010_GPIO_OE_MASK << gpio_shift));
+       if (gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label))
                return;
-       }
 
-       gpio_shift = gpio << 1;
-       REG_RMW(ah,
-               AR_GPIO_OE_OUT,
-               (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
-               (AR_GPIO_OE_OUT_DRV << gpio_shift));
+       ah->caps.gpio_requested |= BIT(gpio);
 }
-EXPORT_SYMBOL(ath9k_hw_cfg_gpio_input);
 
-u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
+static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out,
+                                  u32 ah_signal_type)
 {
-#define MS_REG_READ(x, y) \
-       (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
-
-       if (gpio >= ah->caps.num_gpio_pins)
-               return 0xffffffff;
+       u32 gpio_set, gpio_shift = gpio;
 
        if (AR_DEVID_7010(ah)) {
-               u32 val;
-               val = REG_READ(ah, AR7010_GPIO_IN);
-               return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
-       } else if (AR_SREV_9300_20_OR_LATER(ah))
-               return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) &
-                       AR_GPIO_BIT(gpio)) != 0;
-       else if (AR_SREV_9271(ah))
-               return MS_REG_READ(AR9271, gpio) != 0;
-       else if (AR_SREV_9287_11_OR_LATER(ah))
-               return MS_REG_READ(AR9287, gpio) != 0;
-       else if (AR_SREV_9285_12_OR_LATER(ah))
-               return MS_REG_READ(AR9285, gpio) != 0;
-       else if (AR_SREV_9280_20_OR_LATER(ah))
-               return MS_REG_READ(AR928X, gpio) != 0;
-       else
-               return MS_REG_READ(AR, gpio) != 0;
+               gpio_set = out ?
+                       AR7010_GPIO_OE_AS_OUTPUT : AR7010_GPIO_OE_AS_INPUT;
+               REG_RMW(ah, AR7010_GPIO_OE, gpio_set << gpio_shift,
+                       AR7010_GPIO_OE_MASK << gpio_shift);
+       } else if (AR_SREV_SOC(ah)) {
+               gpio_set = out ? 1 : 0;
+               REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift,
+                       gpio_set << gpio_shift);
+       } else {
+               gpio_shift = gpio << 1;
+               gpio_set = out ?
+                       AR_GPIO_OE_OUT_DRV_ALL : AR_GPIO_OE_OUT_DRV_NO;
+               REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift,
+                       AR_GPIO_OE_OUT_DRV << gpio_shift);
+
+               if (out)
+                       ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+       }
 }
-EXPORT_SYMBOL(ath9k_hw_gpio_get);
 
-void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
-                        u32 ah_signal_type)
+static void ath9k_hw_gpio_request(struct ath_hw *ah, u32 gpio, bool out,
+                                 const char *label, u32 ah_signal_type)
 {
-       u32 gpio_shift;
+       WARN_ON(gpio >= ah->caps.num_gpio_pins);
 
-       if (AR_DEVID_7010(ah)) {
-               gpio_shift = gpio;
-               REG_RMW(ah, AR7010_GPIO_OE,
-                       (AR7010_GPIO_OE_AS_OUTPUT << gpio_shift),
-                       (AR7010_GPIO_OE_MASK << gpio_shift));
-               return;
-       }
+       if (BIT(gpio) & ah->caps.gpio_mask)
+               ath9k_hw_gpio_cfg_wmac(ah, gpio, out, ah_signal_type);
+       else if (AR_SREV_SOC(ah))
+               ath9k_hw_gpio_cfg_soc(ah, gpio, out, label);
+       else
+               WARN_ON(1);
+}
 
-       ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
-       gpio_shift = 2 * gpio;
-       REG_RMW(ah,
-               AR_GPIO_OE_OUT,
-               (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
-               (AR_GPIO_OE_OUT_DRV << gpio_shift));
+void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label)
+{
+       ath9k_hw_gpio_request(ah, gpio, false, label, 0);
 }
-EXPORT_SYMBOL(ath9k_hw_cfg_output);
+EXPORT_SYMBOL(ath9k_hw_gpio_request_in);
 
-void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
+void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label,
+                              u32 ah_signal_type)
 {
-       if (AR_DEVID_7010(ah)) {
-               val = val ? 0 : 1;
-               REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio),
-                       AR_GPIO_BIT(gpio));
+       ath9k_hw_gpio_request(ah, gpio, true, label, ah_signal_type);
+}
+EXPORT_SYMBOL(ath9k_hw_gpio_request_out);
+
+void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio)
+{
+       if (!AR_SREV_SOC(ah))
                return;
+
+       WARN_ON(gpio >= ah->caps.num_gpio_pins);
+
+       if (ah->caps.gpio_requested & BIT(gpio)) {
+               gpio_free(gpio);
+               ah->caps.gpio_requested &= ~BIT(gpio);
        }
+}
+EXPORT_SYMBOL(ath9k_hw_gpio_free);
 
-       if (AR_SREV_9271(ah))
-               val = ~val;
+u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
+{
+       u32 val = 0xffffffff;
 
-       if ((1 << gpio) & AR_GPIO_OE_OUT_MASK)
-               REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
-                       AR_GPIO_BIT(gpio));
-       else
-               gpio_set_value(gpio, val & 1);
+#define MS_REG_READ(x, y) \
+       (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & BIT(y))
+
+       WARN_ON(gpio >= ah->caps.num_gpio_pins);
+
+       if (BIT(gpio) & ah->caps.gpio_mask) {
+               if (AR_SREV_9271(ah))
+                       val = MS_REG_READ(AR9271, gpio);
+               else if (AR_SREV_9287(ah))
+                       val = MS_REG_READ(AR9287, gpio);
+               else if (AR_SREV_9285(ah))
+                       val = MS_REG_READ(AR9285, gpio);
+               else if (AR_SREV_9280(ah))
+                       val = MS_REG_READ(AR928X, gpio);
+               else if (AR_DEVID_7010(ah))
+                       val = REG_READ(ah, AR7010_GPIO_IN) & BIT(gpio);
+               else if (AR_SREV_9300_20_OR_LATER(ah))
+                       val = REG_READ(ah, AR_GPIO_IN) & BIT(gpio);
+               else
+                       val = MS_REG_READ(AR, gpio);
+       } else if (BIT(gpio) & ah->caps.gpio_requested) {
+               val = gpio_get_value(gpio) & BIT(gpio);
+       } else {
+               WARN_ON(1);
+       }
+
+       return val;
 }
-EXPORT_SYMBOL(ath9k_hw_set_gpio);
+EXPORT_SYMBOL(ath9k_hw_gpio_get);
 
-void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label)
+void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
 {
-       if (gpio >= ah->caps.num_gpio_pins)
-               return;
+       WARN_ON(gpio >= ah->caps.num_gpio_pins);
+
+       if (AR_DEVID_7010(ah) || AR_SREV_9271(ah))
+               val = !val;
+       else
+               val = !!val;
 
-       gpio_request_one(gpio, GPIOF_DIR_OUT | GPIOF_INIT_LOW, label);
+       if (BIT(gpio) & ah->caps.gpio_mask) {
+               u32 out_addr = AR_DEVID_7010(ah) ?
+                       AR7010_GPIO_OUT : AR_GPIO_IN_OUT;
+
+               REG_RMW(ah, out_addr, val << gpio, BIT(gpio));
+       } else if (BIT(gpio) & ah->caps.gpio_requested) {
+               gpio_set_value(gpio, val);
+       } else {
+               WARN_ON(1);
+       }
 }
-EXPORT_SYMBOL(ath9k_hw_request_gpio);
+EXPORT_SYMBOL(ath9k_hw_set_gpio);
 
 void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
 {
index 831a54415a2512fe890832dcd6ec688d160b1a7c..9cbca1229bac02862211c14d14048f08197dd39d 100644 (file)
 #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA        0x1e
 
 #define AR_GPIOD_MASK               0x00001FFF
-#define AR_GPIO_BIT(_gpio)          (1 << (_gpio))
 
 #define BASE_ACTIVATE_DELAY         100
 #define RTC_PLL_SETTLE_DELAY        (AR_SREV_9340(ah) ? 1000 : 100)
@@ -301,6 +300,8 @@ struct ath9k_hw_capabilities {
        u8 max_txchains;
        u8 max_rxchains;
        u8 num_gpio_pins;
+       u32 gpio_mask;
+       u32 gpio_requested;
        u8 rx_hp_qdepth;
        u8 rx_lp_qdepth;
        u8 rx_status_len;
@@ -1019,12 +1020,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah);
 u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
 
 /* GPIO / RFKILL / Antennae */
-void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);
+void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label);
+void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label,
+                              u32 ah_signal_type);
+void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio);
 u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
-void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
-                        u32 ah_signal_type);
 void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
-void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label);
 void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
 
 /* General Operation */
index 1c226d63bb0362d44e3420758909592f08287a12..77ace8d72d5400429ac14242ab51a23568d567fb 100644 (file)
@@ -660,7 +660,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
 
        ath9k_cmn_init_crypto(sc->sc_ah);
        ath9k_init_misc(sc);
-       ath_fill_led_pin(sc);
        ath_chanctx_init(sc);
        ath9k_offchannel_init(sc);
 
index 3aed43a63f946d0fa2d218b15f4621be2ad49977..50ec4c9a9da772fb8e7614d26e951388c938d0a3 100644 (file)
@@ -718,12 +718,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
        if (!ath_complete_reset(sc, false))
                ah->reset_power_on = false;
 
-       if (ah->led_pin >= 0) {
-               ath9k_hw_cfg_output(ah, ah->led_pin,
-                                   AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
+       if (ah->led_pin >= 0)
                ath9k_hw_set_gpio(ah, ah->led_pin,
                                  (ah->config.led_active_high) ? 1 : 0);
-       }
 
        /*
         * Reset key cache to sane defaults (all entries cleared) instead of
@@ -867,11 +864,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        spin_lock_bh(&sc->sc_pcu_lock);
 
-       if (ah->led_pin >= 0) {
+       if (ah->led_pin >= 0)
                ath9k_hw_set_gpio(ah, ah->led_pin,
                                  (ah->config.led_active_high) ? 0 : 1);
-               ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
-       }
 
        ath_prepare_reset(sc);
 
index c8d35febaf0f7e7ffb2bdc462f2987ab5f1a3896..9272ca90632b983b5eec1a57612ac29307f15973 100644 (file)
 #define AR_SREV_9561(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9561))
 
+#define AR_SREV_SOC(_ah) \
+       (AR_SREV_9340(_ah) || AR_SREV_9531(_ah) || AR_SREV_9550(ah) || \
+        AR_SREV_9561(ah))
+
 /* NOTE: When adding chips newer than Peacock, add chip check here */
 #define AR_SREV_9580_10_OR_LATER(_ah) \
        (AR_SREV_9580(_ah))
@@ -1104,14 +1108,46 @@ enum {
 
 #define AR_PCIE_PHY_REG3                        0x18c08
 
+/* Define correct GPIO numbers and MASK bits to indicate the WMAC
+ * GPIO resource.
+ * Allow SOC chips(AR9340, AR9531, AR9550, AR9561) to access all GPIOs
+ * which rely on gpiolib framework. But restrict SOC AR9330 only to
+ * access WMAC GPIO which has the same design with the old chips.
+ */
 #define AR_NUM_GPIO                              14
-#define AR928X_NUM_GPIO                          10
+#define AR9280_NUM_GPIO                          10
 #define AR9285_NUM_GPIO                          12
-#define AR9287_NUM_GPIO                          11
+#define AR9287_NUM_GPIO                          10
 #define AR9271_NUM_GPIO                          16
-#define AR9300_NUM_GPIO                          17
+#define AR9300_NUM_GPIO                          16
+#define AR9330_NUM_GPIO                                 16
+#define AR9340_NUM_GPIO                                 23
+#define AR9462_NUM_GPIO                                 10
+#define AR9485_NUM_GPIO                                 12
+#define AR9531_NUM_GPIO                                 18
+#define AR9550_NUM_GPIO                                 24
+#define AR9561_NUM_GPIO                                 23
+#define AR9565_NUM_GPIO                                 12
+#define AR9580_NUM_GPIO                                 16
 #define AR7010_NUM_GPIO                          16
 
+#define AR_GPIO_MASK                            0x00003FFF
+#define AR9271_GPIO_MASK                        0x0000FFFF
+#define AR9280_GPIO_MASK                        0x000003FF
+#define AR9285_GPIO_MASK                        0x00000FFF
+#define AR9287_GPIO_MASK                        0x000003FF
+#define AR9300_GPIO_MASK                        0x0000F4FF
+#define AR9330_GPIO_MASK                        0x0000F4FF
+#define AR9340_GPIO_MASK                        0x0000000F
+#define AR9462_GPIO_MASK                        0x000003FF
+#define AR9485_GPIO_MASK                        0x00000FFF
+#define AR9531_GPIO_MASK                        0x0000000F
+#define AR9550_GPIO_MASK                        0x0000000F
+#define AR9561_GPIO_MASK                        0x0000000F
+#define AR9565_GPIO_MASK                        0x00000FFF
+#define AR9580_GPIO_MASK                        0x0000F4FF
+#define AR7010_GPIO_MASK                        0x0000FFFF
+
 #define AR_GPIO_IN_OUT                           (AR_SREV_9340(ah) ? 0x4028 : 0x4048)
 #define AR_GPIO_IN_VAL                           0x0FFFC000
 #define AR_GPIO_IN_VAL_S                         14
@@ -1132,8 +1168,6 @@ enum {
 
 #define AR_GPIO_OE_OUT                           (AR_SREV_9340(ah) ? 0x4030 : \
                                                  (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c))
-#define AR_GPIO_OE_OUT_MASK                     (AR_SREV_9550_OR_LATER(ah) ? \
-                                                 0x0000000F : 0xFFFFFFFF)
 #define AR_GPIO_OE_OUT_DRV                       0x3
 #define AR_GPIO_OE_OUT_DRV_NO                    0x0
 #define AR_GPIO_OE_OUT_DRV_LOW                   0x1
@@ -1858,15 +1892,33 @@ enum {
 
 #define AR9300_BT_WGHT             0xcccc4444
 
-#define AR_BT_COEX_MODE2           0x817c
-#define AR_BT_BCN_MISS_THRESH      0x000000ff
-#define AR_BT_BCN_MISS_THRESH_S    0
-#define AR_BT_BCN_MISS_CNT         0x0000ff00
-#define AR_BT_BCN_MISS_CNT_S       8
-#define AR_BT_HOLD_RX_CLEAR        0x00010000
-#define AR_BT_HOLD_RX_CLEAR_S      16
-#define AR_BT_DISABLE_BT_ANT       0x00100000
-#define AR_BT_DISABLE_BT_ANT_S     20
+#define AR_BT_COEX_MODE2               0x817c
+#define AR_BT_BCN_MISS_THRESH          0x000000ff
+#define AR_BT_BCN_MISS_THRESH_S                0
+#define AR_BT_BCN_MISS_CNT             0x0000ff00
+#define AR_BT_BCN_MISS_CNT_S           8
+#define AR_BT_HOLD_RX_CLEAR            0x00010000
+#define AR_BT_HOLD_RX_CLEAR_S          16
+#define AR_BT_PROTECT_BT_AFTER_WAKEUP  0x00080000
+#define AR_BT_PROTECT_BT_AFTER_WAKEUP_S 19
+#define AR_BT_DISABLE_BT_ANT           0x00100000
+#define AR_BT_DISABLE_BT_ANT_S         20
+#define AR_BT_QUIET_2_WIRE             0x00200000
+#define AR_BT_QUIET_2_WIRE_S           21
+#define AR_BT_WL_ACTIVE_MODE           0x00c00000
+#define AR_BT_WL_ACTIVE_MODE_S         22
+#define AR_BT_WL_TXRX_SEPARATE         0x01000000
+#define AR_BT_WL_TXRX_SEPARATE_S       24
+#define AR_BT_RS_DISCARD_EXTEND                0x02000000
+#define AR_BT_RS_DISCARD_EXTEND_S      25
+#define AR_BT_TSF_BT_ACTIVE_CTRL       0x0c000000
+#define AR_BT_TSF_BT_ACTIVE_CTRL_S     26
+#define AR_BT_TSF_BT_PRIORITY_CTRL     0x30000000
+#define AR_BT_TSF_BT_PRIORITY_CTRL_S   28
+#define AR_BT_INTERRUPT_ENABLE         0x40000000
+#define AR_BT_INTERRUPT_ENABLE_S       30
+#define AR_BT_PHY_ERR_BT_COLL_ENABLE   0x80000000
+#define AR_BT_PHY_ERR_BT_COLL_ENABLE_S 31
 
 #define AR_TXSIFS              0x81d0
 #define AR_TXSIFS_TIME         0x000000FF
@@ -1875,6 +1927,16 @@ enum {
 #define AR_TXSIFS_ACK_SHIFT    0x00007000
 #define AR_TXSIFS_ACK_SHIFT_S  12
 
+#define AR_BT_COEX_MODE3                       0x81d4
+#define AR_BT_WL_ACTIVE_TIME                   0x000000ff
+#define AR_BT_WL_ACTIVE_TIME_S                 0
+#define AR_BT_WL_QC_TIME                       0x0000ff00
+#define AR_BT_WL_QC_TIME_S                     8
+#define AR_BT_ALLOW_CONCURRENT_ACCESS          0x000f0000
+#define AR_BT_ALLOW_CONCURRENT_ACCESS_S                16
+#define AR_BT_AGC_SATURATION_CNT_ENABLE                0x00100000
+#define AR_BT_AGC_SATURATION_CNT_ENABLE_S      20
+
 #define AR_TXOP_X          0x81ec
 #define AR_TXOP_X_VAL      0x000000FF
 
index c9cb2aad7b6f7ea95a87bc385b9e49c0eb9615f1..d38e50f96db77b52eeab1238093bffea45ec6b5e 100644 (file)
@@ -55,11 +55,26 @@ static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size)
        return j << 2;
 }
 
+static u32 ath9k_rng_delay_get(u32 fail_stats)
+{
+       u32 delay;
+
+       if (fail_stats < 100)
+               delay = 10;
+       else if (fail_stats < 105)
+               delay = 1000;
+       else
+               delay = 10000;
+
+       return delay;
+}
+
 static int ath9k_rng_kthread(void *data)
 {
        int bytes_read;
        struct ath_softc *sc = data;
        u32 *rng_buf;
+       u32 delay, fail_stats = 0;
 
        rng_buf = kmalloc_array(ATH9K_RNG_BUF_SIZE, sizeof(u32), GFP_KERNEL);
        if (!rng_buf)
@@ -69,10 +84,13 @@ static int ath9k_rng_kthread(void *data)
                bytes_read = ath9k_rng_data_read(sc, rng_buf,
                                                 ATH9K_RNG_BUF_SIZE);
                if (unlikely(!bytes_read)) {
-                       msleep_interruptible(10);
+                       delay = ath9k_rng_delay_get(++fail_stats);
+                       msleep_interruptible(delay);
                        continue;
                }
 
+               fail_stats = 0;
+
                /* sleep until entropy bits under write_wakeup_threshold */
                add_hwgenerator_randomness((void *)rng_buf, bytes_read,
                                           ATH9K_RNG_ENTROPY(bytes_read));
index fdf63d5fe82bfcd12592b8b716bf7716459cf92b..11b544b26c748a71262f162713dc888a89547318 100644 (file)
@@ -18,6 +18,7 @@ wil6210-$(CONFIG_WIL6210_TRACING) += trace.o
 wil6210-y += wil_platform.o
 wil6210-y += ethtool.o
 wil6210-y += wil_crash_dump.o
+wil6210-y += p2p.o
 
 # for tracing framework to find trace.h
 CFLAGS_trace.o := -I$(src)
index 11f1bb8dfebebf95a089b015702bb9bcf72072c1..12cae3c005fbadd7f637325264ac172de4f9e019 100644 (file)
@@ -18,6 +18,8 @@
 #include "wil6210.h"
 #include "wmi.h"
 
+#define WIL_MAX_ROC_DURATION_MS 5000
+
 #define CHAN60G(_channel, _flags) {                            \
        .band                   = IEEE80211_BAND_60GHZ,         \
        .center_freq            = 56160 + (2160 * (_channel)),  \
@@ -76,12 +78,24 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
        },
+       [NL80211_IFTYPE_P2P_DEVICE] = {
+               .tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+       },
 };
 
 static const u32 wil_cipher_suites[] = {
        WLAN_CIPHER_SUITE_GCMP,
 };
 
+static const char * const key_usage_str[] = {
+       [WMI_KEY_USE_PAIRWISE]  = "PTK",
+       [WMI_KEY_USE_RX_GROUP]  = "RX_GTK",
+       [WMI_KEY_USE_TX_GROUP]  = "TX_GTK",
+};
+
 int wil_iftype_nl2wmi(enum nl80211_iftype type)
 {
        static const struct {
@@ -113,7 +127,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
                .interval_usec = 0,
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_notify_req_done_event evt;
        } __packed reply;
        struct wil_net_stats *stats = &wil->sta[cid].stats;
@@ -226,13 +240,82 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy,
        return rc;
 }
 
+static struct wireless_dev *
+wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name,
+                      unsigned char name_assign_type,
+                      enum nl80211_iftype type,
+                      u32 *flags, struct vif_params *params)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+       struct net_device *ndev = wil_to_ndev(wil);
+       struct wireless_dev *p2p_wdev;
+
+       wil_dbg_misc(wil, "%s()\n", __func__);
+
+       if (type != NL80211_IFTYPE_P2P_DEVICE) {
+               wil_err(wil, "%s: unsupported iftype %d\n", __func__, type);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (wil->p2p_wdev) {
+               wil_err(wil, "%s: P2P_DEVICE interface already created\n",
+                       __func__);
+               return ERR_PTR(-EINVAL);
+       }
+
+       p2p_wdev = kzalloc(sizeof(*p2p_wdev), GFP_KERNEL);
+       if (!p2p_wdev)
+               return ERR_PTR(-ENOMEM);
+
+       p2p_wdev->iftype = type;
+       p2p_wdev->wiphy = wiphy;
+       /* use our primary ethernet address */
+       ether_addr_copy(p2p_wdev->address, ndev->perm_addr);
+
+       wil->p2p_wdev = p2p_wdev;
+
+       return p2p_wdev;
+}
+
+static int wil_cfg80211_del_iface(struct wiphy *wiphy,
+                                 struct wireless_dev *wdev)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       wil_dbg_misc(wil, "%s()\n", __func__);
+
+       if (wdev != wil->p2p_wdev) {
+               wil_err(wil, "%s: delete of incorrect interface 0x%p\n",
+                       __func__, wdev);
+               return -EINVAL;
+       }
+
+       wil_p2p_wdev_free(wil);
+
+       return 0;
+}
+
 static int wil_cfg80211_change_iface(struct wiphy *wiphy,
                                     struct net_device *ndev,
                                     enum nl80211_iftype type, u32 *flags,
                                     struct vif_params *params)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-       struct wireless_dev *wdev = wil->wdev;
+       struct wireless_dev *wdev = wil_to_wdev(wil);
+       int rc;
+
+       wil_dbg_misc(wil, "%s() type=%d\n", __func__, type);
+
+       if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) {
+               wil_dbg_misc(wil, "interface is up. resetting...\n");
+               mutex_lock(&wil->mutex);
+               __wil_down(wil);
+               rc = __wil_up(wil);
+               mutex_unlock(&wil->mutex);
+
+               if (rc)
+                       return rc;
+       }
 
        switch (type) {
        case NL80211_IFTYPE_STATION:
@@ -260,7 +343,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
                             struct cfg80211_scan_request *request)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-       struct wireless_dev *wdev = wil->wdev;
+       struct wireless_dev *wdev = request->wdev;
        struct {
                struct wmi_start_scan_cmd cmd;
                u16 chnl[4];
@@ -268,6 +351,9 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
        uint i, n;
        int rc;
 
+       wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n",
+                    __func__, wdev, wdev->iftype);
+
        if (wil->scan_request) {
                wil_err(wil, "Already scanning\n");
                return -EAGAIN;
@@ -277,6 +363,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
        switch (wdev->iftype) {
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_P2P_DEVICE:
                break;
        default:
                return -EOPNOTSUPP;
@@ -288,6 +375,20 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
                return -EBUSY;
        }
 
+       /* scan on P2P_DEVICE is handled as p2p search */
+       if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
+               wil->scan_request = request;
+               wil->radio_wdev = wdev;
+               rc = wil_p2p_search(wil, request);
+               if (rc) {
+                       wil->radio_wdev = wil_to_wdev(wil);
+                       wil->scan_request = NULL;
+               }
+               return rc;
+       }
+
+       (void)wil_p2p_stop_discovery(wil);
+
        wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
        wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
 
@@ -313,6 +414,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
        mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
 
        memset(&cmd, 0, sizeof(cmd));
+       cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
        cmd.cmd.num_channels = 0;
        n = min(request->n_channels, 4U);
        for (i = 0; i < n; i++) {
@@ -340,12 +442,19 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
        if (rc)
                goto out;
 
+       if (wil->discovery_mode && cmd.cmd.scan_type == WMI_ACTIVE_SCAN) {
+               cmd.cmd.discovery_mode = 1;
+               wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
+       }
+
+       wil->radio_wdev = wdev;
        rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
                        cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
 
 out:
        if (rc) {
                del_timer_sync(&wil->scan_timer);
+               wil->radio_wdev = wil_to_wdev(wil);
                wil->scan_request = NULL;
        }
 
@@ -390,6 +499,7 @@ static void wil_print_connect_params(struct wil6210_priv *wil,
                print_hex_dump(KERN_INFO, "  SSID: ", DUMP_PREFIX_OFFSET,
                               16, 1, sme->ssid, sme->ssid_len, true);
        wil_info(wil, "  Privacy: %s\n", sme->privacy ? "secure" : "open");
+       wil_info(wil, "  PBSS: %d\n", sme->pbss);
        wil_print_crypto(wil, &sme->crypto);
 }
 
@@ -404,7 +514,9 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
        const u8 *rsn_eid;
        int ch;
        int rc = 0;
+       enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;
 
+       wil_dbg_misc(wil, "%s()\n", __func__);
        wil_print_connect_params(wil, sme);
 
        if (test_bit(wil_status_fwconnecting, wil->status) ||
@@ -422,14 +534,12 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
        if (sme->privacy && !rsn_eid)
                wil_info(wil, "WSC connection\n");
 
-       if (sme->pbss) {
-               wil_err(wil, "connect - PBSS not yet supported\n");
-               return -EOPNOTSUPP;
-       }
+       if (sme->pbss)
+               bss_type = IEEE80211_BSS_TYPE_PBSS;
 
        bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
                               sme->ssid, sme->ssid_len,
-                              IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
+                              bss_type, IEEE80211_PRIVACY_ANY);
        if (!bss) {
                wil_err(wil, "Unable to find BSS\n");
                return -ENOENT;
@@ -568,10 +678,20 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        struct ieee80211_mgmt *mgmt_frame = (void *)buf;
        struct wmi_sw_tx_req_cmd *cmd;
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_sw_tx_complete_event evt;
        } __packed evt;
 
+       /* Note, currently we do not support the "wait" parameter, user-space
+        * must call remain_on_channel before mgmt_tx or listen on a channel
+        * another way (AP/PCP or connected station)
+        * in addition we need to check if specified "chan" argument is
+        * different from currently "listened" channel and fail if it is.
+        */
+
+       wil_dbg_misc(wil, "%s()\n", __func__);
+       print_hex_dump_bytes("mgmt tx frame ", DUMP_PREFIX_OFFSET, buf, len);
+
        cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL);
        if (!cmd) {
                rc = -ENOMEM;
@@ -598,7 +718,7 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
                                    struct cfg80211_chan_def *chandef)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-       struct wireless_dev *wdev = wil->wdev;
+       struct wireless_dev *wdev = wil_to_wdev(wil);
 
        wdev->preset_chandef = *chandef;
 
@@ -608,22 +728,19 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
 static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
                                               bool pairwise)
 {
-       struct wireless_dev *wdev = wil->wdev;
+       struct wireless_dev *wdev = wil_to_wdev(wil);
        enum wmi_key_usage rc;
-       static const char * const key_usage_str[] = {
-               [WMI_KEY_USE_PAIRWISE]  = "WMI_KEY_USE_PAIRWISE",
-               [WMI_KEY_USE_RX_GROUP]  = "WMI_KEY_USE_RX_GROUP",
-               [WMI_KEY_USE_TX_GROUP]  = "WMI_KEY_USE_TX_GROUP",
-       };
 
        if (pairwise) {
                rc = WMI_KEY_USE_PAIRWISE;
        } else {
                switch (wdev->iftype) {
                case NL80211_IFTYPE_STATION:
+               case NL80211_IFTYPE_P2P_CLIENT:
                        rc = WMI_KEY_USE_RX_GROUP;
                        break;
                case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_P2P_GO:
                        rc = WMI_KEY_USE_TX_GROUP;
                        break;
                default:
@@ -638,20 +755,86 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
        return rc;
 }
 
+static struct wil_tid_crypto_rx_single *
+wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
+                   enum wmi_key_usage key_usage, const u8 *mac_addr)
+{
+       int cid = -EINVAL;
+       int tid = 0;
+       struct wil_sta_info *s;
+       struct wil_tid_crypto_rx *c;
+
+       if (key_usage == WMI_KEY_USE_TX_GROUP)
+               return NULL; /* not needed */
+
+       /* supplicant provides Rx group key in STA mode with NULL MAC address */
+       if (mac_addr)
+               cid = wil_find_cid(wil, mac_addr);
+       else if (key_usage == WMI_KEY_USE_RX_GROUP)
+               cid = wil_find_cid_by_idx(wil, 0);
+       if (cid < 0) {
+               wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr,
+                       key_usage_str[key_usage], key_index);
+               return ERR_PTR(cid);
+       }
+
+       s = &wil->sta[cid];
+       if (key_usage == WMI_KEY_USE_PAIRWISE)
+               c = &s->tid_crypto_rx[tid];
+       else
+               c = &s->group_crypto_rx;
+
+       return &c->key_id[key_index];
+}
+
 static int wil_cfg80211_add_key(struct wiphy *wiphy,
                                struct net_device *ndev,
                                u8 key_index, bool pairwise,
                                const u8 *mac_addr,
                                struct key_params *params)
 {
+       int rc;
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
        enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
+       struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
+                                                                 key_index,
+                                                                 key_usage,
+                                                                 mac_addr);
+
+       wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__,
+                    mac_addr, key_usage_str[key_usage], key_index,
+                    params->seq_len, params->seq);
+
+       if (IS_ERR(cc)) {
+               wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n",
+                       __func__, mac_addr, key_usage_str[key_usage], key_index,
+                       params->seq_len, params->seq);
+               return -EINVAL;
+       }
 
-       wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index,
-                    pairwise ? "PTK" : "GTK");
+       if (cc)
+               cc->key_set = false;
+
+       if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
+               wil_err(wil,
+                       "Wrong PN len %d, %s(%pM %s[%d] PN %*phN)\n",
+                       params->seq_len, __func__, mac_addr,
+                       key_usage_str[key_usage], key_index,
+                       params->seq_len, params->seq);
+               return -EINVAL;
+       }
+
+       rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
+                               params->key, key_usage);
+       if ((rc == 0) && cc) {
+               if (params->seq)
+                       memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
+               else
+                       memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
+               cc->key_set = true;
+       }
 
-       return wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
-                                 params->key, key_usage);
+       return rc;
 }
 
 static int wil_cfg80211_del_key(struct wiphy *wiphy,
@@ -661,9 +844,20 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
        enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
+       struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
+                                                                 key_index,
+                                                                 key_usage,
+                                                                 mac_addr);
+
+       wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr,
+                    key_usage_str[key_usage], key_index);
+
+       if (IS_ERR(cc))
+               wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__,
+                        mac_addr, key_usage_str[key_usage], key_index);
 
-       wil_dbg_misc(wil, "%s(%pM[%d] %s)\n", __func__, mac_addr, key_index,
-                    pairwise ? "PTK" : "GTK");
+       if (!IS_ERR_OR_NULL(cc))
+               cc->key_set = false;
 
        return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
 }
@@ -674,6 +868,9 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
                                        u8 key_index, bool unicast,
                                        bool multicast)
 {
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       wil_dbg_misc(wil, "%s: entered\n", __func__);
        return 0;
 }
 
@@ -686,16 +883,19 @@ static int wil_remain_on_channel(struct wiphy *wiphy,
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
        int rc;
 
-       /* TODO: handle duration */
-       wil_info(wil, "%s(%d, %d ms)\n", __func__, chan->center_freq, duration);
+       wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n",
+                    __func__, chan->center_freq, duration, wdev->iftype);
 
-       rc = wmi_set_channel(wil, chan->hw_value);
+       rc = wil_p2p_listen(wil, duration, chan, cookie);
        if (rc)
                return rc;
 
-       rc = wmi_rxon(wil, true);
+       wil->radio_wdev = wdev;
 
-       return rc;
+       cfg80211_ready_on_channel(wdev, *cookie, chan, duration,
+                                 GFP_KERNEL);
+
+       return 0;
 }
 
 static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
@@ -703,13 +903,10 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
                                        u64 cookie)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-       int rc;
-
-       wil_info(wil, "%s()\n", __func__);
 
-       rc = wmi_rxon(wil, false);
+       wil_dbg_misc(wil, "%s()\n", __func__);
 
-       return rc;
+       return wil_p2p_cancel_listen(wil, cookie);
 }
 
 /**
@@ -852,12 +1049,22 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
                                  const u8 *ssid, size_t ssid_len, u32 privacy,
                                  int bi, u8 chan,
                                  struct cfg80211_beacon_data *bcon,
-                                 u8 hidden_ssid)
+                                 u8 hidden_ssid, u32 pbss)
 {
        struct wil6210_priv *wil = wiphy_to_wil(wiphy);
        int rc;
        struct wireless_dev *wdev = ndev->ieee80211_ptr;
        u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+       u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
+
+       if (pbss)
+               wmi_nettype = WMI_NETTYPE_P2P;
+
+       wil_dbg_misc(wil, "%s: is_go=%d\n", __func__, is_go);
+       if (is_go && !pbss) {
+               wil_err(wil, "%s: P2P GO must be in PBSS\n", __func__);
+               return -ENOTSUPP;
+       }
 
        wil_set_recovery_state(wil, fw_recovery_idle);
 
@@ -879,10 +1086,11 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
        wil->privacy = privacy;
        wil->channel = chan;
        wil->hidden_ssid = hidden_ssid;
+       wil->pbss = pbss;
 
        netif_carrier_on(ndev);
 
-       rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid);
+       rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
        if (rc)
                goto err_pcp_start;
 
@@ -928,7 +1136,8 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
                                            wdev->ssid_len, privacy,
                                            wdev->beacon_interval,
                                            wil->channel, bcon,
-                                           wil->hidden_ssid);
+                                           wil->hidden_ssid,
+                                           wil->pbss);
        } else {
                rc = _wil_cfg80211_set_ies(wiphy, bcon);
        }
@@ -954,11 +1163,6 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                return -EINVAL;
        }
 
-       if (info->pbss) {
-               wil_err(wil, "AP: PBSS not yet supported\n");
-               return -EOPNOTSUPP;
-       }
-
        switch (info->hidden_ssid) {
        case NL80211_HIDDEN_SSID_NOT_IN_USE:
                hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
@@ -984,6 +1188,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                     info->hidden_ssid);
        wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
                     info->dtim_period);
+       wil_dbg_misc(wil, "PBSS %d\n", info->pbss);
        print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
                             info->ssid, info->ssid_len);
        wil_print_bcon_data(bcon);
@@ -992,7 +1197,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
        rc = _wil_cfg80211_start_ap(wiphy, ndev,
                                    info->ssid, info->ssid_len, info->privacy,
                                    info->beacon_interval, channel->hw_value,
-                                   bcon, hidden_ssid);
+                                   bcon, hidden_ssid, info->pbss);
 
        return rc;
 }
@@ -1139,7 +1344,26 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy,
        return 0;
 }
 
+static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
+                                        struct wireless_dev *wdev)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       wil_dbg_misc(wil, "%s: entered\n", __func__);
+       return 0;
+}
+
+static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
+                                        struct wireless_dev *wdev)
+{
+       struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+       wil_dbg_misc(wil, "%s: entered\n", __func__);
+}
+
 static struct cfg80211_ops wil_cfg80211_ops = {
+       .add_virtual_intf = wil_cfg80211_add_iface,
+       .del_virtual_intf = wil_cfg80211_del_iface,
        .scan = wil_cfg80211_scan,
        .connect = wil_cfg80211_connect,
        .disconnect = wil_cfg80211_disconnect,
@@ -1160,20 +1384,25 @@ static struct cfg80211_ops wil_cfg80211_ops = {
        .del_station = wil_cfg80211_del_station,
        .probe_client = wil_cfg80211_probe_client,
        .change_bss = wil_cfg80211_change_bss,
+       /* P2P device */
+       .start_p2p_device = wil_cfg80211_start_p2p_device,
+       .stop_p2p_device = wil_cfg80211_stop_p2p_device,
 };
 
 static void wil_wiphy_init(struct wiphy *wiphy)
 {
        wiphy->max_scan_ssids = 1;
        wiphy->max_scan_ie_len = WMI_MAX_IE_LEN;
+       wiphy->max_remain_on_channel_duration = WIL_MAX_ROC_DURATION_MS;
        wiphy->max_num_pmkids = 0 /* TODO: */;
        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
                                 BIT(NL80211_IFTYPE_AP) |
+                                BIT(NL80211_IFTYPE_P2P_CLIENT) |
+                                BIT(NL80211_IFTYPE_P2P_GO) |
+                                BIT(NL80211_IFTYPE_P2P_DEVICE) |
                                 BIT(NL80211_IFTYPE_MONITOR);
-       /* TODO: enable P2P when integrated with supplicant:
-        * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)
-        */
        wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+                       WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
        dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
                __func__, wiphy->flags);
@@ -1241,3 +1470,18 @@ void wil_wdev_free(struct wil6210_priv *wil)
        wiphy_free(wdev->wiphy);
        kfree(wdev);
 }
+
+void wil_p2p_wdev_free(struct wil6210_priv *wil)
+{
+       struct wireless_dev *p2p_wdev;
+
+       mutex_lock(&wil->p2p_wdev_mutex);
+       p2p_wdev = wil->p2p_wdev;
+       if (p2p_wdev) {
+               wil->p2p_wdev = NULL;
+               wil->radio_wdev = wil_to_wdev(wil);
+               cfg80211_unregister_wdev(p2p_wdev);
+               kfree(p2p_wdev);
+       }
+       mutex_unlock(&wil->p2p_wdev_mutex);
+}
index 3bbe73b6d05a9caebe7d867d792501c70336cbbd..b338a09175ad5788aeae709e4223c4d57a4256fb 100644 (file)
@@ -37,6 +37,7 @@ enum dbg_off_type {
        doff_x32 = 1,
        doff_ulong = 2,
        doff_io32 = 3,
+       doff_u8 = 4
 };
 
 /* offset to "wil" */
@@ -346,6 +347,10 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil,
                                                         tbl[i].mode, dbg,
                                                         base + tbl[i].off);
                        break;
+               case doff_u8:
+                       f = debugfs_create_u8(tbl[i].name, tbl[i].mode, dbg,
+                                             base + tbl[i].off);
+                       break;
                default:
                        f = ERR_PTR(-EINVAL);
                }
@@ -821,13 +826,13 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
                                  size_t len, loff_t *ppos)
 {
        struct wil6210_priv *wil = file->private_data;
-       struct wil6210_mbox_hdr_wmi *wmi;
+       struct wmi_cmd_hdr *wmi;
        void *cmd;
-       int cmdlen = len - sizeof(struct wil6210_mbox_hdr_wmi);
+       int cmdlen = len - sizeof(struct wmi_cmd_hdr);
        u16 cmdid;
        int rc, rc1;
 
-       if (cmdlen <= 0)
+       if (cmdlen < 0)
                return -EINVAL;
 
        wmi = kmalloc(len, GFP_KERNEL);
@@ -840,8 +845,8 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
                return rc;
        }
 
-       cmd = &wmi[1];
-       cmdid = le16_to_cpu(wmi->id);
+       cmd = (cmdlen > 0) ? &wmi[1] : NULL;
+       cmdid = le16_to_cpu(wmi->command_id);
 
        rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
        kfree(wmi);
@@ -985,7 +990,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
                .interval_usec = 0,
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_notify_req_done_event evt;
        } __packed reply;
 
@@ -1333,6 +1338,34 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
                   r->ssn_last_drop);
 }
 
+static void wil_print_rxtid_crypto(struct seq_file *s, int tid,
+                                  struct wil_tid_crypto_rx *c)
+{
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               struct wil_tid_crypto_rx_single *cc = &c->key_id[i];
+
+               if (cc->key_set)
+                       goto has_keys;
+       }
+       return;
+
+has_keys:
+       if (tid < WIL_STA_TID_NUM)
+               seq_printf(s, "  [%2d] PN", tid);
+       else
+               seq_puts(s, "  [GR] PN");
+
+       for (i = 0; i < 4; i++) {
+               struct wil_tid_crypto_rx_single *cc = &c->key_id[i];
+
+               seq_printf(s, " [%i%s]%6phN", i, cc->key_set ? "+" : "-",
+                          cc->pn);
+       }
+       seq_puts(s, "\n");
+}
+
 static int wil_sta_debugfs_show(struct seq_file *s, void *data)
 __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
 {
@@ -1360,18 +1393,25 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
                        spin_lock_bh(&p->tid_rx_lock);
                        for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
                                struct wil_tid_ampdu_rx *r = p->tid_rx[tid];
+                               struct wil_tid_crypto_rx *c =
+                                               &p->tid_crypto_rx[tid];
 
                                if (r) {
-                                       seq_printf(s, "[%2d] ", tid);
+                                       seq_printf(s, "  [%2d] ", tid);
                                        wil_print_rxtid(s, r);
                                }
+
+                               wil_print_rxtid_crypto(s, tid, c);
                        }
+                       wil_print_rxtid_crypto(s, WIL_STA_TID_NUM,
+                                              &p->group_crypto_rx);
                        spin_unlock_bh(&p->tid_rx_lock);
                        seq_printf(s,
-                                  "Rx invalid frame: non-data %lu, short %lu, large %lu\n",
+                                  "Rx invalid frame: non-data %lu, short %lu, large %lu, replay %lu\n",
                                   p->stats.rx_non_data_frame,
                                   p->stats.rx_short_frame,
-                                  p->stats.rx_large_frame);
+                                  p->stats.rx_large_frame,
+                                  p->stats.rx_replay);
 
                        seq_puts(s, "Rx/MCS:");
                        for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
@@ -1487,6 +1527,7 @@ static const struct dbg_off dbg_wil_off[] = {
        WIL_FIELD(hw_version,   S_IRUGO,                doff_x32),
        WIL_FIELD(recovery_count, S_IRUGO,              doff_u32),
        WIL_FIELD(ap_isolate,   S_IRUGO,                doff_u32),
+       WIL_FIELD(discovery_mode, S_IRUGO | S_IWUSR,    doff_u8),
        {},
 };
 
index 4f2ffa5c6e1735c108e6ab4cdc05e59211dc9b9e..fe66b2b646f0c10aa2dc07c84da31c30d9e02cc3 100644 (file)
@@ -391,12 +391,14 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
        wil_dbg_irq(wil, "Thread ISR MISC 0x%08x\n", isr);
 
        if (isr & ISR_MISC_FW_ERROR) {
+               wil->recovery_state = fw_recovery_pending;
                wil_fw_core_dump(wil);
                wil_notify_fw_error(wil);
                isr &= ~ISR_MISC_FW_ERROR;
-               if (wil->platform_ops.notify_crash) {
+               if (wil->platform_ops.notify) {
                        wil_err(wil, "notify platform driver about FW crash");
-                       wil->platform_ops.notify_crash(wil->platform_handle);
+                       wil->platform_ops.notify(wil->platform_handle,
+                                                WIL_PLATFORM_EVT_FW_CRASH);
                } else {
                        wil_fw_error_recovery(wil);
                }
index f7f9486219516f3d8d713d0377fa574bb5eb1ec9..630380078236db718590da145ea1f56a4188d151 100644 (file)
@@ -161,13 +161,20 @@ out_free:
 
 int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd)
 {
+       int ret;
+
        switch (cmd) {
        case WIL_IOCTL_MEMIO:
-               return wil_ioc_memio_dword(wil, data);
+               ret = wil_ioc_memio_dword(wil, data);
+               break;
        case WIL_IOCTL_MEMIO_BLOCK:
-               return wil_ioc_memio_block(wil, data);
+               ret = wil_ioc_memio_block(wil, data);
+               break;
        default:
                wil_dbg_ioctl(wil, "Unsupported IOCTL 0x%04x\n", cmd);
                return -ENOIOCTLCMD;
        }
+
+       wil_dbg_ioctl(wil, "ioctl(0x%04x) -> %d\n", cmd, ret);
+       return ret;
 }
index 78ba6e04c9445f35a3700d9bcd4a21ce1b42b557..8d4e8843004e279792b9823fc5599a48519f8975 100644 (file)
@@ -27,6 +27,11 @@ bool debug_fw; /* = false; */
 module_param(debug_fw, bool, S_IRUGO);
 MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
 
+static bool oob_mode;
+module_param(oob_mode, bool, S_IRUGO);
+MODULE_PARM_DESC(oob_mode,
+                " enable out of the box (OOB) mode in FW, for diagnostics and certification");
+
 bool no_fw_recovery;
 module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery");
@@ -149,7 +154,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
        might_sleep();
        wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
                     sta->status);
-
+       /* inform upper/lower layers */
        if (sta->status != wil_sta_unused) {
                if (!from_event)
                        wmi_disconnect_sta(wil, sta->addr, reason_code, true);
@@ -165,7 +170,7 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
                }
                sta->status = wil_sta_unused;
        }
-
+       /* reorder buffers */
        for (i = 0; i < WIL_STA_TID_NUM; i++) {
                struct wil_tid_ampdu_rx *r;
 
@@ -177,10 +182,15 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 
                spin_unlock_bh(&sta->tid_rx_lock);
        }
+       /* crypto context */
+       memset(sta->tid_crypto_rx, 0, sizeof(sta->tid_crypto_rx));
+       memset(&sta->group_crypto_rx, 0, sizeof(sta->group_crypto_rx));
+       /* release vrings */
        for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
                if (wil->vring2cid_tid[i][0] == cid)
                        wil_vring_fini_tx(wil, i);
        }
+       /* statistics */
        memset(&sta->stats, 0, sizeof(sta->stats));
 }
 
@@ -300,6 +310,11 @@ void wil_set_recovery_state(struct wil6210_priv *wil, int state)
        wake_up_interruptible(&wil->wq);
 }
 
+bool wil_is_recovery_blocked(struct wil6210_priv *wil)
+{
+       return no_fw_recovery && (wil->recovery_state == fw_recovery_pending);
+}
+
 static void wil_fw_error_worker(struct work_struct *work)
 {
        struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
@@ -440,9 +455,8 @@ int wil_priv_init(struct wil6210_priv *wil)
 
        mutex_init(&wil->mutex);
        mutex_init(&wil->wmi_mutex);
-       mutex_init(&wil->back_rx_mutex);
-       mutex_init(&wil->back_tx_mutex);
        mutex_init(&wil->probe_client_mutex);
+       mutex_init(&wil->p2p_wdev_mutex);
 
        init_completion(&wil->wmi_ready);
        init_completion(&wil->wmi_call);
@@ -450,17 +464,15 @@ int wil_priv_init(struct wil6210_priv *wil)
        wil->bcast_vring = -1;
        setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
        setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil);
+       setup_timer(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn,
+                   (ulong)wil);
 
        INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
        INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
        INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
-       INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker);
-       INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker);
        INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
 
        INIT_LIST_HEAD(&wil->pending_wmi_ev);
-       INIT_LIST_HEAD(&wil->back_rx_pending);
-       INIT_LIST_HEAD(&wil->back_tx_pending);
        INIT_LIST_HEAD(&wil->probe_client_pending);
        spin_lock_init(&wil->wmi_ev_lock);
        init_waitqueue_head(&wil->wq);
@@ -514,16 +526,14 @@ void wil_priv_deinit(struct wil6210_priv *wil)
 
        wil_set_recovery_state(wil, fw_recovery_idle);
        del_timer_sync(&wil->scan_timer);
+       del_timer_sync(&wil->p2p.discovery_timer);
        cancel_work_sync(&wil->disconnect_worker);
        cancel_work_sync(&wil->fw_error_worker);
+       cancel_work_sync(&wil->p2p.discovery_expired_work);
        mutex_lock(&wil->mutex);
        wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
        mutex_unlock(&wil->mutex);
        wmi_event_flush(wil);
-       wil_back_rx_flush(wil);
-       cancel_work_sync(&wil->back_rx_worker);
-       wil_back_tx_flush(wil);
-       cancel_work_sync(&wil->back_tx_worker);
        wil_probe_client_flush(wil);
        cancel_work_sync(&wil->probe_client_worker);
        destroy_workqueue(wil->wq_service);
@@ -542,6 +552,16 @@ static inline void wil_release_cpu(struct wil6210_priv *wil)
        wil_w(wil, RGF_USER_USER_CPU_0, 1);
 }
 
+static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable)
+{
+       wil_info(wil, "%s: enable=%d\n", __func__, enable);
+       if (enable) {
+               wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
+       } else {
+               wil_c(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE);
+       }
+}
+
 static int wil_target_reset(struct wil6210_priv *wil)
 {
        int delay = 0;
@@ -637,6 +657,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
 static int wil_get_bl_info(struct wil6210_priv *wil)
 {
        struct net_device *ndev = wil_to_ndev(wil);
+       struct wiphy *wiphy = wil_to_wiphy(wil);
        union {
                struct bl_dedicated_registers_v0 bl0;
                struct bl_dedicated_registers_v1 bl1;
@@ -681,6 +702,7 @@ static int wil_get_bl_info(struct wil6210_priv *wil)
        }
 
        ether_addr_copy(ndev->perm_addr, mac);
+       ether_addr_copy(wiphy->perm_addr, mac);
        if (!is_valid_ether_addr(ndev->dev_addr))
                ether_addr_copy(ndev->dev_addr, mac);
 
@@ -767,6 +789,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
        if (wil->hw_version == HW_VER_UNKNOWN)
                return -ENODEV;
 
+       if (wil->platform_ops.notify) {
+               rc = wil->platform_ops.notify(wil->platform_handle,
+                                             WIL_PLATFORM_EVT_PRE_RESET);
+               if (rc)
+                       wil_err(wil,
+                               "%s: PRE_RESET platform notify failed, rc %d\n",
+                               __func__, rc);
+       }
+
        set_bit(wil_status_resetting, wil->status);
 
        cancel_work_sync(&wil->disconnect_worker);
@@ -807,6 +838,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
        if (rc)
                return rc;
 
+       wil_set_oob_mode(wil, oob_mode);
        if (load_fw) {
                wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME,
                         WIL_FW2_NAME);
@@ -846,8 +878,27 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
 
                /* we just started MAC, wait for FW ready */
                rc = wil_wait_for_fw_ready(wil);
-               if (rc == 0) /* check FW is responsive */
-                       rc = wmi_echo(wil);
+               if (rc)
+                       return rc;
+
+               /* check FW is responsive */
+               rc = wmi_echo(wil);
+               if (rc) {
+                       wil_err(wil, "%s: wmi_echo failed, rc %d\n",
+                               __func__, rc);
+                       return rc;
+               }
+
+               if (wil->platform_ops.notify) {
+                       rc = wil->platform_ops.notify(wil->platform_handle,
+                                                     WIL_PLATFORM_EVT_FW_RDY);
+                       if (rc) {
+                               wil_err(wil,
+                                       "%s: FW_RDY notify failed, rc %d\n",
+                                       __func__, rc);
+                               rc = 0;
+                       }
+               }
        }
 
        return rc;
@@ -954,6 +1005,8 @@ int __wil_down(struct wil6210_priv *wil)
        }
        wil_enable_irq(wil);
 
+       (void)wil_p2p_stop_discovery(wil);
+
        if (wil->scan_request) {
                wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
                             wil->scan_request);
index ecc3c1bdae4b535ed1018676eb820fd372f85082..3bc0e2634db0f2a49eb096f5589f5ddbecfda365 100644 (file)
@@ -60,11 +60,7 @@ static int wil_do_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
 {
        struct wil6210_priv *wil = ndev_to_wil(ndev);
 
-       int ret = wil_ioctl(wil, ifr->ifr_data, cmd);
-
-       wil_dbg_misc(wil, "ioctl(0x%04x) -> %d\n", cmd, ret);
-
-       return ret;
+       return wil_ioctl(wil, ifr->ifr_data, cmd);
 }
 
 static const struct net_device_ops wil_netdev_ops = {
@@ -149,6 +145,7 @@ void *wil_if_alloc(struct device *dev)
 
        wil = wdev_to_wil(wdev);
        wil->wdev = wdev;
+       wil->radio_wdev = wdev;
 
        wil_dbg_misc(wil, "%s()\n", __func__);
 
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c
new file mode 100644 (file)
index 0000000..2c1b895
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "wil6210.h"
+#include "wmi.h"
+
+#define P2P_WILDCARD_SSID "DIRECT-"
+#define P2P_DMG_SOCIAL_CHANNEL 2
+#define P2P_SEARCH_DURATION_MS 500
+#define P2P_DEFAULT_BI 100
+
+void wil_p2p_discovery_timer_fn(ulong x)
+{
+       struct wil6210_priv *wil = (void *)x;
+
+       wil_dbg_misc(wil, "%s\n", __func__);
+
+       schedule_work(&wil->p2p.discovery_expired_work);
+}
+
+int wil_p2p_search(struct wil6210_priv *wil,
+                  struct cfg80211_scan_request *request)
+{
+       int rc;
+       struct wil_p2p_info *p2p = &wil->p2p;
+
+       wil_dbg_misc(wil, "%s: channel %d\n",
+                    __func__, P2P_DMG_SOCIAL_CHANNEL);
+
+       mutex_lock(&wil->mutex);
+
+       if (p2p->discovery_started) {
+               wil_err(wil, "%s: search failed. discovery already ongoing\n",
+                       __func__);
+               rc = -EBUSY;
+               goto out;
+       }
+
+       rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI);
+       if (rc) {
+               wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__);
+               goto out;
+       }
+
+       rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
+       if (rc) {
+               wil_err(wil, "%s: wmi_set_ssid failed\n", __func__);
+               goto out_stop;
+       }
+
+       /* Set application IE to probe request and probe response */
+       rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ,
+                       request->ie_len, request->ie);
+       if (rc) {
+               wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n",
+                       __func__);
+               goto out_stop;
+       }
+
+       /* supplicant doesn't provide Probe Response IEs. As a workaround -
+        * re-use Probe Request IEs
+        */
+       rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP,
+                       request->ie_len, request->ie);
+       if (rc) {
+               wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n",
+                       __func__);
+               goto out_stop;
+       }
+
+       rc = wmi_start_search(wil);
+       if (rc) {
+               wil_err(wil, "%s: wmi_start_search failed\n", __func__);
+               goto out_stop;
+       }
+
+       p2p->discovery_started = 1;
+       INIT_WORK(&p2p->discovery_expired_work, wil_p2p_search_expired);
+       mod_timer(&p2p->discovery_timer,
+                 jiffies + msecs_to_jiffies(P2P_SEARCH_DURATION_MS));
+
+out_stop:
+       if (rc)
+               wmi_stop_discovery(wil);
+
+out:
+       mutex_unlock(&wil->mutex);
+       return rc;
+}
+
+int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,
+                  struct ieee80211_channel *chan, u64 *cookie)
+{
+       struct wil_p2p_info *p2p = &wil->p2p;
+       u8 channel = P2P_DMG_SOCIAL_CHANNEL;
+       int rc;
+
+       if (chan)
+               channel = chan->hw_value;
+
+       wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration);
+
+       mutex_lock(&wil->mutex);
+
+       if (p2p->discovery_started) {
+               wil_err(wil, "%s: discovery already ongoing\n", __func__);
+               rc = -EBUSY;
+               goto out;
+       }
+
+       rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI);
+       if (rc) {
+               wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__);
+               goto out;
+       }
+
+       rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
+       if (rc) {
+               wil_err(wil, "%s: wmi_set_ssid failed\n", __func__);
+               goto out_stop;
+       }
+
+       rc = wmi_start_listen(wil);
+       if (rc) {
+               wil_err(wil, "%s: wmi_start_listen failed\n", __func__);
+               goto out_stop;
+       }
+
+       memcpy(&p2p->listen_chan, chan, sizeof(*chan));
+       *cookie = ++p2p->cookie;
+
+       p2p->discovery_started = 1;
+       INIT_WORK(&p2p->discovery_expired_work, wil_p2p_listen_expired);
+       mod_timer(&p2p->discovery_timer,
+                 jiffies + msecs_to_jiffies(duration));
+
+out_stop:
+       if (rc)
+               wmi_stop_discovery(wil);
+
+out:
+       mutex_unlock(&wil->mutex);
+       return rc;
+}
+
+u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
+{
+       struct wil_p2p_info *p2p = &wil->p2p;
+       u8 started = p2p->discovery_started;
+
+       if (p2p->discovery_started) {
+               del_timer_sync(&p2p->discovery_timer);
+               p2p->discovery_started = 0;
+               wmi_stop_discovery(wil);
+       }
+
+       return started;
+}
+
+int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
+{
+       struct wil_p2p_info *p2p = &wil->p2p;
+       u8 started;
+
+       mutex_lock(&wil->mutex);
+
+       if (cookie != p2p->cookie) {
+               wil_info(wil, "%s: Cookie mismatch: 0x%016llx vs. 0x%016llx\n",
+                        __func__, p2p->cookie, cookie);
+               mutex_unlock(&wil->mutex);
+               return -ENOENT;
+       }
+
+       started = wil_p2p_stop_discovery(wil);
+
+       mutex_unlock(&wil->mutex);
+
+       if (!started) {
+               wil_err(wil, "%s: listen not started\n", __func__);
+               return -ENOENT;
+       }
+
+       mutex_lock(&wil->p2p_wdev_mutex);
+       cfg80211_remain_on_channel_expired(wil->radio_wdev,
+                                          p2p->cookie,
+                                          &p2p->listen_chan,
+                                          GFP_KERNEL);
+       wil->radio_wdev = wil->wdev;
+       mutex_unlock(&wil->p2p_wdev_mutex);
+       return 0;
+}
+
+void wil_p2p_listen_expired(struct work_struct *work)
+{
+       struct wil_p2p_info *p2p = container_of(work,
+                       struct wil_p2p_info, discovery_expired_work);
+       struct wil6210_priv *wil = container_of(p2p,
+                       struct wil6210_priv, p2p);
+       u8 started;
+
+       wil_dbg_misc(wil, "%s()\n", __func__);
+
+       mutex_lock(&wil->mutex);
+       started = wil_p2p_stop_discovery(wil);
+       mutex_unlock(&wil->mutex);
+
+       if (started) {
+               mutex_lock(&wil->p2p_wdev_mutex);
+               cfg80211_remain_on_channel_expired(wil->radio_wdev,
+                                                  p2p->cookie,
+                                                  &p2p->listen_chan,
+                                                  GFP_KERNEL);
+               wil->radio_wdev = wil->wdev;
+               mutex_unlock(&wil->p2p_wdev_mutex);
+       }
+
+}
+
+void wil_p2p_search_expired(struct work_struct *work)
+{
+       struct wil_p2p_info *p2p = container_of(work,
+                       struct wil_p2p_info, discovery_expired_work);
+       struct wil6210_priv *wil = container_of(p2p,
+                       struct wil6210_priv, p2p);
+       u8 started;
+
+       wil_dbg_misc(wil, "%s()\n", __func__);
+
+       mutex_lock(&wil->mutex);
+       started = wil_p2p_stop_discovery(wil);
+       mutex_unlock(&wil->mutex);
+
+       if (started) {
+               mutex_lock(&wil->p2p_wdev_mutex);
+               cfg80211_scan_done(wil->scan_request, 0);
+               wil->scan_request = NULL;
+               wil->radio_wdev = wil->wdev;
+               mutex_unlock(&wil->p2p_wdev_mutex);
+       }
+}
index e36f2a0c8cb67547a27774a7736e70e841fd4171..aeb72c438e4465927fce36fa7e09a3d665574b97 100644 (file)
@@ -275,6 +275,7 @@ static void wil_pcie_remove(struct pci_dev *pdev)
        pci_disable_device(pdev);
        if (wil->platform_ops.uninit)
                wil->platform_ops.uninit(wil->platform_handle);
+       wil_p2p_wdev_free(wil);
        wil_if_free(wil);
 }
 
index 32031e7a11d58a96b1b83671ab45c519e3282f99..19ed127d4d055703d14e018a1f278a5b8d9dbd89 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2016 Qualcomm Atheros, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -291,35 +291,15 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
        return min(max_agg_size, req_agg_wsize);
 }
 
-/* Block Ack - Rx side (recipient */
+/* Block Ack - Rx side (recipient) */
 int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
                         u8 dialog_token, __le16 ba_param_set,
                         __le16 ba_timeout, __le16 ba_seq_ctrl)
-{
-       struct wil_back_rx *req = kzalloc(sizeof(*req), GFP_KERNEL);
-
-       if (!req)
-               return -ENOMEM;
-
-       req->cidxtid = cidxtid;
-       req->dialog_token = dialog_token;
-       req->ba_param_set = le16_to_cpu(ba_param_set);
-       req->ba_timeout = le16_to_cpu(ba_timeout);
-       req->ba_seq_ctrl = le16_to_cpu(ba_seq_ctrl);
-
-       mutex_lock(&wil->back_rx_mutex);
-       list_add_tail(&req->list, &wil->back_rx_pending);
-       mutex_unlock(&wil->back_rx_mutex);
-
-       queue_work(wil->wq_service, &wil->back_rx_worker);
-
-       return 0;
-}
-
-static void wil_back_rx_handle(struct wil6210_priv *wil,
-                              struct wil_back_rx *req)
 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 {
+       u16 param_set = le16_to_cpu(ba_param_set);
+       u16 agg_timeout = le16_to_cpu(ba_timeout);
+       u16 seq_ctrl = le16_to_cpu(ba_seq_ctrl);
        struct wil_sta_info *sta;
        u8 cid, tid;
        u16 agg_wsize = 0;
@@ -328,34 +308,35 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
         * bits 2..5: TID
         * bits 6..15: buffer size
         */
-       u16 req_agg_wsize = WIL_GET_BITS(req->ba_param_set, 6, 15);
-       bool agg_amsdu = !!(req->ba_param_set & BIT(0));
-       int ba_policy = req->ba_param_set & BIT(1);
-       u16 agg_timeout = req->ba_timeout;
+       u16 req_agg_wsize = WIL_GET_BITS(param_set, 6, 15);
+       bool agg_amsdu = !!(param_set & BIT(0));
+       int ba_policy = param_set & BIT(1);
        u16 status = WLAN_STATUS_SUCCESS;
-       u16 ssn = req->ba_seq_ctrl >> 4;
+       u16 ssn = seq_ctrl >> 4;
        struct wil_tid_ampdu_rx *r;
-       int rc;
+       int rc = 0;
 
        might_sleep();
-       parse_cidxtid(req->cidxtid, &cid, &tid);
+       parse_cidxtid(cidxtid, &cid, &tid);
 
        /* sanity checks */
        if (cid >= WIL6210_MAX_CID) {
                wil_err(wil, "BACK: invalid CID %d\n", cid);
-               return;
+               rc = -EINVAL;
+               goto out;
        }
 
        sta = &wil->sta[cid];
        if (sta->status != wil_sta_connected) {
                wil_err(wil, "BACK: CID %d not connected\n", cid);
-               return;
+               rc = -EINVAL;
+               goto out;
        }
 
        wil_dbg_wmi(wil,
                    "ADDBA request for CID %d %pM TID %d size %d timeout %d AMSDU%s policy %d token %d SSN 0x%03x\n",
-                   cid, sta->addr, tid, req_agg_wsize, req->ba_timeout,
-                   agg_amsdu ? "+" : "-", !!ba_policy, req->dialog_token, ssn);
+                   cid, sta->addr, tid, req_agg_wsize, agg_timeout,
+                   agg_amsdu ? "+" : "-", !!ba_policy, dialog_token, ssn);
 
        /* apply policies */
        if (ba_policy) {
@@ -365,10 +346,13 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
        if (status == WLAN_STATUS_SUCCESS)
                agg_wsize = wil_agg_size(wil, req_agg_wsize);
 
-       rc = wmi_addba_rx_resp(wil, cid, tid, req->dialog_token, status,
+       rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status,
                               agg_amsdu, agg_wsize, agg_timeout);
-       if (rc || (status != WLAN_STATUS_SUCCESS))
-               return;
+       if (rc || (status != WLAN_STATUS_SUCCESS)) {
+               wil_err(wil, "%s: do not apply ba, rc(%d), status(%d)\n",
+                       __func__, rc, status);
+               goto out;
+       }
 
        /* apply */
        r = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn);
@@ -376,143 +360,37 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
        wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]);
        sta->tid_rx[tid] = r;
        spin_unlock_bh(&sta->tid_rx_lock);
-}
-
-void wil_back_rx_flush(struct wil6210_priv *wil)
-{
-       struct wil_back_rx *evt, *t;
 
-       wil_dbg_misc(wil, "%s()\n", __func__);
-
-       mutex_lock(&wil->back_rx_mutex);
-
-       list_for_each_entry_safe(evt, t, &wil->back_rx_pending, list) {
-               list_del(&evt->list);
-               kfree(evt);
-       }
-
-       mutex_unlock(&wil->back_rx_mutex);
-}
-
-/* Retrieve next ADDBA request from the pending list */
-static struct list_head *next_back_rx(struct wil6210_priv *wil)
-{
-       struct list_head *ret = NULL;
-
-       mutex_lock(&wil->back_rx_mutex);
-
-       if (!list_empty(&wil->back_rx_pending)) {
-               ret = wil->back_rx_pending.next;
-               list_del(ret);
-       }
-
-       mutex_unlock(&wil->back_rx_mutex);
-
-       return ret;
-}
-
-void wil_back_rx_worker(struct work_struct *work)
-{
-       struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
-                                               back_rx_worker);
-       struct wil_back_rx *evt;
-       struct list_head *lh;
-
-       while ((lh = next_back_rx(wil)) != NULL) {
-               evt = list_entry(lh, struct wil_back_rx, list);
-
-               wil_back_rx_handle(wil, evt);
-               kfree(evt);
-       }
+out:
+       return rc;
 }
 
-/* BACK - Tx (originator) side */
-static void wil_back_tx_handle(struct wil6210_priv *wil,
-                              struct wil_back_tx *req)
+/* BACK - Tx side (originator) */
+int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
 {
-       struct vring_tx_data *txdata = &wil->vring_tx_data[req->ringid];
-       int rc;
+       u8 agg_wsize = wil_agg_size(wil, wsize);
+       u16 agg_timeout = 0;
+       struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
+       int rc = 0;
 
        if (txdata->addba_in_progress) {
                wil_dbg_misc(wil, "ADDBA for vring[%d] already in progress\n",
-                            req->ringid);
-               return;
+                            ringid);
+               goto out;
        }
        if (txdata->agg_wsize) {
                wil_dbg_misc(wil,
-                            "ADDBA for vring[%d] already established wsize %d\n",
-                            req->ringid, txdata->agg_wsize);
-               return;
+                            "ADDBA for vring[%d] already done for wsize %d\n",
+                            ringid, txdata->agg_wsize);
+               goto out;
        }
        txdata->addba_in_progress = true;
-       rc = wmi_addba(wil, req->ringid, req->agg_wsize, req->agg_timeout);
-       if (rc)
+       rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout);
+       if (rc) {
+               wil_err(wil, "%s: wmi_addba failed, rc (%d)", __func__, rc);
                txdata->addba_in_progress = false;
-}
-
-static struct list_head *next_back_tx(struct wil6210_priv *wil)
-{
-       struct list_head *ret = NULL;
-
-       mutex_lock(&wil->back_tx_mutex);
-
-       if (!list_empty(&wil->back_tx_pending)) {
-               ret = wil->back_tx_pending.next;
-               list_del(ret);
-       }
-
-       mutex_unlock(&wil->back_tx_mutex);
-
-       return ret;
-}
-
-void wil_back_tx_worker(struct work_struct *work)
-{
-       struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
-                                                back_tx_worker);
-       struct wil_back_tx *evt;
-       struct list_head *lh;
-
-       while ((lh = next_back_tx(wil)) != NULL) {
-               evt = list_entry(lh, struct wil_back_tx, list);
-
-               wil_back_tx_handle(wil, evt);
-               kfree(evt);
        }
-}
-
-void wil_back_tx_flush(struct wil6210_priv *wil)
-{
-       struct wil_back_tx *evt, *t;
-
-       wil_dbg_misc(wil, "%s()\n", __func__);
-
-       mutex_lock(&wil->back_tx_mutex);
-
-       list_for_each_entry_safe(evt, t, &wil->back_tx_pending, list) {
-               list_del(&evt->list);
-               kfree(evt);
-       }
-
-       mutex_unlock(&wil->back_tx_mutex);
-}
-
-int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
-{
-       struct wil_back_tx *req = kzalloc(sizeof(*req), GFP_KERNEL);
-
-       if (!req)
-               return -ENOMEM;
 
-       req->ringid = ringid;
-       req->agg_wsize = wil_agg_size(wil, wsize);
-       req->agg_timeout = 0;
-
-       mutex_lock(&wil->back_tx_mutex);
-       list_add_tail(&req->list, &wil->back_tx_pending);
-       mutex_unlock(&wil->back_tx_mutex);
-
-       queue_work(wil->wq_service, &wil->back_tx_worker);
-
-       return 0;
+out:
+       return rc;
 }
index e59239d22b9493cee2cb1bdc2f2d6066a86e94e2..c4db2a9d9f7f6c8338e5f35d331069e93bccf89d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Qualcomm Atheros, Inc.
+ * Copyright (c) 2013-2016 Qualcomm Atheros, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -37,39 +37,40 @@ static inline void trace_ ## name(proto) {}
 #endif /* !CONFIG_WIL6210_TRACING || defined(__CHECKER__) */
 
 DECLARE_EVENT_CLASS(wil6210_wmi,
-       TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+       TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len),
 
        TP_ARGS(wmi, buf, buf_len),
 
        TP_STRUCT__entry(
                __field(u8, mid)
-               __field(u16, id)
-               __field(u32, timestamp)
+               __field(u16, command_id)
+               __field(u32, fw_timestamp)
                __field(u16, buf_len)
                __dynamic_array(u8, buf, buf_len)
        ),
 
        TP_fast_assign(
                __entry->mid = wmi->mid;
-               __entry->id = le16_to_cpu(wmi->id);
-               __entry->timestamp = le32_to_cpu(wmi->timestamp);
+               __entry->command_id = le16_to_cpu(wmi->command_id);
+               __entry->fw_timestamp = le32_to_cpu(wmi->fw_timestamp);
                __entry->buf_len = buf_len;
                memcpy(__get_dynamic_array(buf), buf, buf_len);
        ),
 
        TP_printk(
                "MID %d id 0x%04x len %d timestamp %d",
-               __entry->mid, __entry->id, __entry->buf_len, __entry->timestamp
+               __entry->mid, __entry->command_id, __entry->buf_len,
+               __entry->fw_timestamp
        )
 );
 
 DEFINE_EVENT(wil6210_wmi, wil6210_wmi_cmd,
-       TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+       TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len),
        TP_ARGS(wmi, buf, buf_len)
 );
 
 DEFINE_EVENT(wil6210_wmi, wil6210_wmi_event,
-       TP_PROTO(struct wil6210_mbox_hdr_wmi *wmi, void *buf, u16 buf_len),
+       TP_PROTO(struct wmi_cmd_hdr *wmi, void *buf, u16 buf_len),
        TP_ARGS(wmi, buf, buf_len)
 );
 
index 6af20903cf89fac32bd3f96d14d8b4ed5923d60a..f260b232fd57114907e5aa5664db28094ba15bc4 100644 (file)
@@ -549,6 +549,60 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count)
        return rc;
 }
 
+/**
+ * reverse_memcmp - Compare two areas of memory, in reverse order
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ *
+ * Cut'n'paste from original memcmp (see lib/string.c)
+ * with minimal modifications
+ */
+static int reverse_memcmp(const void *cs, const void *ct, size_t count)
+{
+       const unsigned char *su1, *su2;
+       int res = 0;
+
+       for (su1 = cs + count - 1, su2 = ct + count - 1; count > 0;
+            --su1, --su2, count--) {
+               res = *su1 - *su2;
+               if (res)
+                       break;
+       }
+       return res;
+}
+
+static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
+{
+       struct vring_rx_desc *d = wil_skb_rxdesc(skb);
+       int cid = wil_rxdesc_cid(d);
+       int tid = wil_rxdesc_tid(d);
+       int key_id = wil_rxdesc_key_id(d);
+       int mc = wil_rxdesc_mcast(d);
+       struct wil_sta_info *s = &wil->sta[cid];
+       struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
+                                     &s->tid_crypto_rx[tid];
+       struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
+       const u8 *pn = (u8 *)&d->mac.pn_15_0;
+
+       if (!cc->key_set) {
+               wil_err_ratelimited(wil,
+                                   "Key missing. CID %d TID %d MCast %d KEY_ID %d\n",
+                                   cid, tid, mc, key_id);
+               return -EINVAL;
+       }
+
+       if (reverse_memcmp(pn, cc->pn, IEEE80211_GCMP_PN_LEN) <= 0) {
+               wil_err_ratelimited(wil,
+                                   "Replay attack. CID %d TID %d MCast %d KEY_ID %d PN %6phN last %6phN\n",
+                                   cid, tid, mc, key_id, pn, cc->pn);
+               return -EINVAL;
+       }
+       memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN);
+
+       return 0;
+}
+
 /*
  * Pass Rx packet to the netif. Update statistics.
  * Called in softirq context (NAPI poll).
@@ -561,6 +615,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
        unsigned int len = skb->len;
        struct vring_rx_desc *d = wil_skb_rxdesc(skb);
        int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */
+       int security = wil_rxdesc_security(d);
        struct ethhdr *eth = (void *)skb->data;
        /* here looking for DA, not A1, thus Rxdesc's 'mcast' indication
         * is not suitable, need to look at data
@@ -586,6 +641,13 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
 
        skb_orphan(skb);
 
+       if (security && (wil_rx_crypto_check(wil, skb) != 0)) {
+               rc = GRO_DROP;
+               dev_kfree_skb(skb);
+               stats->rx_replay++;
+               goto stats;
+       }
+
        if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) {
                if (mcast) {
                        /* send multicast frames both to higher layers in
@@ -627,6 +689,7 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
                wil_dbg_txrx(wil, "Rx complete %d bytes => %s\n",
                             len, gro_res_str[rc]);
        }
+stats:
        /* statistics. rc set to GRO_NORMAL for AP bridging */
        if (unlikely(rc == GRO_DROP)) {
                ndev->stats.rx_dropped++;
@@ -757,7 +820,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
                },
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_vring_cfg_done_event cmd;
        } __packed reply;
        struct vring *vring = &wil->vring_tx[id];
@@ -834,7 +897,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
                },
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_vring_cfg_done_event cmd;
        } __packed reply;
        struct vring *vring = &wil->vring_tx[id];
index ee7c7b4b9a178845e94530e0b63b3a62c4594456..fcdffaa8251bd812f7819581d06d8acf0a1ca353 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -480,6 +480,16 @@ static inline int wil_rxdesc_ext_subtype(struct vring_rx_desc *d)
        return WIL_GET_BITS(d->mac.d0, 28, 31);
 }
 
+static inline int wil_rxdesc_key_id(struct vring_rx_desc *d)
+{
+       return WIL_GET_BITS(d->mac.d1, 4, 5);
+}
+
+static inline int wil_rxdesc_security(struct vring_rx_desc *d)
+{
+       return WIL_GET_BITS(d->mac.d1, 7, 7);
+}
+
 static inline int wil_rxdesc_ds_bits(struct vring_rx_desc *d)
 {
        return WIL_GET_BITS(d->mac.d1, 8, 9);
index 8427d68b6fa8e875a2ae13cbdcaf5b3b187b19e9..4d699ea463732cae27ab30dfa06beb33e38893f3 100644 (file)
@@ -22,6 +22,7 @@
 #include <net/cfg80211.h>
 #include <linux/timex.h>
 #include <linux/types.h>
+#include "wmi.h"
 #include "wil_platform.h"
 
 extern bool no_fw_recovery;
@@ -131,6 +132,7 @@ struct RGF_ICR {
 /* registers - FW addresses */
 #define RGF_USER_USAGE_1               (0x880004)
 #define RGF_USER_USAGE_6               (0x880018)
+       #define BIT_USER_OOB_MODE               BIT(31)
 #define RGF_USER_HW_MACHINE_STATE      (0x8801dc)
        #define HW_MACHINE_BOOT_DONE    (0x3fffffd)
 #define RGF_USER_USER_CPU_0            (0x8801e0)
@@ -334,29 +336,11 @@ struct wil6210_mbox_hdr {
 /* max. value for wil6210_mbox_hdr.len */
 #define MAX_MBOXITEM_SIZE   (240)
 
-/**
- * struct wil6210_mbox_hdr_wmi - WMI header
- *
- * @mid: MAC ID
- *     00 - default, created by FW
- *     01..0f - WiFi ports, driver to create
- *     10..fe - debug
- *     ff - broadcast
- * @id: command/event ID
- * @timestamp: FW fills for events, free-running msec timer
- */
-struct wil6210_mbox_hdr_wmi {
-       u8 mid;
-       u8 reserved;
-       __le16 id;
-       __le32 timestamp;
-} __packed;
-
 struct pending_wmi_event {
        struct list_head list;
        struct {
                struct wil6210_mbox_hdr hdr;
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                u8 data[0];
        } __packed event;
 };
@@ -455,6 +439,29 @@ struct wil_tid_ampdu_rx {
        bool first_time; /* is it 1-st time this buffer used? */
 };
 
+/**
+ * struct wil_tid_crypto_rx_single - TID crypto information (Rx).
+ *
+ * @pn: GCMP PN for the session
+ * @key_set: valid key present
+ */
+struct wil_tid_crypto_rx_single {
+       u8 pn[IEEE80211_GCMP_PN_LEN];
+       bool key_set;
+};
+
+struct wil_tid_crypto_rx {
+       struct wil_tid_crypto_rx_single key_id[4];
+};
+
+struct wil_p2p_info {
+       struct ieee80211_channel listen_chan;
+       u8 discovery_started;
+       u64 cookie;
+       struct timer_list discovery_timer; /* listen/search duration */
+       struct work_struct discovery_expired_work; /* listen/search expire */
+};
+
 enum wil_sta_status {
        wil_sta_unused = 0,
        wil_sta_conn_pending = 1,
@@ -474,6 +481,7 @@ struct wil_net_stats {
        unsigned long   rx_non_data_frame;
        unsigned long   rx_short_frame;
        unsigned long   rx_large_frame;
+       unsigned long   rx_replay;
        u16 last_mcs_rx;
        u64 rx_per_mcs[WIL_MCS_MAX + 1];
 };
@@ -495,6 +503,8 @@ struct wil_sta_info {
        spinlock_t tid_rx_lock; /* guarding tid_rx array */
        unsigned long tid_rx_timer_expired[BITS_TO_LONGS(WIL_STA_TID_NUM)];
        unsigned long tid_rx_stop_requested[BITS_TO_LONGS(WIL_STA_TID_NUM)];
+       struct wil_tid_crypto_rx tid_crypto_rx[WIL_STA_TID_NUM];
+       struct wil_tid_crypto_rx group_crypto_rx;
 };
 
 enum {
@@ -507,24 +517,6 @@ enum {
        hw_capability_last
 };
 
-struct wil_back_rx {
-       struct list_head list;
-       /* request params, converted to CPU byte order - what we asked for */
-       u8 cidxtid;
-       u8 dialog_token;
-       u16 ba_param_set;
-       u16 ba_timeout;
-       u16 ba_seq_ctrl;
-};
-
-struct wil_back_tx {
-       struct list_head list;
-       /* request params, converted to CPU byte order - what we asked for */
-       u8 ringid;
-       u8 agg_wsize;
-       u16 agg_timeout;
-};
-
 struct wil_probe_client_req {
        struct list_head list;
        u64 cookie;
@@ -595,13 +587,6 @@ struct wil6210_priv {
        spinlock_t wmi_ev_lock;
        struct napi_struct napi_rx;
        struct napi_struct napi_tx;
-       /* BACK */
-       struct list_head back_rx_pending;
-       struct mutex back_rx_mutex; /* protect @back_rx_pending */
-       struct work_struct back_rx_worker;
-       struct list_head back_tx_pending;
-       struct mutex back_tx_mutex; /* protect @back_tx_pending */
-       struct work_struct back_tx_worker;
        /* keep alive */
        struct list_head probe_client_pending;
        struct mutex probe_client_mutex; /* protect @probe_client_pending */
@@ -622,11 +607,21 @@ struct wil6210_priv {
        /* debugfs */
        struct dentry *debug;
        struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
+       u8 discovery_mode;
 
        void *platform_handle;
        struct wil_platform_ops platform_ops;
 
        struct pmc_ctx pmc;
+
+       bool pbss;
+
+       struct wil_p2p_info p2p;
+
+       /* P2P_DEVICE vif */
+       struct wireless_dev *p2p_wdev;
+       struct mutex p2p_wdev_mutex; /* protect @p2p_wdev */
+       struct wireless_dev *radio_wdev;
 };
 
 #define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -722,6 +717,7 @@ void wil_priv_deinit(struct wil6210_priv *wil);
 int wil_reset(struct wil6210_priv *wil, bool no_fw);
 void wil_fw_error_recovery(struct wil6210_priv *wil);
 void wil_set_recovery_state(struct wil6210_priv *wil, int state);
+bool wil_is_recovery_blocked(struct wil6210_priv *wil);
 int wil_up(struct wil6210_priv *wil);
 int __wil_up(struct wil6210_priv *wil);
 int wil_down(struct wil6210_priv *wil);
@@ -752,7 +748,6 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
 int wmi_echo(struct wil6210_priv *wil);
 int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
 int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
-int wmi_p2p_cfg(struct wil6210_priv *wil, int channel);
 int wmi_rxon(struct wil6210_priv *wil, bool on);
 int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
 int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason,
@@ -765,11 +760,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
 int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
                         u8 dialog_token, __le16 ba_param_set,
                         __le16 ba_timeout, __le16 ba_seq_ctrl);
-void wil_back_rx_worker(struct work_struct *work);
-void wil_back_rx_flush(struct wil6210_priv *wil);
 int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
-void wil_back_tx_worker(struct work_struct *work);
-void wil_back_tx_flush(struct wil6210_priv *wil);
 
 void wil6210_clear_irq(struct wil6210_priv *wil);
 int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi);
@@ -779,6 +770,24 @@ void wil_unmask_irq(struct wil6210_priv *wil);
 void wil_configure_interrupt_moderation(struct wil6210_priv *wil);
 void wil_disable_irq(struct wil6210_priv *wil);
 void wil_enable_irq(struct wil6210_priv *wil);
+
+/* P2P */
+void wil_p2p_discovery_timer_fn(ulong x);
+int wil_p2p_search(struct wil6210_priv *wil,
+                  struct cfg80211_scan_request *request);
+int wil_p2p_listen(struct wil6210_priv *wil, unsigned int duration,
+                  struct ieee80211_channel *chan, u64 *cookie);
+u8 wil_p2p_stop_discovery(struct wil6210_priv *wil);
+int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie);
+void wil_p2p_listen_expired(struct work_struct *work);
+void wil_p2p_search_expired(struct work_struct *work);
+
+/* WMI for P2P */
+int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi);
+int wmi_start_listen(struct wil6210_priv *wil);
+int wmi_start_search(struct wil6210_priv *wil);
+int wmi_stop_discovery(struct wil6210_priv *wil);
+
 int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                         struct cfg80211_mgmt_tx_params *params,
                         u64 *cookie);
@@ -790,10 +799,11 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
 
 struct wireless_dev *wil_cfg80211_init(struct device *dev);
 void wil_wdev_free(struct wil6210_priv *wil);
+void wil_p2p_wdev_free(struct wil6210_priv *wil);
 
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
 int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
-                 u8 chan, u8 hidden_ssid);
+                 u8 chan, u8 hidden_ssid, u8 is_go);
 int wmi_pcp_stop(struct wil6210_priv *wil);
 void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
                        u16 reason_code, bool from_event);
index 9a949d9103438f459c8e715bf83e1d16c56853a0..33d4a34b3b1c005371733517678a8f8cfb1eed7c 100644 (file)
 
 struct device;
 
+enum wil_platform_event {
+       WIL_PLATFORM_EVT_FW_CRASH = 0,
+       WIL_PLATFORM_EVT_PRE_RESET = 1,
+       WIL_PLATFORM_EVT_FW_RDY = 2,
+};
+
 /**
  * struct wil_platform_ops - wil platform module calls from this
  * driver to platform driver
@@ -28,7 +34,7 @@ struct wil_platform_ops {
        int (*suspend)(void *handle);
        int (*resume)(void *handle);
        void (*uninit)(void *handle);
-       int (*notify_crash)(void *handle);
+       int (*notify)(void *handle, enum wil_platform_event evt);
 };
 
 /**
index 493e721c4fa715ba23ac86e153fe4626d389e9fb..3cc4462aec1a57f80daa8273839aea62b2fa09af 100644 (file)
@@ -176,7 +176,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 {
        struct {
                struct wil6210_mbox_hdr hdr;
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
        } __packed cmd = {
                .hdr = {
                        .type = WIL_MBOX_HDR_TYPE_WMI,
@@ -185,7 +185,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
                },
                .wmi = {
                        .mid = 0,
-                       .id = cpu_to_le16(cmdid),
+                       .command_id = cpu_to_le16(cmdid),
                },
        };
        struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
@@ -368,6 +368,8 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
                wil_hex_dump_wmi("IE ", DUMP_PREFIX_OFFSET, 16, 1, ie_buf,
                                 ie_len, true);
 
+               wil_dbg_wmi(wil, "Capability info : 0x%04x\n", cap);
+
                bss = cfg80211_inform_bss_frame(wiphy, channel, rx_mgmt_frame,
                                                d_len, signal, GFP_KERNEL);
                if (bss) {
@@ -378,8 +380,10 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
                        wil_err(wil, "cfg80211_inform_bss_frame() failed\n");
                }
        } else {
-               cfg80211_rx_mgmt(wil->wdev, freq, signal,
+               mutex_lock(&wil->p2p_wdev_mutex);
+               cfg80211_rx_mgmt(wil->radio_wdev, freq, signal,
                                 (void *)rx_mgmt_frame, d_len, 0);
+               mutex_unlock(&wil->p2p_wdev_mutex);
        }
 }
 
@@ -406,7 +410,10 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
                             wil->scan_request, aborted);
 
                del_timer_sync(&wil->scan_timer);
+               mutex_lock(&wil->p2p_wdev_mutex);
                cfg80211_scan_done(wil->scan_request, aborted);
+               wil->radio_wdev = wil->wdev;
+               mutex_unlock(&wil->p2p_wdev_mutex);
                wil->scan_request = NULL;
        } else {
                wil_err(wil, "SCAN_COMPLETE while not scanning\n");
@@ -487,6 +494,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
                        return;
                }
                del_timer_sync(&wil->connect_timer);
+       } else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
+                  (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
+               if (wil->sta[evt->cid].status != wil_sta_unused) {
+                       wil_err(wil, "%s: AP: Invalid status %d for CID %d\n",
+                               __func__, wil->sta[evt->cid].status, evt->cid);
+                       mutex_unlock(&wil->mutex);
+                       return;
+               }
        }
 
        /* FIXME FW can transmit only ucast frames to peer */
@@ -648,7 +663,7 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
 static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
                              int len)
 {
-       struct wmi_vring_ba_status_event *evt = d;
+       struct wmi_ba_status_event *evt = d;
        struct vring_tx_data *txdata;
 
        wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
@@ -834,10 +849,10 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
                      offsetof(struct wil6210_mbox_ring_desc, sync), 0);
                /* indicate */
                if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
-                   (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
-                       struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
-                       u16 id = le16_to_cpu(wmi->id);
-                       u32 tstamp = le32_to_cpu(wmi->timestamp);
+                   (len >= sizeof(struct wmi_cmd_hdr))) {
+                       struct wmi_cmd_hdr *wmi = &evt->event.wmi;
+                       u16 id = le16_to_cpu(wmi->command_id);
+                       u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
                        spin_lock_irqsave(&wil->wmi_ev_lock, flags);
                        if (wil->reply_id && wil->reply_id == id) {
                                if (wil->reply_buf) {
@@ -947,7 +962,7 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
 }
 
 int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
-                 u8 chan, u8 hidden_ssid)
+                 u8 chan, u8 hidden_ssid, u8 is_go)
 {
        int rc;
 
@@ -958,9 +973,10 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
                .channel = chan - 1,
                .pcp_max_assoc_sta = max_assoc_sta,
                .hidden_ssid = hidden_ssid,
+               .is_go = is_go,
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_pcp_started_event evt;
        } __packed reply;
 
@@ -1014,7 +1030,7 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
 {
        int rc;
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_set_ssid_cmd cmd;
        } __packed reply;
        int len; /* reply.cmd.ssid_len in CPU order */
@@ -1047,7 +1063,7 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel)
 {
        int rc;
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_set_pcp_channel_cmd cmd;
        } __packed reply;
 
@@ -1064,14 +1080,86 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel)
        return 0;
 }
 
-int wmi_p2p_cfg(struct wil6210_priv *wil, int channel)
+int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
 {
+       int rc;
        struct wmi_p2p_cfg_cmd cmd = {
-               .discovery_mode = WMI_DISCOVERY_MODE_NON_OFFLOAD,
+               .discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
+               .bcon_interval = cpu_to_le16(bi),
                .channel = channel - 1,
        };
+       struct {
+               struct wmi_cmd_hdr wmi;
+               struct wmi_p2p_cfg_done_event evt;
+       } __packed reply;
+
+       wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
+
+       rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd),
+                     WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
+       if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
+               wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
+               rc = -EINVAL;
+       }
 
-       return wmi_send(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd));
+       return rc;
+}
+
+int wmi_start_listen(struct wil6210_priv *wil)
+{
+       int rc;
+       struct {
+               struct wmi_cmd_hdr wmi;
+               struct wmi_listen_started_event evt;
+       } __packed reply;
+
+       wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
+
+       rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
+                     WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
+       if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
+               wil_err(wil, "device failed to start listen. status %d\n",
+                       reply.evt.status);
+               rc = -EINVAL;
+       }
+
+       return rc;
+}
+
+int wmi_start_search(struct wil6210_priv *wil)
+{
+       int rc;
+       struct {
+               struct wmi_cmd_hdr wmi;
+               struct wmi_search_started_event evt;
+       } __packed reply;
+
+       wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
+
+       rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0,
+                     WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
+       if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
+               wil_err(wil, "device failed to start search. status %d\n",
+                       reply.evt.status);
+               rc = -EINVAL;
+       }
+
+       return rc;
+}
+
+int wmi_stop_discovery(struct wil6210_priv *wil)
+{
+       int rc;
+
+       wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
+
+       rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
+                     WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
+
+       if (rc)
+               wil_err(wil, "Failed to stop discovery\n");
+
+       return rc;
 }
 
 int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
@@ -1155,7 +1243,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
 {
        int rc;
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_listen_started_event evt;
        } __packed reply;
 
@@ -1192,7 +1280,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
                .host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_cfg_rx_chain_done_event evt;
        } __packed evt;
        int rc;
@@ -1246,7 +1334,7 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
                .measure_mode = cpu_to_le32(TEMPERATURE_MEASURE_NOW),
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_temp_sense_done_event evt;
        } __packed reply;
 
@@ -1272,7 +1360,7 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason,
                .disconnect_reason = cpu_to_le16(reason),
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_disconnect_event evt;
        } __packed reply;
 
@@ -1364,7 +1452,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
                .ba_timeout = cpu_to_le16(timeout),
        };
        struct {
-               struct wil6210_mbox_hdr_wmi wmi;
+               struct wmi_cmd_hdr wmi;
                struct wmi_rcp_addba_resp_sent_event evt;
        } __packed reply;
 
@@ -1420,10 +1508,10 @@ static void wmi_event_handle(struct wil6210_priv *wil,
        u16 len = le16_to_cpu(hdr->len);
 
        if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
-           (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
-               struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]);
+           (len >= sizeof(struct wmi_cmd_hdr))) {
+               struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
                void *evt_data = (void *)(&wmi[1]);
-               u16 id = le16_to_cpu(wmi->id);
+               u16 id = le16_to_cpu(wmi->command_id);
 
                wil_dbg_wmi(wil, "Handle WMI 0x%04x (reply_id 0x%04x)\n",
                            id, wil->reply_id);
index 6e90e78f1554c84c3f0ab820ede5ed4c5437ce3d..29865e0b5203786de386cf6519caa1008f17b502 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
- * Copyright (c) 2006-2012 Wilocity .
+ * Copyright (c) 2012-2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2006-2012 Wilocity
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 
 /*
  * This file contains the definitions of the WMI protocol specified in the
- * Wireless Module Interface (WMI) for the Wilocity
- * MARLON 60 Gigabit wireless solution.
+ * Wireless Module Interface (WMI) for the Qualcomm
+ * 60 GHz wireless solution.
  * It includes definitions of all the commands and events.
  * Commands are messages from the host to the WM.
  * Events are messages from the WM to the host.
+ *
+ * This is an automatically generated file.
  */
 
 #ifndef __WILOCITY_WMI_H__
 #define __WILOCITY_WMI_H__
 
 /* General */
-#define WILOCITY_MAX_ASSOC_STA (8)
-#define WILOCITY_DEFAULT_ASSOC_STA (1)
-#define WMI_MAC_LEN            (6)
-#define WMI_PROX_RANGE_NUM     (3)
-#define WMI_MAX_LOSS_DMG_BEACONS       (32)
+#define WMI_MAX_ASSOC_STA              (8)
+#define WMI_DEFAULT_ASSOC_STA          (1)
+#define WMI_MAC_LEN                    (6)
+#define WMI_PROX_RANGE_NUM             (3)
+#define WMI_MAX_LOSS_DMG_BEACONS       (20)
+
+/* Mailbox interface
+ * used for commands and events
+ */
+enum wmi_mid {
+       MID_DEFAULT             = 0x00,
+       FIRST_DBG_MID_ID        = 0x10,
+       LAST_DBG_MID_ID         = 0xFE,
+       MID_BROADCAST           = 0xFF,
+};
+
+/* WMI_CMD_HDR */
+struct wmi_cmd_hdr {
+       u8 mid;
+       u8 reserved;
+       __le16 command_id;
+       __le32 fw_timestamp;
+} __packed;
 
 /* List of Commands */
 enum wmi_command_id {
-       WMI_CONNECT_CMDID               = 0x0001,
-       WMI_DISCONNECT_CMDID            = 0x0003,
-       WMI_DISCONNECT_STA_CMDID        = 0x0004,
-       WMI_START_SCAN_CMDID            = 0x0007,
-       WMI_SET_BSS_FILTER_CMDID        = 0x0009,
-       WMI_SET_PROBED_SSID_CMDID       = 0x000a,
-       WMI_SET_LISTEN_INT_CMDID        = 0x000b,
-       WMI_BCON_CTRL_CMDID             = 0x000f,
-       WMI_ADD_CIPHER_KEY_CMDID        = 0x0016,
-       WMI_DELETE_CIPHER_KEY_CMDID     = 0x0017,
-       WMI_SET_APPIE_CMDID             = 0x003f,
-       WMI_SET_WSC_STATUS_CMDID        = 0x0041,
-       WMI_PXMT_RANGE_CFG_CMDID        = 0x0042,
-       WMI_PXMT_SNR2_RANGE_CFG_CMDID   = 0x0043,
-/*     WMI_FAST_MEM_ACC_MODE_CMDID     = 0x0300, */
-       WMI_MEM_READ_CMDID              = 0x0800,
-       WMI_MEM_WR_CMDID                = 0x0801,
-       WMI_ECHO_CMDID                  = 0x0803,
-       WMI_DEEP_ECHO_CMDID             = 0x0804,
-       WMI_CONFIG_MAC_CMDID            = 0x0805,
-       WMI_CONFIG_PHY_DEBUG_CMDID      = 0x0806,
-       WMI_ADD_DEBUG_TX_PCKT_CMDID     = 0x0808,
-       WMI_PHY_GET_STATISTICS_CMDID    = 0x0809,
-       WMI_FS_TUNE_CMDID               = 0x080a,
-       WMI_CORR_MEASURE_CMDID          = 0x080b,
-       WMI_READ_RSSI_CMDID             = 0x080c,
-       WMI_TEMP_SENSE_CMDID            = 0x080e,
-       WMI_DC_CALIB_CMDID              = 0x080f,
-       WMI_SEND_TONE_CMDID             = 0x0810,
-       WMI_IQ_TX_CALIB_CMDID           = 0x0811,
-       WMI_IQ_RX_CALIB_CMDID           = 0x0812,
-       WMI_SET_UCODE_IDLE_CMDID        = 0x0813,
-       WMI_SET_WORK_MODE_CMDID         = 0x0815,
-       WMI_LO_LEAKAGE_CALIB_CMDID      = 0x0816,
-       WMI_MARLON_R_READ_CMDID         = 0x0818,
-       WMI_MARLON_R_WRITE_CMDID        = 0x0819,
-       WMI_MARLON_R_TXRX_SEL_CMDID     = 0x081a,
-       MAC_IO_STATIC_PARAMS_CMDID      = 0x081b,
-       MAC_IO_DYNAMIC_PARAMS_CMDID     = 0x081c,
-       WMI_SILENT_RSSI_CALIB_CMDID     = 0x081d,
-       WMI_RF_RX_TEST_CMDID            = 0x081e,
-       WMI_CFG_RX_CHAIN_CMDID          = 0x0820,
-       WMI_VRING_CFG_CMDID             = 0x0821,
-       WMI_BCAST_VRING_CFG_CMDID       = 0x0822,
-       WMI_VRING_BA_EN_CMDID           = 0x0823,
-       WMI_VRING_BA_DIS_CMDID          = 0x0824,
-       WMI_RCP_ADDBA_RESP_CMDID        = 0x0825,
-       WMI_RCP_DELBA_CMDID             = 0x0826,
-       WMI_SET_SSID_CMDID              = 0x0827,
-       WMI_GET_SSID_CMDID              = 0x0828,
-       WMI_SET_PCP_CHANNEL_CMDID       = 0x0829,
-       WMI_GET_PCP_CHANNEL_CMDID       = 0x082a,
-       WMI_SW_TX_REQ_CMDID             = 0x082b,
-       WMI_READ_MAC_RXQ_CMDID          = 0x0830,
-       WMI_READ_MAC_TXQ_CMDID          = 0x0831,
-       WMI_WRITE_MAC_RXQ_CMDID         = 0x0832,
-       WMI_WRITE_MAC_TXQ_CMDID         = 0x0833,
-       WMI_WRITE_MAC_XQ_FIELD_CMDID    = 0x0834,
-       WMI_MLME_PUSH_CMDID             = 0x0835,
-       WMI_BEAMFORMING_MGMT_CMDID      = 0x0836,
-       WMI_BF_TXSS_MGMT_CMDID          = 0x0837,
-       WMI_BF_SM_MGMT_CMDID            = 0x0838,
-       WMI_BF_RXSS_MGMT_CMDID          = 0x0839,
-       WMI_BF_TRIG_CMDID               = 0x083A,
-       WMI_SET_SECTORS_CMDID           = 0x0849,
-       WMI_MAINTAIN_PAUSE_CMDID        = 0x0850,
-       WMI_MAINTAIN_RESUME_CMDID       = 0x0851,
-       WMI_RS_MGMT_CMDID               = 0x0852,
-       WMI_RF_MGMT_CMDID               = 0x0853,
-       WMI_THERMAL_THROTTLING_CTRL_CMDID       = 0x0854,
-       WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x0855,
+       WMI_CONNECT_CMDID                       = 0x01,
+       WMI_DISCONNECT_CMDID                    = 0x03,
+       WMI_DISCONNECT_STA_CMDID                = 0x04,
+       WMI_START_SCAN_CMDID                    = 0x07,
+       WMI_SET_BSS_FILTER_CMDID                = 0x09,
+       WMI_SET_PROBED_SSID_CMDID               = 0x0A,
+       WMI_SET_LISTEN_INT_CMDID                = 0x0B,
+       WMI_BCON_CTRL_CMDID                     = 0x0F,
+       WMI_ADD_CIPHER_KEY_CMDID                = 0x16,
+       WMI_DELETE_CIPHER_KEY_CMDID             = 0x17,
+       WMI_PCP_CONF_CMDID                      = 0x18,
+       WMI_SET_APPIE_CMDID                     = 0x3F,
+       WMI_SET_WSC_STATUS_CMDID                = 0x41,
+       WMI_PXMT_RANGE_CFG_CMDID                = 0x42,
+       WMI_PXMT_SNR2_RANGE_CFG_CMDID           = 0x43,
+       WMI_MEM_READ_CMDID                      = 0x800,
+       WMI_MEM_WR_CMDID                        = 0x801,
+       WMI_ECHO_CMDID                          = 0x803,
+       WMI_DEEP_ECHO_CMDID                     = 0x804,
+       WMI_CONFIG_MAC_CMDID                    = 0x805,
+       WMI_CONFIG_PHY_DEBUG_CMDID              = 0x806,
+       WMI_ADD_DEBUG_TX_PCKT_CMDID             = 0x808,
+       WMI_PHY_GET_STATISTICS_CMDID            = 0x809,
+       WMI_FS_TUNE_CMDID                       = 0x80A,
+       WMI_CORR_MEASURE_CMDID                  = 0x80B,
+       WMI_READ_RSSI_CMDID                     = 0x80C,
+       WMI_TEMP_SENSE_CMDID                    = 0x80E,
+       WMI_DC_CALIB_CMDID                      = 0x80F,
+       WMI_SEND_TONE_CMDID                     = 0x810,
+       WMI_IQ_TX_CALIB_CMDID                   = 0x811,
+       WMI_IQ_RX_CALIB_CMDID                   = 0x812,
+       WMI_SET_UCODE_IDLE_CMDID                = 0x813,
+       WMI_SET_WORK_MODE_CMDID                 = 0x815,
+       WMI_LO_LEAKAGE_CALIB_CMDID              = 0x816,
+       WMI_MARLON_R_READ_CMDID                 = 0x818,
+       WMI_MARLON_R_WRITE_CMDID                = 0x819,
+       WMI_MARLON_R_TXRX_SEL_CMDID             = 0x81A,
+       MAC_IO_STATIC_PARAMS_CMDID              = 0x81B,
+       MAC_IO_DYNAMIC_PARAMS_CMDID             = 0x81C,
+       WMI_SILENT_RSSI_CALIB_CMDID             = 0x81D,
+       WMI_RF_RX_TEST_CMDID                    = 0x81E,
+       WMI_CFG_RX_CHAIN_CMDID                  = 0x820,
+       WMI_VRING_CFG_CMDID                     = 0x821,
+       WMI_BCAST_VRING_CFG_CMDID               = 0x822,
+       WMI_VRING_BA_EN_CMDID                   = 0x823,
+       WMI_VRING_BA_DIS_CMDID                  = 0x824,
+       WMI_RCP_ADDBA_RESP_CMDID                = 0x825,
+       WMI_RCP_DELBA_CMDID                     = 0x826,
+       WMI_SET_SSID_CMDID                      = 0x827,
+       WMI_GET_SSID_CMDID                      = 0x828,
+       WMI_SET_PCP_CHANNEL_CMDID               = 0x829,
+       WMI_GET_PCP_CHANNEL_CMDID               = 0x82A,
+       WMI_SW_TX_REQ_CMDID                     = 0x82B,
+       WMI_READ_MAC_RXQ_CMDID                  = 0x830,
+       WMI_READ_MAC_TXQ_CMDID                  = 0x831,
+       WMI_WRITE_MAC_RXQ_CMDID                 = 0x832,
+       WMI_WRITE_MAC_TXQ_CMDID                 = 0x833,
+       WMI_WRITE_MAC_XQ_FIELD_CMDID            = 0x834,
+       WMI_MLME_PUSH_CMDID                     = 0x835,
+       WMI_BEAMFORMING_MGMT_CMDID              = 0x836,
+       WMI_BF_TXSS_MGMT_CMDID                  = 0x837,
+       WMI_BF_SM_MGMT_CMDID                    = 0x838,
+       WMI_BF_RXSS_MGMT_CMDID                  = 0x839,
+       WMI_BF_TRIG_CMDID                       = 0x83A,
+       WMI_SET_SECTORS_CMDID                   = 0x849,
+       WMI_MAINTAIN_PAUSE_CMDID                = 0x850,
+       WMI_MAINTAIN_RESUME_CMDID               = 0x851,
+       WMI_RS_MGMT_CMDID                       = 0x852,
+       WMI_RF_MGMT_CMDID                       = 0x853,
+       WMI_THERMAL_THROTTLING_CTRL_CMDID       = 0x854,
+       WMI_THERMAL_THROTTLING_GET_STATUS_CMDID = 0x855,
+       WMI_OTP_READ_CMDID                      = 0x856,
+       WMI_OTP_WRITE_CMDID                     = 0x857,
        /* Performance monitoring commands */
-       WMI_BF_CTRL_CMDID               = 0x0862,
-       WMI_NOTIFY_REQ_CMDID            = 0x0863,
-       WMI_GET_STATUS_CMDID            = 0x0864,
-       WMI_UNIT_TEST_CMDID             = 0x0900,
-       WMI_HICCUP_CMDID                = 0x0901,
-       WMI_FLASH_READ_CMDID            = 0x0902,
-       WMI_FLASH_WRITE_CMDID           = 0x0903,
-       WMI_SECURITY_UNIT_TEST_CMDID    = 0x0904,
-       /*P2P*/
-       WMI_P2P_CFG_CMDID               = 0x0910,
-       WMI_PORT_ALLOCATE_CMDID         = 0x0911,
-       WMI_PORT_DELETE_CMDID           = 0x0912,
-       WMI_POWER_MGMT_CFG_CMDID        = 0x0913,
-       WMI_START_LISTEN_CMDID          = 0x0914,
-       WMI_START_SEARCH_CMDID          = 0x0915,
-       WMI_DISCOVERY_START_CMDID       = 0x0916,
-       WMI_DISCOVERY_STOP_CMDID        = 0x0917,
-       WMI_PCP_START_CMDID             = 0x0918,
-       WMI_PCP_STOP_CMDID              = 0x0919,
-       WMI_GET_PCP_FACTOR_CMDID        = 0x091b,
-
-       WMI_SET_MAC_ADDRESS_CMDID       = 0xf003,
-       WMI_ABORT_SCAN_CMDID            = 0xf007,
-       WMI_SET_PMK_CMDID               = 0xf028,
-
-       WMI_SET_PROMISCUOUS_MODE_CMDID  = 0xf041,
-       WMI_GET_PMK_CMDID               = 0xf048,
-       WMI_SET_PASSPHRASE_CMDID        = 0xf049,
-       WMI_SEND_ASSOC_RES_CMDID        = 0xf04a,
-       WMI_SET_ASSOC_REQ_RELAY_CMDID   = 0xf04b,
-       WMI_EAPOL_TX_CMDID              = 0xf04c,
-       WMI_MAC_ADDR_REQ_CMDID          = 0xf04d,
-       WMI_FW_VER_CMDID                = 0xf04e,
-       WMI_PMC_CMDID                   = 0xf04f,
+       WMI_BF_CTRL_CMDID                       = 0x862,
+       WMI_NOTIFY_REQ_CMDID                    = 0x863,
+       WMI_GET_STATUS_CMDID                    = 0x864,
+       WMI_UNIT_TEST_CMDID                     = 0x900,
+       WMI_HICCUP_CMDID                        = 0x901,
+       WMI_FLASH_READ_CMDID                    = 0x902,
+       WMI_FLASH_WRITE_CMDID                   = 0x903,
+       /* P2P */
+       WMI_P2P_CFG_CMDID                       = 0x910,
+       WMI_PORT_ALLOCATE_CMDID                 = 0x911,
+       WMI_PORT_DELETE_CMDID                   = 0x912,
+       WMI_POWER_MGMT_CFG_CMDID                = 0x913,
+       WMI_START_LISTEN_CMDID                  = 0x914,
+       WMI_START_SEARCH_CMDID                  = 0x915,
+       WMI_DISCOVERY_START_CMDID               = 0x916,
+       WMI_DISCOVERY_STOP_CMDID                = 0x917,
+       WMI_PCP_START_CMDID                     = 0x918,
+       WMI_PCP_STOP_CMDID                      = 0x919,
+       WMI_GET_PCP_FACTOR_CMDID                = 0x91B,
+       WMI_SET_MAC_ADDRESS_CMDID               = 0xF003,
+       WMI_ABORT_SCAN_CMDID                    = 0xF007,
+       WMI_SET_PROMISCUOUS_MODE_CMDID          = 0xF041,
+       WMI_GET_PMK_CMDID                       = 0xF048,
+       WMI_SET_PASSPHRASE_CMDID                = 0xF049,
+       WMI_SEND_ASSOC_RES_CMDID                = 0xF04A,
+       WMI_SET_ASSOC_REQ_RELAY_CMDID           = 0xF04B,
+       WMI_MAC_ADDR_REQ_CMDID                  = 0xF04D,
+       WMI_FW_VER_CMDID                        = 0xF04E,
+       WMI_PMC_CMDID                           = 0xF04F,
 };
 
-/*
- * Commands data structures
- */
-
-/*
- * WMI_CONNECT_CMDID
- */
+/* WMI_CONNECT_CMDID */
 enum wmi_network_type {
        WMI_NETTYPE_INFRA               = 0x01,
        WMI_NETTYPE_ADHOC               = 0x02,
        WMI_NETTYPE_ADHOC_CREATOR       = 0x04,
        WMI_NETTYPE_AP                  = 0x10,
        WMI_NETTYPE_P2P                 = 0x20,
-       WMI_NETTYPE_WBE                 = 0x40, /* PCIE over 60g */
+       /* PCIE over 60g */
+       WMI_NETTYPE_WBE                 = 0x40,
 };
 
 enum wmi_dot11_auth_mode {
-       WMI_AUTH11_OPEN                 = 0x01,
-       WMI_AUTH11_SHARED               = 0x02,
-       WMI_AUTH11_LEAP                 = 0x04,
-       WMI_AUTH11_WSC                  = 0x08,
+       WMI_AUTH11_OPEN         = 0x01,
+       WMI_AUTH11_SHARED       = 0x02,
+       WMI_AUTH11_LEAP         = 0x04,
+       WMI_AUTH11_WSC          = 0x08,
 };
 
 enum wmi_auth_mode {
-       WMI_AUTH_NONE                   = 0x01,
-       WMI_AUTH_WPA                    = 0x02,
-       WMI_AUTH_WPA2                   = 0x04,
-       WMI_AUTH_WPA_PSK                = 0x08,
-       WMI_AUTH_WPA2_PSK               = 0x10,
-       WMI_AUTH_WPA_CCKM               = 0x20,
-       WMI_AUTH_WPA2_CCKM              = 0x40,
+       WMI_AUTH_NONE           = 0x01,
+       WMI_AUTH_WPA            = 0x02,
+       WMI_AUTH_WPA2           = 0x04,
+       WMI_AUTH_WPA_PSK        = 0x08,
+       WMI_AUTH_WPA2_PSK       = 0x10,
+       WMI_AUTH_WPA_CCKM       = 0x20,
+       WMI_AUTH_WPA2_CCKM      = 0x40,
 };
 
 enum wmi_crypto_type {
-       WMI_CRYPT_NONE                  = 0x01,
-       WMI_CRYPT_WEP                   = 0x02,
-       WMI_CRYPT_TKIP                  = 0x04,
-       WMI_CRYPT_AES                   = 0x08,
-       WMI_CRYPT_AES_GCMP              = 0x20,
+       WMI_CRYPT_NONE          = 0x01,
+       WMI_CRYPT_AES_GCMP      = 0x20,
 };
 
 enum wmi_connect_ctrl_flag_bits {
-       WMI_CONNECT_ASSOC_POLICY_USER           = 0x0001,
-       WMI_CONNECT_SEND_REASSOC                = 0x0002,
-       WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER     = 0x0004,
-       WMI_CONNECT_PROFILE_MATCH_DONE          = 0x0008,
-       WMI_CONNECT_IGNORE_AAC_BEACON           = 0x0010,
-       WMI_CONNECT_CSA_FOLLOW_BSS              = 0x0020,
-       WMI_CONNECT_DO_WPA_OFFLOAD              = 0x0040,
-       WMI_CONNECT_DO_NOT_DEAUTH               = 0x0080,
+       WMI_CONNECT_ASSOC_POLICY_USER           = 0x01,
+       WMI_CONNECT_SEND_REASSOC                = 0x02,
+       WMI_CONNECT_IGNORE_WPA_GROUP_CIPHER     = 0x04,
+       WMI_CONNECT_PROFILE_MATCH_DONE          = 0x08,
+       WMI_CONNECT_IGNORE_AAC_BEACON           = 0x10,
+       WMI_CONNECT_CSA_FOLLOW_BSS              = 0x20,
+       WMI_CONNECT_DO_WPA_OFFLOAD              = 0x40,
+       WMI_CONNECT_DO_NOT_DEAUTH               = 0x80,
 };
 
-#define WMI_MAX_SSID_LEN    (32)
+#define WMI_MAX_SSID_LEN       (32)
 
+/* WMI_CONNECT_CMDID */
 struct wmi_connect_cmd {
        u8 network_type;
        u8 dot11_auth_mode;
@@ -216,31 +226,17 @@ struct wmi_connect_cmd {
        u8 reserved1[2];
 } __packed;
 
-/*
- * WMI_DISCONNECT_STA_CMDID
- */
+/* WMI_DISCONNECT_STA_CMDID */
 struct wmi_disconnect_sta_cmd {
        u8 dst_mac[WMI_MAC_LEN];
        __le16 disconnect_reason;
 } __packed;
 
-/*
- * WMI_SET_PMK_CMDID
- */
-
-#define WMI_MIN_KEY_INDEX      (0)
 #define WMI_MAX_KEY_INDEX      (3)
 #define WMI_MAX_KEY_LEN                (32)
 #define WMI_PASSPHRASE_LEN     (64)
-#define WMI_PMK_LEN            (32)
-
-struct  wmi_set_pmk_cmd {
-       u8 pmk[WMI_PMK_LEN];
-} __packed;
 
-/*
- * WMI_SET_PASSPHRASE_CMDID
- */
+/* WMI_SET_PASSPHRASE_CMDID */
 struct wmi_set_passphrase_cmd {
        u8 ssid[WMI_MAX_SSID_LEN];
        u8 passphrase[WMI_PASSPHRASE_LEN];
@@ -248,36 +244,34 @@ struct wmi_set_passphrase_cmd {
        u8 passphrase_len;
 } __packed;
 
-/*
- * WMI_ADD_CIPHER_KEY_CMDID
- */
+/* WMI_ADD_CIPHER_KEY_CMDID */
 enum wmi_key_usage {
-       WMI_KEY_USE_PAIRWISE    = 0,
-       WMI_KEY_USE_RX_GROUP    = 1,
-       WMI_KEY_USE_TX_GROUP    = 2,
+       WMI_KEY_USE_PAIRWISE    = 0x00,
+       WMI_KEY_USE_RX_GROUP    = 0x01,
+       WMI_KEY_USE_TX_GROUP    = 0x02,
 };
 
 struct wmi_add_cipher_key_cmd {
        u8 key_index;
        u8 key_type;
-       u8 key_usage;           /* enum wmi_key_usage */
+       /* enum wmi_key_usage */
+       u8 key_usage;
        u8 key_len;
-       u8 key_rsc[8];          /* key replay sequence counter */
+       /* key replay sequence counter */
+       u8 key_rsc[8];
        u8 key[WMI_MAX_KEY_LEN];
-       u8 key_op_ctrl;         /* Additional Key Control information */
+       /* Additional Key Control information */
+       u8 key_op_ctrl;
        u8 mac[WMI_MAC_LEN];
 } __packed;
 
-/*
- * WMI_DELETE_CIPHER_KEY_CMDID
- */
+/* WMI_DELETE_CIPHER_KEY_CMDID */
 struct wmi_delete_cipher_key_cmd {
        u8 key_index;
        u8 mac[WMI_MAC_LEN];
 } __packed;
 
-/*
- * WMI_START_SCAN_CMDID
+/* WMI_START_SCAN_CMDID
  *
  * Start L1 scan operation
  *
@@ -286,146 +280,142 @@ struct wmi_delete_cipher_key_cmd {
  * - WMI_SCAN_COMPLETE_EVENTID
  */
 enum wmi_scan_type {
-       WMI_LONG_SCAN           = 0,
-       WMI_SHORT_SCAN          = 1,
-       WMI_PBC_SCAN            = 2,
-       WMI_DIRECT_SCAN         = 3,
-       WMI_ACTIVE_SCAN         = 4,
+       WMI_ACTIVE_SCAN         = 0x00,
+       WMI_SHORT_SCAN          = 0x01,
+       WMI_PASSIVE_SCAN        = 0x02,
+       WMI_DIRECT_SCAN         = 0x03,
+       WMI_LONG_SCAN           = 0x04,
 };
 
+/* WMI_START_SCAN_CMDID */
 struct wmi_start_scan_cmd {
-       u8 direct_scan_mac_addr[6];
-       u8 reserved[2];
-       __le32 home_dwell_time; /* Max duration in the home channel(ms) */
-       __le32 force_scan_interval;     /* Time interval between scans (ms)*/
-       u8 scan_type;           /* wmi_scan_type */
-       u8 num_channels;                /* how many channels follow */
+       u8 direct_scan_mac_addr[WMI_MAC_LEN];
+       /* DMG Beacon frame is transmitted during active scanning */
+       u8 discovery_mode;
+       /* reserved */
+       u8 reserved;
+       /* Max duration in the home channel(ms) */
+       __le32 dwell_time;
+       /* Time interval between scans (ms) */
+       __le32 force_scan_interval;
+       /* enum wmi_scan_type */
+       u8 scan_type;
+       /* how many channels follow */
+       u8 num_channels;
+       /* channels ID's:
+        * 0 - 58320 MHz
+        * 1 - 60480 MHz
+        * 2 - 62640 MHz
+        */
        struct {
                u8 channel;
                u8 reserved;
-       } channel_list[0];      /* channels ID's */
-                               /* 0 - 58320 MHz */
-                               /* 1 - 60480 MHz */
-                               /* 2 - 62640 MHz */
+       } channel_list[0];
 } __packed;
 
-/*
- * WMI_SET_PROBED_SSID_CMDID
- */
+/* WMI_SET_PROBED_SSID_CMDID */
 #define MAX_PROBED_SSID_INDEX  (3)
 
 enum wmi_ssid_flag {
-       WMI_SSID_FLAG_DISABLE   = 0,    /* disables entry */
-       WMI_SSID_FLAG_SPECIFIC  = 1,    /* probes specified ssid */
-       WMI_SSID_FLAG_ANY       = 2,    /* probes for any ssid */
+       /* disables entry */
+       WMI_SSID_FLAG_DISABLE   = 0x00,
+       /* probes specified ssid */
+       WMI_SSID_FLAG_SPECIFIC  = 0x01,
+       /* probes for any ssid */
+       WMI_SSID_FLAG_ANY       = 0x02,
 };
 
 struct wmi_probed_ssid_cmd {
-       u8 entry_index;                 /* 0 to MAX_PROBED_SSID_INDEX */
-       u8 flag;                        /* enum wmi_ssid_flag */
+       /* 0 to MAX_PROBED_SSID_INDEX */
+       u8 entry_index;
+       /* enum wmi_ssid_flag */
+       u8 flag;
        u8 ssid_len;
        u8 ssid[WMI_MAX_SSID_LEN];
 } __packed;
 
-/*
- * WMI_SET_APPIE_CMDID
+/* WMI_SET_APPIE_CMDID
  * Add Application specified IE to a management frame
  */
-#define WMI_MAX_IE_LEN         (1024)
+#define WMI_MAX_IE_LEN (1024)
 
-/*
- * Frame Types
- */
+/* Frame Types */
 enum wmi_mgmt_frame_type {
-       WMI_FRAME_BEACON        = 0,
-       WMI_FRAME_PROBE_REQ     = 1,
-       WMI_FRAME_PROBE_RESP    = 2,
-       WMI_FRAME_ASSOC_REQ     = 3,
-       WMI_FRAME_ASSOC_RESP    = 4,
-       WMI_NUM_MGMT_FRAME,
+       WMI_FRAME_BEACON        = 0x00,
+       WMI_FRAME_PROBE_REQ     = 0x01,
+       WMI_FRAME_PROBE_RESP    = 0x02,
+       WMI_FRAME_ASSOC_REQ     = 0x03,
+       WMI_FRAME_ASSOC_RESP    = 0x04,
+       WMI_NUM_MGMT_FRAME      = 0x05,
 };
 
 struct wmi_set_appie_cmd {
-       u8 mgmt_frm_type;       /* enum wmi_mgmt_frame_type */
+       /* enum wmi_mgmt_frame_type */
+       u8 mgmt_frm_type;
        u8 reserved;
-       __le16 ie_len;  /* Length of the IE to be added to MGMT frame */
+       /* Length of the IE to be added to MGMT frame */
+       __le16 ie_len;
        u8 ie_info[0];
 } __packed;
 
-/*
- * WMI_PXMT_RANGE_CFG_CMDID
- */
+/* WMI_PXMT_RANGE_CFG_CMDID */
 struct wmi_pxmt_range_cfg_cmd {
        u8 dst_mac[WMI_MAC_LEN];
        __le16 range;
 } __packed;
 
-/*
- * WMI_PXMT_SNR2_RANGE_CFG_CMDID
- */
+/* WMI_PXMT_SNR2_RANGE_CFG_CMDID */
 struct wmi_pxmt_snr2_range_cfg_cmd {
-       s8 snr2range_arr[WMI_PROX_RANGE_NUM-1];
+       s8 snr2range_arr[2];
 } __packed;
 
-/*
- * WMI_RF_MGMT_CMDID
- */
+/* WMI_RF_MGMT_CMDID */
 enum wmi_rf_mgmt_type {
-       WMI_RF_MGMT_W_DISABLE   = 0,
-       WMI_RF_MGMT_W_ENABLE    = 1,
-       WMI_RF_MGMT_GET_STATUS  = 2,
+       WMI_RF_MGMT_W_DISABLE   = 0x00,
+       WMI_RF_MGMT_W_ENABLE    = 0x01,
+       WMI_RF_MGMT_GET_STATUS  = 0x02,
 };
 
+/* WMI_RF_MGMT_CMDID */
 struct wmi_rf_mgmt_cmd {
        __le32 rf_mgmt_type;
 } __packed;
 
-/*
- * WMI_THERMAL_THROTTLING_CTRL_CMDID
- */
+/* WMI_THERMAL_THROTTLING_CTRL_CMDID */
 #define THERMAL_THROTTLING_USE_DEFAULT_MAX_TXOP_LENGTH (0xFFFFFFFF)
 
+/* WMI_THERMAL_THROTTLING_CTRL_CMDID */
 struct wmi_thermal_throttling_ctrl_cmd {
        __le32 time_on_usec;
        __le32 time_off_usec;
        __le32 max_txop_length_usec;
 } __packed;
 
-/*
- * WMI_RF_RX_TEST_CMDID
- */
+/* WMI_RF_RX_TEST_CMDID */
 struct wmi_rf_rx_test_cmd {
        __le32 sector;
 } __packed;
 
-/*
- * WMI_CORR_MEASURE_CMDID
- */
+/* WMI_CORR_MEASURE_CMDID */
 struct wmi_corr_measure_cmd {
-       s32 freq_mhz;
+       __le32 freq_mhz;
        __le32 length_samples;
        __le32 iterations;
 } __packed;
 
-/*
- * WMI_SET_SSID_CMDID
- */
+/* WMI_SET_SSID_CMDID */
 struct wmi_set_ssid_cmd {
        __le32 ssid_len;
        u8 ssid[WMI_MAX_SSID_LEN];
 } __packed;
 
-/*
- * WMI_SET_PCP_CHANNEL_CMDID
- */
+/* WMI_SET_PCP_CHANNEL_CMDID */
 struct wmi_set_pcp_channel_cmd {
        u8 channel;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_BCON_CTRL_CMDID
- */
+/* WMI_BCON_CTRL_CMDID */
 struct wmi_bcon_ctrl_cmd {
        __le16 bcon_interval;
        __le16 frag_num;
@@ -434,214 +424,192 @@ struct wmi_bcon_ctrl_cmd {
        u8 pcp_max_assoc_sta;
        u8 disable_sec_offload;
        u8 disable_sec;
+       u8 hidden_ssid;
+       u8 is_go;
+       u8 reserved[2];
 } __packed;
 
-/******* P2P ***********/
-
-/*
- * WMI_PORT_ALLOCATE_CMDID
- */
+/* WMI_PORT_ALLOCATE_CMDID */
 enum wmi_port_role {
-       WMI_PORT_STA            = 0,
-       WMI_PORT_PCP            = 1,
-       WMI_PORT_AP             = 2,
-       WMI_PORT_P2P_DEV        = 3,
-       WMI_PORT_P2P_CLIENT     = 4,
-       WMI_PORT_P2P_GO         = 5,
+       WMI_PORT_STA            = 0x00,
+       WMI_PORT_PCP            = 0x01,
+       WMI_PORT_AP             = 0x02,
+       WMI_PORT_P2P_DEV        = 0x03,
+       WMI_PORT_P2P_CLIENT     = 0x04,
+       WMI_PORT_P2P_GO         = 0x05,
 };
 
+/* WMI_PORT_ALLOCATE_CMDID */
 struct wmi_port_allocate_cmd {
        u8 mac[WMI_MAC_LEN];
        u8 port_role;
        u8 mid;
 } __packed;
 
-/*
- * WMI_PORT_DELETE_CMDID
- */
-struct wmi_delete_port_cmd {
+/* WMI_PORT_DELETE_CMDID */
+struct wmi_port_delete_cmd {
        u8 mid;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_P2P_CFG_CMDID
- */
+/* WMI_P2P_CFG_CMDID */
 enum wmi_discovery_mode {
-       WMI_DISCOVERY_MODE_NON_OFFLOAD  = 0,
-       WMI_DISCOVERY_MODE_OFFLOAD      = 1,
-       WMI_DISCOVERY_MODE_PEER2PEER    = 2,
+       WMI_DISCOVERY_MODE_NON_OFFLOAD  = 0x00,
+       WMI_DISCOVERY_MODE_OFFLOAD      = 0x01,
+       WMI_DISCOVERY_MODE_PEER2PEER    = 0x02,
 };
 
 struct wmi_p2p_cfg_cmd {
-       u8 discovery_mode;      /* wmi_discovery_mode */
+       /* enum wmi_discovery_mode */
+       u8 discovery_mode;
        u8 channel;
-       __le16 bcon_interval; /* base to listen/search duration calculation */
+       /* base to listen/search duration calculation */
+       __le16 bcon_interval;
 } __packed;
 
-/*
- * WMI_POWER_MGMT_CFG_CMDID
- */
+/* WMI_POWER_MGMT_CFG_CMDID */
 enum wmi_power_source_type {
-       WMI_POWER_SOURCE_BATTERY        = 0,
-       WMI_POWER_SOURCE_OTHER          = 1,
+       WMI_POWER_SOURCE_BATTERY        = 0x00,
+       WMI_POWER_SOURCE_OTHER          = 0x01,
 };
 
 struct wmi_power_mgmt_cfg_cmd {
-       u8 power_source;        /* wmi_power_source_type */
+       /* enum wmi_power_source_type */
+       u8 power_source;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_PCP_START_CMDID
- */
-
-enum wmi_hidden_ssid {
-       WMI_HIDDEN_SSID_DISABLED        = 0,
-       WMI_HIDDEN_SSID_SEND_EMPTY      = 1,
-       WMI_HIDDEN_SSID_CLEAR   = 2,
-};
-
+/* WMI_PCP_START_CMDID */
 struct wmi_pcp_start_cmd {
        __le16 bcon_interval;
        u8 pcp_max_assoc_sta;
        u8 hidden_ssid;
-       u8 reserved0[8];
+       u8 is_go;
+       u8 reserved0[7];
        u8 network_type;
        u8 channel;
        u8 disable_sec_offload;
        u8 disable_sec;
 } __packed;
 
-/*
- * WMI_SW_TX_REQ_CMDID
- */
+/* WMI_SW_TX_REQ_CMDID */
 struct wmi_sw_tx_req_cmd {
        u8 dst_mac[WMI_MAC_LEN];
        __le16 len;
        u8 payload[0];
 } __packed;
 
-/*
- * WMI_VRING_CFG_CMDID
- */
-
 struct wmi_sw_ring_cfg {
        __le64 ring_mem_base;
        __le16 ring_size;
        __le16 max_mpdu_size;
 } __packed;
 
+/* wmi_vring_cfg_schd */
 struct wmi_vring_cfg_schd {
        __le16 priority;
        __le16 timeslot_us;
 } __packed;
 
 enum wmi_vring_cfg_encap_trans_type {
-       WMI_VRING_ENC_TYPE_802_3                = 0,
-       WMI_VRING_ENC_TYPE_NATIVE_WIFI          = 1,
+       WMI_VRING_ENC_TYPE_802_3        = 0x00,
+       WMI_VRING_ENC_TYPE_NATIVE_WIFI  = 0x01,
 };
 
 enum wmi_vring_cfg_ds_cfg {
-       WMI_VRING_DS_PBSS                       = 0,
-       WMI_VRING_DS_STATION                    = 1,
-       WMI_VRING_DS_AP                         = 2,
-       WMI_VRING_DS_ADDR4                      = 3,
+       WMI_VRING_DS_PBSS       = 0x00,
+       WMI_VRING_DS_STATION    = 0x01,
+       WMI_VRING_DS_AP         = 0x02,
+       WMI_VRING_DS_ADDR4      = 0x03,
 };
 
 enum wmi_vring_cfg_nwifi_ds_trans_type {
-       WMI_NWIFI_TX_TRANS_MODE_NO              = 0,
-       WMI_NWIFI_TX_TRANS_MODE_AP2PBSS         = 1,
-       WMI_NWIFI_TX_TRANS_MODE_STA2PBSS        = 2,
+       WMI_NWIFI_TX_TRANS_MODE_NO              = 0x00,
+       WMI_NWIFI_TX_TRANS_MODE_AP2PBSS         = 0x01,
+       WMI_NWIFI_TX_TRANS_MODE_STA2PBSS        = 0x02,
 };
 
 enum wmi_vring_cfg_schd_params_priority {
-       WMI_SCH_PRIO_REGULAR                    = 0,
-       WMI_SCH_PRIO_HIGH                       = 1,
+       WMI_SCH_PRIO_REGULAR    = 0x00,
+       WMI_SCH_PRIO_HIGH       = 0x01,
 };
 
-#define CIDXTID_CID_POS (0)
-#define CIDXTID_CID_LEN (4)
-#define CIDXTID_CID_MSK (0xF)
-#define CIDXTID_TID_POS (4)
-#define CIDXTID_TID_LEN (4)
-#define CIDXTID_TID_MSK (0xF0)
+#define CIDXTID_CID_POS                                (0)
+#define CIDXTID_CID_LEN                                (4)
+#define CIDXTID_CID_MSK                                (0xF)
+#define CIDXTID_TID_POS                                (4)
+#define CIDXTID_TID_LEN                                (4)
+#define CIDXTID_TID_MSK                                (0xF0)
+#define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS     (0)
+#define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN     (1)
+#define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK     (0x1)
+#define VRING_CFG_MAC_CTRL_AGGR_EN_POS         (1)
+#define VRING_CFG_MAC_CTRL_AGGR_EN_LEN         (1)
+#define VRING_CFG_MAC_CTRL_AGGR_EN_MSK         (0x2)
+#define VRING_CFG_TO_RESOLUTION_VALUE_POS      (0)
+#define VRING_CFG_TO_RESOLUTION_VALUE_LEN      (6)
+#define VRING_CFG_TO_RESOLUTION_VALUE_MSK      (0x3F)
 
 struct wmi_vring_cfg {
        struct wmi_sw_ring_cfg tx_sw_ring;
-       u8 ringid;                              /* 0-23 vrings */
-
+       /* 0-23 vrings */
+       u8 ringid;
        u8 cidxtid;
-
        u8 encap_trans_type;
-       u8 ds_cfg;                              /* 802.3 DS cfg */
+       /* 802.3 DS cfg */
+       u8 ds_cfg;
        u8 nwifi_ds_trans_type;
-
-       #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0)
-       #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1)
-       #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1)
-       #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1)
-       #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1)
-       #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2)
        u8 mac_ctrl;
-
-       #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0)
-       #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6)
-       #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F)
        u8 to_resolution;
        u8 agg_max_wsize;
        struct wmi_vring_cfg_schd schd_params;
 } __packed;
 
 enum wmi_vring_cfg_cmd_action {
-       WMI_VRING_CMD_ADD                       = 0,
-       WMI_VRING_CMD_MODIFY                    = 1,
-       WMI_VRING_CMD_DELETE                    = 2,
+       WMI_VRING_CMD_ADD       = 0x00,
+       WMI_VRING_CMD_MODIFY    = 0x01,
+       WMI_VRING_CMD_DELETE    = 0x02,
 };
 
+/* WMI_VRING_CFG_CMDID */
 struct wmi_vring_cfg_cmd {
        __le32 action;
        struct wmi_vring_cfg vring_cfg;
 } __packed;
 
-/*
- * WMI_BCAST_VRING_CFG_CMDID
- */
 struct wmi_bcast_vring_cfg {
        struct wmi_sw_ring_cfg tx_sw_ring;
-       u8 ringid;                              /* 0-23 vrings */
+       /* 0-23 vrings */
+       u8 ringid;
        u8 encap_trans_type;
-       u8 ds_cfg;                              /* 802.3 DS cfg */
+       /* 802.3 DS cfg */
+       u8 ds_cfg;
        u8 nwifi_ds_trans_type;
 } __packed;
 
+/* WMI_BCAST_VRING_CFG_CMDID */
 struct wmi_bcast_vring_cfg_cmd {
        __le32 action;
        struct wmi_bcast_vring_cfg vring_cfg;
 } __packed;
 
-/*
- * WMI_VRING_BA_EN_CMDID
- */
+/* WMI_VRING_BA_EN_CMDID */
 struct wmi_vring_ba_en_cmd {
        u8 ringid;
        u8 agg_max_wsize;
        __le16 ba_timeout;
        u8 amsdu;
+       u8 reserved[3];
 } __packed;
 
-/*
- * WMI_VRING_BA_DIS_CMDID
- */
+/* WMI_VRING_BA_DIS_CMDID */
 struct wmi_vring_ba_dis_cmd {
        u8 ringid;
        u8 reserved;
        __le16 reason;
 } __packed;
 
-/*
- * WMI_NOTIFY_REQ_CMDID
- */
+/* WMI_NOTIFY_REQ_CMDID */
 struct wmi_notify_req_cmd {
        u8 cid;
        u8 year;
@@ -654,102 +622,100 @@ struct wmi_notify_req_cmd {
        u8 miliseconds;
 } __packed;
 
-/*
- * WMI_CFG_RX_CHAIN_CMDID
- */
+/* WMI_CFG_RX_CHAIN_CMDID */
 enum wmi_sniffer_cfg_mode {
-       WMI_SNIFFER_OFF                         = 0,
-       WMI_SNIFFER_ON                          = 1,
+       WMI_SNIFFER_OFF = 0x00,
+       WMI_SNIFFER_ON  = 0x01,
 };
 
 enum wmi_sniffer_cfg_phy_info_mode {
-       WMI_SNIFFER_PHY_INFO_DISABLED           = 0,
-       WMI_SNIFFER_PHY_INFO_ENABLED            = 1,
+       WMI_SNIFFER_PHY_INFO_DISABLED   = 0x00,
+       WMI_SNIFFER_PHY_INFO_ENABLED    = 0x01,
 };
 
 enum wmi_sniffer_cfg_phy_support {
-       WMI_SNIFFER_CP                          = 0,
-       WMI_SNIFFER_DP                          = 1,
-       WMI_SNIFFER_BOTH_PHYS                   = 2,
+       WMI_SNIFFER_CP          = 0x00,
+       WMI_SNIFFER_DP          = 0x01,
+       WMI_SNIFFER_BOTH_PHYS   = 0x02,
 };
 
+/* wmi_sniffer_cfg */
 struct wmi_sniffer_cfg {
-       __le32 mode;            /* enum wmi_sniffer_cfg_mode */
-       __le32 phy_info_mode;   /* enum wmi_sniffer_cfg_phy_info_mode */
-       __le32 phy_support;     /* enum wmi_sniffer_cfg_phy_support */
+       /* enum wmi_sniffer_cfg_mode */
+       __le32 mode;
+       /* enum wmi_sniffer_cfg_phy_info_mode */
+       __le32 phy_info_mode;
+       /* enum wmi_sniffer_cfg_phy_support */
+       __le32 phy_support;
        u8 channel;
        u8 reserved[3];
 } __packed;
 
 enum wmi_cfg_rx_chain_cmd_action {
-       WMI_RX_CHAIN_ADD                        = 0,
-       WMI_RX_CHAIN_DEL                        = 1,
+       WMI_RX_CHAIN_ADD        = 0x00,
+       WMI_RX_CHAIN_DEL        = 0x01,
 };
 
 enum wmi_cfg_rx_chain_cmd_decap_trans_type {
-       WMI_DECAP_TYPE_802_3                    = 0,
-       WMI_DECAP_TYPE_NATIVE_WIFI              = 1,
-       WMI_DECAP_TYPE_NONE                     = 2,
+       WMI_DECAP_TYPE_802_3            = 0x00,
+       WMI_DECAP_TYPE_NATIVE_WIFI      = 0x01,
+       WMI_DECAP_TYPE_NONE             = 0x02,
 };
 
 enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type {
-       WMI_NWIFI_RX_TRANS_MODE_NO              = 0,
-       WMI_NWIFI_RX_TRANS_MODE_PBSS2AP         = 1,
-       WMI_NWIFI_RX_TRANS_MODE_PBSS2STA        = 2,
+       WMI_NWIFI_RX_TRANS_MODE_NO              = 0x00,
+       WMI_NWIFI_RX_TRANS_MODE_PBSS2AP         = 0x01,
+       WMI_NWIFI_RX_TRANS_MODE_PBSS2STA        = 0x02,
 };
 
 enum wmi_cfg_rx_chain_cmd_reorder_type {
-       WMI_RX_HW_REORDER 0,
-       WMI_RX_SW_REORDER 1,
+       WMI_RX_HW_REORDER       = 0x00,
+       WMI_RX_SW_REORDER       = 0x01,
 };
 
+#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS   (0)
+#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN   (1)
+#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK   (0x1)
+#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS            (1)
+#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN            (1)
+#define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK            (0x2)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS           (0)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN           (1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK           (0x1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS            (1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN            (1)
+#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK            (0x2)
+#define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS                        (0)
+#define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN                        (1)
+#define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK                        (0x1)
+#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS               (1)
+#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN               (1)
+#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK               (0x2)
+#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS          (0)
+#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN          (1)
+#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK          (0x1)
+#define RING_CTRL_OVERRIDE_WB_THRSH_POS                        (1)
+#define RING_CTRL_OVERRIDE_WB_THRSH_LEN                        (1)
+#define RING_CTRL_OVERRIDE_WB_THRSH_MSK                        (0x2)
+#define RING_CTRL_OVERRIDE_ITR_THRSH_POS               (2)
+#define RING_CTRL_OVERRIDE_ITR_THRSH_LEN               (1)
+#define RING_CTRL_OVERRIDE_ITR_THRSH_MSK               (0x4)
+#define RING_CTRL_OVERRIDE_HOST_THRSH_POS              (3)
+#define RING_CTRL_OVERRIDE_HOST_THRSH_LEN              (1)
+#define RING_CTRL_OVERRIDE_HOST_THRSH_MSK              (0x8)
+
+/* WMI_CFG_RX_CHAIN_CMDID */
 struct wmi_cfg_rx_chain_cmd {
        __le32 action;
        struct wmi_sw_ring_cfg rx_sw_ring;
        u8 mid;
        u8 decap_trans_type;
-
-       #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0)
-       #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1)
-       #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1)
-       #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_POS (1)
-       #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_LEN (1)
-       #define L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK (0x2)
        u8 l2_802_3_offload_ctrl;
-
-       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0)
-       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1)
-       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1)
-       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1)
-       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1)
-       #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2)
        u8 l2_nwifi_offload_ctrl;
-
        u8 vlan_id;
        u8 nwifi_ds_trans_type;
-
-       #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0)
-       #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1)
-       #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1)
-       #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1)
-       #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1)
-       #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2)
        u8 l3_l4_ctrl;
-
-       #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0)
-       #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1)
-       #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1)
-       #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1)
-       #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1)
-       #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2)
-       #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2)
-       #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1)
-       #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4)
-       #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3)
-       #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1)
-       #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8)
        u8 ring_ctrl;
-
        __le16 prefetch_thrsh;
        __le16 wb_thrsh;
        __le32 itr_value;
@@ -757,31 +723,27 @@ struct wmi_cfg_rx_chain_cmd {
        u8 reorder_type;
        u8 reserved;
        struct wmi_sniffer_cfg sniffer_cfg;
+       __le16 max_rx_pl_per_desc;
 } __packed;
 
-/*
- * WMI_RCP_ADDBA_RESP_CMDID
- */
+/* WMI_RCP_ADDBA_RESP_CMDID */
 struct wmi_rcp_addba_resp_cmd {
        u8 cidxtid;
        u8 dialog_token;
        __le16 status_code;
-       __le16 ba_param_set;    /* ieee80211_ba_parameterset field to send */
+       /* ieee80211_ba_parameterset field to send */
+       __le16 ba_param_set;
        __le16 ba_timeout;
 } __packed;
 
-/*
- * WMI_RCP_DELBA_CMDID
- */
+/* WMI_RCP_DELBA_CMDID */
 struct wmi_rcp_delba_cmd {
        u8 cidxtid;
        u8 reserved;
        __le16 reason;
 } __packed;
 
-/*
- * WMI_RCP_ADDBA_REQ_CMDID
- */
+/* WMI_RCP_ADDBA_REQ_CMDID */
 struct wmi_rcp_addba_req_cmd {
        u8 cidxtid;
        u8 dialog_token;
@@ -792,32 +754,16 @@ struct wmi_rcp_addba_req_cmd {
        __le16 ba_seq_ctrl;
 } __packed;
 
-/*
- * WMI_SET_MAC_ADDRESS_CMDID
- */
+/* WMI_SET_MAC_ADDRESS_CMDID */
 struct wmi_set_mac_address_cmd {
        u8 mac[WMI_MAC_LEN];
        u8 reserved[2];
 } __packed;
 
-/*
-* WMI_EAPOL_TX_CMDID
-*/
-struct wmi_eapol_tx_cmd {
-       u8 dst_mac[WMI_MAC_LEN];
-       __le16 eapol_len;
-       u8 eapol[0];
-} __packed;
-
-/*
- * WMI_ECHO_CMDID
- *
+/* WMI_ECHO_CMDID
  * Check FW is alive
- *
  * WMI_DEEP_ECHO_CMDID
- *
  * Check FW and ucode are alive
- *
  * Returned event: WMI_ECHO_RSP_EVENTID
  * same event for both commands
  */
@@ -825,70 +771,79 @@ struct wmi_echo_cmd {
        __le32 value;
 } __packed;
 
-/*
- * WMI_TEMP_SENSE_CMDID
+/* WMI_OTP_READ_CMDID */
+struct wmi_otp_read_cmd {
+       __le32 addr;
+       __le32 size;
+       __le32 values;
+} __packed;
+
+/* WMI_OTP_WRITE_CMDID */
+struct wmi_otp_write_cmd {
+       __le32 addr;
+       __le32 size;
+       __le32 values;
+} __packed;
+
+/* WMI_TEMP_SENSE_CMDID
  *
  * Measure MAC and radio temperatures
+ *
+ * Possible modes for temperature measurement
  */
-
-/* Possible modes for temperature measurement */
 enum wmi_temperature_measure_mode {
-       TEMPERATURE_USE_OLD_VALUE       = 0x1,
-       TEMPERATURE_MEASURE_NOW         = 0x2,
+       TEMPERATURE_USE_OLD_VALUE       = 0x01,
+       TEMPERATURE_MEASURE_NOW         = 0x02,
 };
 
+/* WMI_TEMP_SENSE_CMDID */
 struct wmi_temp_sense_cmd {
        __le32 measure_baseband_en;
        __le32 measure_rf_en;
        __le32 measure_mode;
 } __packed;
 
-/*
- * WMI_PMC_CMDID
- */
-enum wmi_pmc_op_e {
-       WMI_PMC_ALLOCATE = 0,
-       WMI_PMC_RELEASE = 1,
+enum wmi_pmc_op {
+       WMI_PMC_ALLOCATE        = 0x00,
+       WMI_PMC_RELEASE         = 0x01,
 };
 
+/* WMI_PMC_CMDID */
 struct wmi_pmc_cmd {
-       u8 op;          /* enum wmi_pmc_cmd_op_type */
+       /* enum wmi_pmc_cmd_op_type */
+       u8 op;
        u8 reserved;
        __le16 ring_size;
        __le64 mem_base;
 } __packed;
 
-/*
- * WMI Events
- */
-
-/*
+/* WMI Events
  * List of Events (target to host)
  */
 enum wmi_event_id {
        WMI_READY_EVENTID                       = 0x1001,
        WMI_CONNECT_EVENTID                     = 0x1002,
        WMI_DISCONNECT_EVENTID                  = 0x1003,
-       WMI_SCAN_COMPLETE_EVENTID               = 0x100a,
-       WMI_REPORT_STATISTICS_EVENTID           = 0x100b,
+       WMI_SCAN_COMPLETE_EVENTID               = 0x100A,
+       WMI_REPORT_STATISTICS_EVENTID           = 0x100B,
        WMI_RD_MEM_RSP_EVENTID                  = 0x1800,
        WMI_FW_READY_EVENTID                    = 0x1801,
-       WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID      = 0x0200,
+       WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID      = 0x200,
        WMI_ECHO_RSP_EVENTID                    = 0x1803,
-       WMI_FS_TUNE_DONE_EVENTID                = 0x180a,
-       WMI_CORR_MEASURE_EVENTID                = 0x180b,
-       WMI_READ_RSSI_EVENTID                   = 0x180c,
-       WMI_TEMP_SENSE_DONE_EVENTID             = 0x180e,
-       WMI_DC_CALIB_DONE_EVENTID               = 0x180f,
+       WMI_FS_TUNE_DONE_EVENTID                = 0x180A,
+       WMI_CORR_MEASURE_EVENTID                = 0x180B,
+       WMI_READ_RSSI_EVENTID                   = 0x180C,
+       WMI_TEMP_SENSE_DONE_EVENTID             = 0x180E,
+       WMI_DC_CALIB_DONE_EVENTID               = 0x180F,
        WMI_IQ_TX_CALIB_DONE_EVENTID            = 0x1811,
        WMI_IQ_RX_CALIB_DONE_EVENTID            = 0x1812,
        WMI_SET_WORK_MODE_DONE_EVENTID          = 0x1815,
        WMI_LO_LEAKAGE_CALIB_DONE_EVENTID       = 0x1816,
        WMI_MARLON_R_READ_DONE_EVENTID          = 0x1818,
        WMI_MARLON_R_WRITE_DONE_EVENTID         = 0x1819,
-       WMI_MARLON_R_TXRX_SEL_DONE_EVENTID      = 0x181a,
-       WMI_SILENT_RSSI_CALIB_DONE_EVENTID      = 0x181d,
-       WMI_RF_RX_TEST_DONE_EVENTID             = 0x181e,
+       WMI_MARLON_R_TXRX_SEL_DONE_EVENTID      = 0x181A,
+       WMI_SILENT_RSSI_CALIB_DONE_EVENTID      = 0x181D,
+       WMI_RF_RX_TEST_DONE_EVENTID             = 0x181E,
        WMI_CFG_RX_CHAIN_DONE_EVENTID           = 0x1820,
        WMI_VRING_CFG_DONE_EVENTID              = 0x1821,
        WMI_BA_STATUS_EVENTID                   = 0x1823,
@@ -896,15 +851,13 @@ enum wmi_event_id {
        WMI_RCP_ADDBA_RESP_SENT_EVENTID         = 0x1825,
        WMI_DELBA_EVENTID                       = 0x1826,
        WMI_GET_SSID_EVENTID                    = 0x1828,
-       WMI_GET_PCP_CHANNEL_EVENTID             = 0x182a,
-       WMI_SW_TX_COMPLETE_EVENTID              = 0x182b,
-
+       WMI_GET_PCP_CHANNEL_EVENTID             = 0x182A,
+       WMI_SW_TX_COMPLETE_EVENTID              = 0x182B,
        WMI_READ_MAC_RXQ_EVENTID                = 0x1830,
        WMI_READ_MAC_TXQ_EVENTID                = 0x1831,
        WMI_WRITE_MAC_RXQ_EVENTID               = 0x1832,
        WMI_WRITE_MAC_TXQ_EVENTID               = 0x1833,
        WMI_WRITE_MAC_XQ_FIELD_EVENTID          = 0x1834,
-
        WMI_BEAMFORMING_MGMT_DONE_EVENTID       = 0x1836,
        WMI_BF_TXSS_MGMT_DONE_EVENTID           = 0x1837,
        WMI_BF_RXSS_MGMT_DONE_EVENTID           = 0x1839,
@@ -914,20 +867,18 @@ enum wmi_event_id {
        WMI_BF_SM_MGMT_DONE_EVENTID             = 0x1838,
        WMI_RX_MGMT_PACKET_EVENTID              = 0x1840,
        WMI_TX_MGMT_PACKET_EVENTID              = 0x1841,
-
+       WMI_OTP_READ_RESULT_EVENTID             = 0x1856,
        /* Performance monitoring events */
        WMI_DATA_PORT_OPEN_EVENTID              = 0x1860,
        WMI_WBE_LINK_DOWN_EVENTID               = 0x1861,
-
        WMI_BF_CTRL_DONE_EVENTID                = 0x1862,
        WMI_NOTIFY_REQ_DONE_EVENTID             = 0x1863,
        WMI_GET_STATUS_DONE_EVENTID             = 0x1864,
        WMI_VRING_EN_EVENTID                    = 0x1865,
-
        WMI_UNIT_TEST_EVENTID                   = 0x1900,
        WMI_FLASH_READ_DONE_EVENTID             = 0x1902,
        WMI_FLASH_WRITE_DONE_EVENTID            = 0x1903,
-       /*P2P*/
+       /* P2P */
        WMI_P2P_CFG_DONE_EVENTID                = 0x1910,
        WMI_PORT_ALLOCATED_EVENTID              = 0x1911,
        WMI_PORT_DELETED_EVENTID                = 0x1912,
@@ -937,49 +888,42 @@ enum wmi_event_id {
        WMI_DISCOVERY_STOPPED_EVENTID           = 0x1917,
        WMI_PCP_STARTED_EVENTID                 = 0x1918,
        WMI_PCP_STOPPED_EVENTID                 = 0x1919,
-       WMI_PCP_FACTOR_EVENTID                  = 0x191a,
+       WMI_PCP_FACTOR_EVENTID                  = 0x191A,
        WMI_SET_CHANNEL_EVENTID                 = 0x9000,
        WMI_ASSOC_REQ_EVENTID                   = 0x9001,
        WMI_EAPOL_RX_EVENTID                    = 0x9002,
        WMI_MAC_ADDR_RESP_EVENTID               = 0x9003,
        WMI_FW_VER_EVENTID                      = 0x9004,
+       WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID   = 0x9005,
 };
 
-/*
- * Events data structures
- */
-
+/* Events data structures */
 enum wmi_fw_status {
-       WMI_FW_STATUS_SUCCESS,
-       WMI_FW_STATUS_FAILURE,
+       WMI_FW_STATUS_SUCCESS   = 0x00,
+       WMI_FW_STATUS_FAILURE   = 0x01,
 };
 
-/*
- * WMI_RF_MGMT_STATUS_EVENTID
- */
+/* WMI_RF_MGMT_STATUS_EVENTID */
 enum wmi_rf_status {
-       WMI_RF_ENABLED                  = 0,
-       WMI_RF_DISABLED_HW              = 1,
-       WMI_RF_DISABLED_SW              = 2,
-       WMI_RF_DISABLED_HW_SW           = 3,
+       WMI_RF_ENABLED          = 0x00,
+       WMI_RF_DISABLED_HW      = 0x01,
+       WMI_RF_DISABLED_SW      = 0x02,
+       WMI_RF_DISABLED_HW_SW   = 0x03,
 };
 
+/* WMI_RF_MGMT_STATUS_EVENTID */
 struct wmi_rf_mgmt_status_event {
        __le32 rf_status;
 } __packed;
 
-/*
- * WMI_THERMAL_THROTTLING_STATUS_EVENTID
- */
+/* WMI_THERMAL_THROTTLING_STATUS_EVENTID */
 struct wmi_thermal_throttling_status_event {
        __le32 time_on_usec;
        __le32 time_off_usec;
        __le32 max_txop_length_usec;
 } __packed;
 
-/*
- * WMI_GET_STATUS_DONE_EVENTID
- */
+/* WMI_GET_STATUS_DONE_EVENTID */
 struct wmi_get_status_done_event {
        __le32 is_associated;
        u8 cid;
@@ -995,9 +939,7 @@ struct wmi_get_status_done_event {
        __le32 is_secured;
 } __packed;
 
-/*
- * WMI_FW_VER_EVENTID
- */
+/* WMI_FW_VER_EVENTID */
 struct wmi_fw_ver_event {
        u8 major;
        u8 minor;
@@ -1005,9 +947,7 @@ struct wmi_fw_ver_event {
        __le16 build;
 } __packed;
 
-/*
-* WMI_MAC_ADDR_RESP_EVENTID
-*/
+/* WMI_MAC_ADDR_RESP_EVENTID */
 struct wmi_mac_addr_resp_event {
        u8 mac[WMI_MAC_LEN];
        u8 auth_mode;
@@ -1015,42 +955,38 @@ struct wmi_mac_addr_resp_event {
        __le32 offload_mode;
 } __packed;
 
-/*
-* WMI_EAPOL_RX_EVENTID
-*/
+/* WMI_EAPOL_RX_EVENTID */
 struct wmi_eapol_rx_event {
        u8 src_mac[WMI_MAC_LEN];
        __le16 eapol_len;
        u8 eapol[0];
 } __packed;
 
-/*
-* WMI_READY_EVENTID
-*/
+/* WMI_READY_EVENTID */
 enum wmi_phy_capability {
-       WMI_11A_CAPABILITY              = 1,
-       WMI_11G_CAPABILITY              = 2,
-       WMI_11AG_CAPABILITY             = 3,
-       WMI_11NA_CAPABILITY             = 4,
-       WMI_11NG_CAPABILITY             = 5,
-       WMI_11NAG_CAPABILITY            = 6,
-       WMI_11AD_CAPABILITY             = 7,
-       WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY,
+       WMI_11A_CAPABILITY              = 0x01,
+       WMI_11G_CAPABILITY              = 0x02,
+       WMI_11AG_CAPABILITY             = 0x03,
+       WMI_11NA_CAPABILITY             = 0x04,
+       WMI_11NG_CAPABILITY             = 0x05,
+       WMI_11NAG_CAPABILITY            = 0x06,
+       WMI_11AD_CAPABILITY             = 0x07,
+       WMI_11N_CAPABILITY_OFFSET       = 0x03,
 };
 
 struct wmi_ready_event {
        __le32 sw_version;
        __le32 abi_version;
        u8 mac[WMI_MAC_LEN];
-       u8 phy_capability;              /* enum wmi_phy_capability */
+       /* enum wmi_phy_capability */
+       u8 phy_capability;
        u8 numof_additional_mids;
 } __packed;
 
-/*
- * WMI_NOTIFY_REQ_DONE_EVENTID
- */
+/* WMI_NOTIFY_REQ_DONE_EVENTID */
 struct wmi_notify_req_done_event {
-       __le32 status; /* beamforming status, 0: fail; 1: OK; 2: retrying */
+       /* beamforming status, 0: fail; 1: OK; 2: retrying */
+       __le32 status;
        __le64 tsf;
        __le32 snr_val;
        __le32 tx_tpt;
@@ -1066,9 +1002,7 @@ struct wmi_notify_req_done_event {
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_CONNECT_EVENTID
- */
+/* WMI_CONNECT_EVENTID */
 struct wmi_connect_event {
        u8 channel;
        u8 reserved0;
@@ -1082,68 +1016,103 @@ struct wmi_connect_event {
        u8 assoc_resp_len;
        u8 cid;
        u8 reserved2[3];
+       /* not in use */
        u8 assoc_info[0];
 } __packed;
 
-/*
- * WMI_DISCONNECT_EVENTID
- */
+/* WMI_DISCONNECT_EVENTID */
 enum wmi_disconnect_reason {
-       WMI_DIS_REASON_NO_NETWORK_AVAIL         = 1,
-       WMI_DIS_REASON_LOST_LINK                = 2, /* bmiss */
-       WMI_DIS_REASON_DISCONNECT_CMD           = 3,
-       WMI_DIS_REASON_BSS_DISCONNECTED         = 4,
-       WMI_DIS_REASON_AUTH_FAILED              = 5,
-       WMI_DIS_REASON_ASSOC_FAILED             = 6,
-       WMI_DIS_REASON_NO_RESOURCES_AVAIL       = 7,
-       WMI_DIS_REASON_CSERV_DISCONNECT         = 8,
-       WMI_DIS_REASON_INVALID_PROFILE          = 10,
-       WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH    = 11,
-       WMI_DIS_REASON_PROFILE_MISMATCH         = 12,
-       WMI_DIS_REASON_CONNECTION_EVICTED       = 13,
-       WMI_DIS_REASON_IBSS_MERGE               = 14,
+       WMI_DIS_REASON_NO_NETWORK_AVAIL         = 0x01,
+       /* bmiss */
+       WMI_DIS_REASON_LOST_LINK                = 0x02,
+       WMI_DIS_REASON_DISCONNECT_CMD           = 0x03,
+       WMI_DIS_REASON_BSS_DISCONNECTED         = 0x04,
+       WMI_DIS_REASON_AUTH_FAILED              = 0x05,
+       WMI_DIS_REASON_ASSOC_FAILED             = 0x06,
+       WMI_DIS_REASON_NO_RESOURCES_AVAIL       = 0x07,
+       WMI_DIS_REASON_CSERV_DISCONNECT         = 0x08,
+       WMI_DIS_REASON_INVALID_PROFILE          = 0x0A,
+       WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH    = 0x0B,
+       WMI_DIS_REASON_PROFILE_MISMATCH         = 0x0C,
+       WMI_DIS_REASON_CONNECTION_EVICTED       = 0x0D,
+       WMI_DIS_REASON_IBSS_MERGE               = 0x0E,
 };
 
 struct wmi_disconnect_event {
-       __le16 protocol_reason_status;  /* reason code, see 802.11 spec. */
-       u8 bssid[WMI_MAC_LEN];          /* set if known */
-       u8 disconnect_reason;           /* see wmi_disconnect_reason */
-       u8 assoc_resp_len;      /* not used */
-       u8 assoc_info[0];       /* not used */
+       /* reason code, see 802.11 spec. */
+       __le16 protocol_reason_status;
+       /* set if known */
+       u8 bssid[WMI_MAC_LEN];
+       /* see enum wmi_disconnect_reason */
+       u8 disconnect_reason;
+       /* last assoc req may passed to host - not in used */
+       u8 assoc_resp_len;
+       /* last assoc req may passed to host - not in used */
+       u8 assoc_info[0];
 } __packed;
 
-/*
- * WMI_SCAN_COMPLETE_EVENTID
- */
+/* WMI_SCAN_COMPLETE_EVENTID */
 enum scan_status {
-       WMI_SCAN_SUCCESS        = 0,
-       WMI_SCAN_FAILED         = 1,
-       WMI_SCAN_ABORTED        = 2,
-       WMI_SCAN_REJECTED       = 3,
+       WMI_SCAN_SUCCESS        = 0x00,
+       WMI_SCAN_FAILED         = 0x01,
+       WMI_SCAN_ABORTED        = 0x02,
+       WMI_SCAN_REJECTED       = 0x03,
+       WMI_SCAN_ABORT_REJECTED = 0x04,
 };
 
 struct wmi_scan_complete_event {
-       __le32 status;  /* scan_status */
+       /* enum scan_status */
+       __le32 status;
 } __packed;
 
-/*
- * WMI_BA_STATUS_EVENTID
- */
+/* WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENT */
+enum wmi_acs_info_bitmask {
+       WMI_ACS_INFO_BITMASK_BEACON_FOUND       = 0x01,
+       WMI_ACS_INFO_BITMASK_BUSY_TIME          = 0x02,
+       WMI_ACS_INFO_BITMASK_TX_TIME            = 0x04,
+       WMI_ACS_INFO_BITMASK_RX_TIME            = 0x08,
+       WMI_ACS_INFO_BITMASK_NOISE              = 0x10,
+};
+
+struct scan_acs_info {
+       u8 channel;
+       u8 beacon_found;
+       /* msec */
+       __le16 busy_time;
+       __le16 tx_time;
+       __le16 rx_time;
+       u8 noise;
+       u8 reserved[3];
+} __packed;
+
+struct wmi_acs_passive_scan_complete_event {
+       __le32 dwell_time;
+       /* valid fields within channel info according to
+        * their appearance in struct order
+        */
+       __le16 filled;
+       u8 num_scanned_channels;
+       u8 reserved;
+       struct scan_acs_info scan_info_list[0];
+} __packed;
+
+/* WMI_BA_STATUS_EVENTID */
 enum wmi_vring_ba_status {
-       WMI_BA_AGREED                   = 0,
-       WMI_BA_NON_AGREED               = 1,
+       WMI_BA_AGREED                   = 0x00,
+       WMI_BA_NON_AGREED               = 0x01,
        /* BA_EN in middle of teardown flow */
-       WMI_BA_TD_WIP                   = 2,
+       WMI_BA_TD_WIP                   = 0x02,
        /* BA_DIS or BA_EN in middle of BA SETUP flow */
-       WMI_BA_SETUP_WIP                = 3,
+       WMI_BA_SETUP_WIP                = 0x03,
        /* BA_EN when the BA session is already active */
-       WMI_BA_SESSION_ACTIVE           = 4,
+       WMI_BA_SESSION_ACTIVE           = 0x04,
        /* BA_DIS when the BA session is not active */
-       WMI_BA_SESSION_NOT_ACTIVE       = 5,
+       WMI_BA_SESSION_NOT_ACTIVE       = 0x05,
 };
 
-struct wmi_vring_ba_status_event {
-       __le16 status; /* enum wmi_vring_ba_status */
+struct wmi_ba_status_event {
+       /* enum wmi_vring_ba_status */
+       __le16 status;
        u8 reserved[2];
        u8 ringid;
        u8 agg_wsize;
@@ -1151,18 +1120,14 @@ struct wmi_vring_ba_status_event {
        u8 amsdu;
 } __packed;
 
-/*
- * WMI_DELBA_EVENTID
- */
+/* WMI_DELBA_EVENTID */
 struct wmi_delba_event {
        u8 cidxtid;
        u8 from_initiator;
        __le16 reason;
 } __packed;
 
-/*
- * WMI_VRING_CFG_DONE_EVENTID
- */
+/* WMI_VRING_CFG_DONE_EVENTID */
 struct wmi_vring_cfg_done_event {
        u8 ringid;
        u8 status;
@@ -1170,174 +1135,151 @@ struct wmi_vring_cfg_done_event {
        __le32 tx_vring_tail_ptr;
 } __packed;
 
-/*
- * WMI_RCP_ADDBA_RESP_SENT_EVENTID
- */
+/* WMI_RCP_ADDBA_RESP_SENT_EVENTID */
 struct wmi_rcp_addba_resp_sent_event {
        u8 cidxtid;
        u8 reserved;
        __le16 status;
 } __packed;
 
-/*
- * WMI_RCP_ADDBA_REQ_EVENTID
- */
+/* WMI_RCP_ADDBA_REQ_EVENTID */
 struct wmi_rcp_addba_req_event {
        u8 cidxtid;
        u8 dialog_token;
-       __le16 ba_param_set;    /* ieee80211_ba_parameterset as it received */
+       /* ieee80211_ba_parameterset as it received */
+       __le16 ba_param_set;
        __le16 ba_timeout;
-       __le16 ba_seq_ctrl;     /* ieee80211_ba_seqstrl field as it received */
+       /* ieee80211_ba_seqstrl field as it received */
+       __le16 ba_seq_ctrl;
 } __packed;
 
-/*
- * WMI_CFG_RX_CHAIN_DONE_EVENTID
- */
+/* WMI_CFG_RX_CHAIN_DONE_EVENTID */
 enum wmi_cfg_rx_chain_done_event_status {
-       WMI_CFG_RX_CHAIN_SUCCESS        = 1,
+       WMI_CFG_RX_CHAIN_SUCCESS        = 0x01,
 };
 
 struct wmi_cfg_rx_chain_done_event {
-       __le32 rx_ring_tail_ptr;        /* Rx V-Ring Tail pointer */
+       /* V-Ring Tail pointer */
+       __le32 rx_ring_tail_ptr;
        __le32 status;
 } __packed;
 
-/*
- * WMI_WBE_LINK_DOWN_EVENTID
- */
+/* WMI_WBE_LINK_DOWN_EVENTID */
 enum wmi_wbe_link_down_event_reason {
-       WMI_WBE_REASON_USER_REQUEST     = 0,
-       WMI_WBE_REASON_RX_DISASSOC      = 1,
-       WMI_WBE_REASON_BAD_PHY_LINK     = 2,
+       WMI_WBE_REASON_USER_REQUEST     = 0x00,
+       WMI_WBE_REASON_RX_DISASSOC      = 0x01,
+       WMI_WBE_REASON_BAD_PHY_LINK     = 0x02,
 };
 
+/* WMI_WBE_LINK_DOWN_EVENTID */
 struct wmi_wbe_link_down_event {
        u8 cid;
        u8 reserved[3];
        __le32 reason;
 } __packed;
 
-/*
- * WMI_DATA_PORT_OPEN_EVENTID
- */
+/* WMI_DATA_PORT_OPEN_EVENTID */
 struct wmi_data_port_open_event {
        u8 cid;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_VRING_EN_EVENTID
- */
+/* WMI_VRING_EN_EVENTID */
 struct wmi_vring_en_event {
        u8 vring_index;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_GET_PCP_CHANNEL_EVENTID
- */
+/* WMI_GET_PCP_CHANNEL_EVENTID */
 struct wmi_get_pcp_channel_event {
        u8 channel;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_P2P_CFG_DONE_EVENTID
- */
+/* WMI_P2P_CFG_DONE_EVENTID */
 struct wmi_p2p_cfg_done_event {
-       u8 status;      /* wmi_fw_status */
+       /* wmi_fw_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
-* WMI_PORT_ALLOCATED_EVENTID
-*/
+/* WMI_PORT_ALLOCATED_EVENTID */
 struct wmi_port_allocated_event {
-       u8 status;      /* wmi_fw_status */
+       /* wmi_fw_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
-* WMI_PORT_DELETED_EVENTID
-*/
+/* WMI_PORT_DELETED_EVENTID */
 struct wmi_port_deleted_event {
-       u8 status;      /* wmi_fw_status */
+       /* wmi_fw_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_LISTEN_STARTED_EVENTID
- */
+/* WMI_LISTEN_STARTED_EVENTID */
 struct wmi_listen_started_event {
-       u8 status;      /* wmi_fw_status */
+       /* wmi_fw_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_SEARCH_STARTED_EVENTID
- */
+/* WMI_SEARCH_STARTED_EVENTID */
 struct wmi_search_started_event {
-       u8 status;      /* wmi_fw_status */
+       /* wmi_fw_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_PCP_STARTED_EVENTID
- */
+/* WMI_PCP_STARTED_EVENTID */
 struct wmi_pcp_started_event {
-       u8 status;      /* wmi_fw_status */
+       /* wmi_fw_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_PCP_FACTOR_EVENTID
- */
+/* WMI_PCP_FACTOR_EVENTID */
 struct wmi_pcp_factor_event {
        __le32 pcp_factor;
 } __packed;
 
-/*
- * WMI_SW_TX_COMPLETE_EVENTID
- */
 enum wmi_sw_tx_status {
-       WMI_TX_SW_STATUS_SUCCESS                = 0,
-       WMI_TX_SW_STATUS_FAILED_NO_RESOURCES    = 1,
-       WMI_TX_SW_STATUS_FAILED_TX              = 2,
+       WMI_TX_SW_STATUS_SUCCESS                = 0x00,
+       WMI_TX_SW_STATUS_FAILED_NO_RESOURCES    = 0x01,
+       WMI_TX_SW_STATUS_FAILED_TX              = 0x02,
 };
 
+/* WMI_SW_TX_COMPLETE_EVENTID */
 struct wmi_sw_tx_complete_event {
-       u8 status;      /* enum wmi_sw_tx_status */
+       /* enum wmi_sw_tx_status */
+       u8 status;
        u8 reserved[3];
 } __packed;
 
-/*
- * WMI_CORR_MEASURE_EVENTID
- */
+/* WMI_CORR_MEASURE_EVENTID */
 struct wmi_corr_measure_event {
-       s32 i;
-       s32 q;
-       s32 image_i;
-       s32 image_q;
+       /* signed */
+       __le32 i;
+       /* signed */
+       __le32 q;
+       /* signed */
+       __le32 image_i;
+       /* signed */
+       __le32 image_q;
 } __packed;
 
-/*
- * WMI_READ_RSSI_EVENTID
- */
+/* WMI_READ_RSSI_EVENTID */
 struct wmi_read_rssi_event {
        __le32 ina_rssi_adc_dbm;
 } __packed;
 
-/*
- * WMI_GET_SSID_EVENTID
- */
+/* WMI_GET_SSID_EVENTID */
 struct wmi_get_ssid_event {
        __le32 ssid_len;
        u8 ssid[WMI_MAX_SSID_LEN];
 } __packed;
 
-/*
- * WMI_RX_MGMT_PACKET_EVENTID
- */
+/* wmi_rx_mgmt_info */
 struct wmi_rx_mgmt_info {
        u8 mcs;
        s8 snr;
@@ -1346,39 +1288,65 @@ struct wmi_rx_mgmt_info {
        __le16 stype;
        __le16 status;
        __le32 len;
+       /* Not resolved when == 0xFFFFFFFF  ==> Broadcast to all MIDS */
        u8 qid;
+       /* Not resolved when == 0xFFFFFFFF  ==> Broadcast to all MIDS */
        u8 mid;
        u8 cid;
-       u8 channel;     /* From Radio MNGR */
+       /* From Radio MNGR */
+       u8 channel;
 } __packed;
 
-/*
- * WMI_TX_MGMT_PACKET_EVENTID
- */
+/* wmi_otp_read_write_cmd */
+struct wmi_otp_read_write_cmd {
+       __le32 addr;
+       __le32 size;
+       u8 values[0];
+} __packed;
+
+/* WMI_OTP_READ_RESULT_EVENTID */
+struct wmi_otp_read_result_event {
+       u8 payload[0];
+} __packed;
+
+/* WMI_TX_MGMT_PACKET_EVENTID */
 struct wmi_tx_mgmt_packet_event {
        u8 payload[0];
 } __packed;
 
+/* WMI_RX_MGMT_PACKET_EVENTID */
 struct wmi_rx_mgmt_packet_event {
        struct wmi_rx_mgmt_info info;
        u8 payload[0];
 } __packed;
 
-/*
- * WMI_ECHO_RSP_EVENTID
- */
-struct wmi_echo_event {
+/* WMI_ECHO_RSP_EVENTID */
+struct wmi_echo_rsp_event {
        __le32 echoed_value;
 } __packed;
 
-/*
- * WMI_TEMP_SENSE_DONE_EVENTID
+/* WMI_TEMP_SENSE_DONE_EVENTID
  *
  * Measure MAC and radio temperatures
  */
 struct wmi_temp_sense_done_event {
+       /* Temperature times 1000 (actual temperature will be achieved by
+        * dividing the value by 1000)
+        */
        __le32 baseband_t1000;
+       /* Temperature times 1000 (actual temperature will be achieved by
+        * dividing the value by 1000)
+        */
        __le32 rf_t1000;
 } __packed;
 
+#define WMI_SCAN_DWELL_TIME_MS (100)
+#define WMI_SURVEY_TIMEOUT_MS  (10000)
+
+enum wmi_hidden_ssid {
+       WMI_HIDDEN_SSID_DISABLED        = 0x00,
+       WMI_HIDDEN_SSID_SEND_EMPTY      = 0x10,
+       WMI_HIDDEN_SSID_CLEAR           = 0xFE,
+};
+
 #endif /* __WILOCITY_WMI_H__ */
index 33eb274cd0e6b61be2b000e3e30c82f2ea6c7f1e..e66153d60bd50e8d502d58d44fac4099bb00c689 100644 (file)
@@ -31,6 +31,10 @@ struct ath9k_platform_data {
        u32 gpio_mask;
        u32 gpio_val;
 
+       u32 bt_active_pin;
+       u32 bt_priority_pin;
+       u32 wlan_active_pin;
+
        bool endian_check;
        bool is_clk_25mhz;
        bool tx_gain_buffalo;