Merge ath-next from ath.git
authorKalle Valo <kvalo@codeaurora.org>
Mon, 15 Jun 2015 10:25:32 +0000 (13:25 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 15 Jun 2015 10:25:32 +0000 (13:25 +0300)
Major changes:

wil6210:

* add modparam for bcast ring size
* support hidden SSID
* add per-MCS Rx stats

21 files changed:
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/core.h
drivers/net/wireless/ath/ath10k/hw.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath10k/pci.c
drivers/net/wireless/ath/ath10k/wmi-tlv.c
drivers/net/wireless/ath/ath10k/wmi.c
drivers/net/wireless/ath/ath10k/wmi.h
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/ath/wil6210/debugfs.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/netdev.c
drivers/net/wireless/ath/wil6210/pcie_bus.c
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/ath/wil6210/wil_platform.c
drivers/net/wireless/ath/wil6210/wil_platform.h
drivers/net/wireless/ath/wil6210/wmi.c
drivers/net/wireless/ath/wil6210/wmi.h

index bcccae19325d8f77da713a37956514ee5f97c1b9..59496a90ad5e241563f5bcaa8226ebfde87bd478 100644 (file)
@@ -48,6 +48,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .name = "qca988x hw2.0",
                .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
                .uart_pin = 7,
+               .has_shifted_cc_wraparound = true,
                .fw = {
                        .dir = QCA988X_HW_2_0_FW_DIR,
                        .fw = QCA988X_HW_2_0_FW_FILE,
@@ -1084,6 +1085,22 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
        if (status)
                goto err;
 
+       /* Some of of qca988x solutions are having global reset issue
+         * during target initialization. Bypassing PLL setting before
+         * downloading firmware and letting the SoC run on REF_CLK is
+         * fixing the problem. Corresponding firmware change is also needed
+         * to set the clock source once the target is initialized.
+        */
+       if (test_bit(ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT,
+                    ar->fw_features)) {
+               status = ath10k_bmi_write32(ar, hi_skip_clock_init, 1);
+               if (status) {
+                       ath10k_err(ar, "could not write to skip_clock_init: %d\n",
+                                  status);
+                       goto err;
+               }
+       }
+
        status = ath10k_download_fw(ar, mode);
        if (status)
                goto err;
index 70fcdc9c27587593046f1aeab8fd3b68b2d74364..78094f23c9dd5264a66d32167680a8af8728a8ff 100644 (file)
@@ -284,15 +284,6 @@ struct ath10k_sta {
 #endif
 };
 
-struct ath10k_chanctx {
-       /* Used to story copy of chanctx_conf to avoid inconsistencies. Ideally
-        * mac80211 should allow some sort of explicit locking to guarantee
-        * that the publicly available chanctx_conf can be accessed safely at
-        * all times.
-        */
-       struct ieee80211_chanctx_conf conf;
-};
-
 #define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
 
 enum ath10k_beacon_state {
@@ -468,6 +459,9 @@ enum ath10k_fw_features {
         */
        ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
 
+       /* Firmware supports bypassing PLL setting on init. */
+       ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9,
+
        /* keep last */
        ATH10K_FW_FEATURE_COUNT,
 };
@@ -577,6 +571,13 @@ struct ath10k {
                u32 patch_load_addr;
                int uart_pin;
 
+               /* This is true if given HW chip has a quirky Cycle Counter
+                * wraparound which resets to 0x7fffffff instead of 0. All
+                * other CC related counters (e.g. Rx Clear Count) are divided
+                * by 2 so they never wraparound themselves.
+                */
+               bool has_shifted_cc_wraparound;
+
                struct ath10k_hw_params_fw {
                        const char *dir;
                        const char *fw;
@@ -694,6 +695,14 @@ struct ath10k {
        u32 survey_last_cycle_count;
        struct survey_info survey[ATH10K_NUM_CHANS];
 
+       /* Channel info events are expected to come in pairs without and with
+        * COMPLETE flag set respectively for each channel visit during scan.
+        *
+        * However there are deviations from this rule. This flag is used to
+        * avoid reporting garbage data.
+        */
+       bool ch_info_can_report_survey;
+
        struct dfs_pattern_detector *dfs_detector;
 
        unsigned long tx_paused; /* see ATH10K_TX_PAUSE_ */
index 839a8791fb9e4a53d05e29e991b6d33510520044..5997f00afe3b43b677f1718a64a213090c969d92 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <linux/types.h>
+#include "core.h"
 #include "hw.h"
 
 const struct ath10k_hw_regs qca988x_regs = {
@@ -56,3 +57,23 @@ const struct ath10k_hw_regs qca6174_regs = {
        .soc_chip_id_address                    = 0x000f0,
        .scratch_3_address                      = 0x0028,
 };
+
+void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+                               u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
+{
+       u32 cc_fix = 0;
+
+       survey->filled |= SURVEY_INFO_TIME |
+                         SURVEY_INFO_TIME_BUSY;
+
+       if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) {
+               cc_fix = 0x7fffffff;
+               survey->filled &= ~SURVEY_INFO_TIME_BUSY;
+       }
+
+       cc -= cc_prev - cc_fix;
+       rcc -= rcc_prev;
+
+       survey->time = CCNT_TO_MSEC(cc);
+       survey->time_busy = CCNT_TO_MSEC(rcc);
+}
index 89e09cbeac19f4cc64d96002aafd31cc0bc1cc2c..85cca29375fee8f08ab09975c31cc3130194176e 100644 (file)
@@ -169,6 +169,9 @@ struct ath10k_hw_regs {
 extern const struct ath10k_hw_regs qca988x_regs;
 extern const struct ath10k_hw_regs qca6174_regs;
 
+void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+                               u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev);
+
 #define QCA_REV_988X(ar) ((ar)->hw_rev == ATH10K_HW_QCA988X)
 #define QCA_REV_6174(ar) ((ar)->hw_rev == ATH10K_HW_QCA6174)
 
@@ -449,6 +452,9 @@ enum ath10k_hw_rate_cck {
 #define SCRATCH_3_ADDRESS                      ar->regs->scratch_3_address
 #define CPU_INTR_ADDRESS                       0x0010
 
+/* Cycle counters are running at 88MHz */
+#define CCNT_TO_MSEC(x) ((x) / 88000)
+
 /* Firmware indications to the Host via SCRATCH_3 register. */
 #define FW_INDICATOR_ADDRESS   (SOC_CORE_BASE_ADDRESS + SCRATCH_3_ADDRESS)
 #define FW_IND_EVENT_PENDING                   1
index 0ed422ae46a487e612508de17bfbbfe662749a0f..c48c744acbccc3c7dca95b86a8fbba40779476ec 100644 (file)
@@ -3949,83 +3949,6 @@ static int ath10k_config_ps(struct ath10k *ar)
        return ret;
 }
 
-static void ath10k_mac_chan_reconfigure(struct ath10k *ar)
-{
-       struct ath10k_vif *arvif;
-       struct cfg80211_chan_def def;
-       int ret;
-
-       lockdep_assert_held(&ar->conf_mutex);
-
-       ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chan reconfigure\n");
-
-       /* First stop monitor interface. Some FW versions crash if there's a
-        * lone monitor interface. */
-       if (ar->monitor_started)
-               ath10k_monitor_stop(ar);
-
-       list_for_each_entry(arvif, &ar->arvifs, list) {
-               if (!arvif->is_started)
-                       continue;
-
-               if (!arvif->is_up)
-                       continue;
-
-               if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-                       continue;
-
-               ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
-               if (ret) {
-                       ath10k_warn(ar, "failed to down vdev %d: %d\n",
-                                   arvif->vdev_id, ret);
-                       continue;
-               }
-       }
-
-       /* all vdevs are downed now - attempt to restart and re-up them */
-
-       list_for_each_entry(arvif, &ar->arvifs, list) {
-               if (!arvif->is_started)
-                       continue;
-
-               if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)
-                       continue;
-
-               ret = ath10k_mac_setup_bcn_tmpl(arvif);
-               if (ret)
-                       ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
-                                   ret);
-
-               ret = ath10k_mac_setup_prb_tmpl(arvif);
-               if (ret)
-                       ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
-                                   ret);
-
-               if (WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def)))
-                       continue;
-
-               ret = ath10k_vdev_restart(arvif, &def);
-               if (ret) {
-                       ath10k_warn(ar, "failed to restart vdev %d: %d\n",
-                                   arvif->vdev_id, ret);
-                       continue;
-               }
-
-               if (!arvif->is_up)
-                       continue;
-
-               ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
-                                        arvif->bssid);
-               if (ret) {
-                       ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
-                                   arvif->vdev_id, ret);
-                       continue;
-               }
-       }
-
-       ath10k_monitor_recalc(ar);
-}
-
 static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
 {
        int ret;
@@ -6144,7 +6067,10 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
 }
 
 static void
-ath10k_mac_update_rx_channel(struct ath10k *ar)
+ath10k_mac_update_rx_channel(struct ath10k *ar,
+                            struct ieee80211_chanctx_conf *ctx,
+                            struct ieee80211_vif_chanctx_switch *vifs,
+                            int n_vifs)
 {
        struct cfg80211_chan_def *def = NULL;
 
@@ -6154,6 +6080,9 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
        lockdep_assert_held(&ar->conf_mutex);
        lockdep_assert_held(&ar->data_lock);
 
+       WARN_ON(ctx && vifs);
+       WARN_ON(vifs && n_vifs != 1);
+
        /* FIXME: Sort of an optimization and a workaround. Peers and vifs are
         * on a linked list now. Doing a lookup peer -> vif -> chanctx for each
         * ppdu on Rx may reduce performance on low-end systems. It should be
@@ -6165,36 +6094,28 @@ ath10k_mac_update_rx_channel(struct ath10k *ar)
         * affected much.
         */
        rcu_read_lock();
-       if (ath10k_mac_num_chanctxs(ar) == 1) {
+       if (!ctx && ath10k_mac_num_chanctxs(ar) == 1) {
                ieee80211_iter_chan_contexts_atomic(ar->hw,
                                        ath10k_mac_get_any_chandef_iter,
                                        &def);
+
+               if (vifs)
+                       def = &vifs[0].new_ctx->def;
+
                ar->rx_channel = def->chan;
+       } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
+               ar->rx_channel = ctx->def.chan;
        } else {
                ar->rx_channel = NULL;
        }
        rcu_read_unlock();
 }
 
-static void
-ath10k_mac_chan_ctx_init(struct ath10k *ar,
-                        struct ath10k_chanctx *arctx,
-                        struct ieee80211_chanctx_conf *conf)
-{
-       lockdep_assert_held(&ar->conf_mutex);
-       lockdep_assert_held(&ar->data_lock);
-
-       memset(arctx, 0, sizeof(*arctx));
-
-       arctx->conf = *conf;
-}
-
 static int
 ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
                          struct ieee80211_chanctx_conf *ctx)
 {
        struct ath10k *ar = hw->priv;
-       struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 
        ath10k_dbg(ar, ATH10K_DBG_MAC,
                   "mac chanctx add freq %hu width %d ptr %p\n",
@@ -6203,8 +6124,7 @@ ath10k_mac_op_add_chanctx(struct ieee80211_hw *hw,
        mutex_lock(&ar->conf_mutex);
 
        spin_lock_bh(&ar->data_lock);
-       ath10k_mac_chan_ctx_init(ar, arctx, ctx);
-       ath10k_mac_update_rx_channel(ar);
+       ath10k_mac_update_rx_channel(ar, ctx, NULL, 0);
        spin_unlock_bh(&ar->data_lock);
 
        ath10k_recalc_radar_detection(ar);
@@ -6228,7 +6148,7 @@ ath10k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
        mutex_lock(&ar->conf_mutex);
 
        spin_lock_bh(&ar->data_lock);
-       ath10k_mac_update_rx_channel(ar);
+       ath10k_mac_update_rx_channel(ar, NULL, NULL, 0);
        spin_unlock_bh(&ar->data_lock);
 
        ath10k_recalc_radar_detection(ar);
@@ -6243,16 +6163,12 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
                             u32 changed)
 {
        struct ath10k *ar = hw->priv;
-       struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
 
        mutex_lock(&ar->conf_mutex);
 
        ath10k_dbg(ar, ATH10K_DBG_MAC,
-                  "mac chanctx change freq %hu->%hu width %d->%d ptr %p changed %x\n",
-                  arctx->conf.def.chan->center_freq,
-                  ctx->def.chan->center_freq,
-                  arctx->conf.def.width, ctx->def.width,
-                  ctx, changed);
+                  "mac chanctx change freq %hu width %d ptr %p changed %x\n",
+                  ctx->def.chan->center_freq, ctx->def.width, ctx, changed);
 
        /* This shouldn't really happen because channel switching should use
         * switch_vif_chanctx().
@@ -6260,10 +6176,6 @@ ath10k_mac_op_change_chanctx(struct ieee80211_hw *hw,
        if (WARN_ON(changed & IEEE80211_CHANCTX_CHANGE_CHANNEL))
                goto unlock;
 
-       spin_lock_bh(&ar->data_lock);
-       arctx->conf = *ctx;
-       spin_unlock_bh(&ar->data_lock);
-
        ath10k_recalc_radar_detection(ar);
 
        /* FIXME: How to configure Rx chains properly? */
@@ -6283,7 +6195,6 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
                                 struct ieee80211_chanctx_conf *ctx)
 {
        struct ath10k *ar = hw->priv;
-       struct ath10k_chanctx *arctx = (void *)ctx->drv_priv;
        struct ath10k_vif *arvif = (void *)vif->drv_priv;
        int ret;
 
@@ -6298,11 +6209,11 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
                return -EBUSY;
        }
 
-       ret = ath10k_vdev_start(arvif, &arctx->conf.def);
+       ret = ath10k_vdev_start(arvif, &ctx->def);
        if (ret) {
                ath10k_warn(ar, "failed to start vdev %i addr %pM on freq %d: %d\n",
                            arvif->vdev_id, vif->addr,
-                           arctx->conf.def.chan->center_freq, ret);
+                           ctx->def.chan->center_freq, ret);
                goto err;
        }
 
@@ -6377,7 +6288,7 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
 {
        struct ath10k *ar = hw->priv;
        struct ath10k_vif *arvif;
-       struct ath10k_chanctx *arctx_new, *arctx_old;
+       int ret;
        int i;
 
        mutex_lock(&ar->conf_mutex);
@@ -6386,38 +6297,81 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
                   "mac chanctx switch n_vifs %d mode %d\n",
                   n_vifs, mode);
 
-       spin_lock_bh(&ar->data_lock);
+       /* First stop monitor interface. Some FW versions crash if there's a
+        * lone monitor interface.
+        */
+       if (ar->monitor_started)
+               ath10k_monitor_stop(ar);
+
        for (i = 0; i < n_vifs; i++) {
                arvif = ath10k_vif_to_arvif(vifs[i].vif);
-               arctx_new = (void *)vifs[i].new_ctx->drv_priv;
-               arctx_old = (void *)vifs[i].old_ctx->drv_priv;
 
                ath10k_dbg(ar, ATH10K_DBG_MAC,
-                          "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d ptr %p->%p\n",
+                          "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
                           arvif->vdev_id,
                           vifs[i].old_ctx->def.chan->center_freq,
                           vifs[i].new_ctx->def.chan->center_freq,
                           vifs[i].old_ctx->def.width,
-                          vifs[i].new_ctx->def.width,
-                          arctx_old, arctx_new);
+                          vifs[i].new_ctx->def.width);
 
-               if (mode == CHANCTX_SWMODE_SWAP_CONTEXTS) {
-                       ath10k_mac_chan_ctx_init(ar, arctx_new,
-                                                vifs[i].new_ctx);
-               }
+               if (WARN_ON(!arvif->is_started))
+                       continue;
 
-               arctx_new->conf = *vifs[i].new_ctx;
+               if (WARN_ON(!arvif->is_up))
+                       continue;
 
-               /* FIXME: ath10k_mac_chan_reconfigure() uses current, i.e. not
-                * yet updated chanctx_conf pointer.
-                */
-               arctx_old->conf = *vifs[i].new_ctx;
+               ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
+               if (ret) {
+                       ath10k_warn(ar, "failed to down vdev %d: %d\n",
+                                   arvif->vdev_id, ret);
+                       continue;
+               }
        }
-       ath10k_mac_update_rx_channel(ar);
+
+       /* All relevant vdevs are downed and associated channel resources
+        * should be available for the channel switch now.
+        */
+
+       spin_lock_bh(&ar->data_lock);
+       ath10k_mac_update_rx_channel(ar, NULL, vifs, n_vifs);
        spin_unlock_bh(&ar->data_lock);
 
-       /* FIXME: Reconfigure only affected vifs */
-       ath10k_mac_chan_reconfigure(ar);
+       for (i = 0; i < n_vifs; i++) {
+               arvif = ath10k_vif_to_arvif(vifs[i].vif);
+
+               if (WARN_ON(!arvif->is_started))
+                       continue;
+
+               if (WARN_ON(!arvif->is_up))
+                       continue;
+
+               ret = ath10k_mac_setup_bcn_tmpl(arvif);
+               if (ret)
+                       ath10k_warn(ar, "failed to update bcn tmpl during csa: %d\n",
+                                   ret);
+
+               ret = ath10k_mac_setup_prb_tmpl(arvif);
+               if (ret)
+                       ath10k_warn(ar, "failed to update prb tmpl during csa: %d\n",
+                                   ret);
+
+               ret = ath10k_vdev_restart(arvif, &vifs[i].new_ctx->def);
+               if (ret) {
+                       ath10k_warn(ar, "failed to restart vdev %d: %d\n",
+                                   arvif->vdev_id, ret);
+                       continue;
+               }
+
+               ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
+                                        arvif->bssid);
+               if (ret) {
+                       ath10k_warn(ar, "failed to bring vdev up %d: %d\n",
+                                   arvif->vdev_id, ret);
+                       continue;
+               }
+       }
+
+       ath10k_monitor_recalc(ar);
 
        mutex_unlock(&ar->conf_mutex);
        return 0;
@@ -6914,7 +6868,6 @@ 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->chanctx_data_size = sizeof(struct ath10k_chanctx);
 
        ar->hw->max_listen_interval = ATH10K_MAX_HW_LISTEN_INTERVAL;
 
index 17a060e8efa2250bbe8d9d63c0eb104fa5282953..ea656e011a96e195d4513e41a482a40bab07df42 100644 (file)
@@ -1424,7 +1424,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
        struct ath10k_ce_ring *ce_ring;
        struct ce_desc *ce_desc;
        struct sk_buff *skb;
-       unsigned int id;
        int i;
 
        ar = pci_pipe->hif_ce_state;
@@ -1448,8 +1447,6 @@ static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
                        continue;
 
                ce_ring->per_transfer_context[i] = NULL;
-               id = MS(__le16_to_cpu(ce_desc[i].flags),
-                       CE_DESC_FLAGS_META_DATA);
 
                ar_pci->msg_callbacks_current.tx_completion(ar, skb);
        }
@@ -2850,6 +2847,7 @@ err_free_pipes:
        ath10k_pci_free_pipes(ar);
 
 err_sleep:
+       ath10k_pci_sleep_sync(ar);
        ath10k_pci_release(ar);
 
 err_core_destroy:
@@ -2927,8 +2925,10 @@ MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
 
 /* QCA6174 2.1 firmware files */
 MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API4_FILE);
+MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" ATH10K_FW_API5_FILE);
 MODULE_FIRMWARE(QCA6174_HW_2_1_FW_DIR "/" QCA6174_HW_2_1_BOARD_DATA_FILE);
 
 /* QCA6174 3.1 firmware files */
 MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API4_FILE);
+MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" ATH10K_FW_API5_FILE);
 MODULE_FIRMWARE(QCA6174_HW_3_0_FW_DIR "/" QCA6174_HW_3_0_BOARD_DATA_FILE);
index 563fde73623c19037be244470abc523db00df971..8fdba3865c960e699bacf0998fd911d1e3a231b1 100644 (file)
@@ -402,7 +402,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
        id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
 
        if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-               return;
+               goto out;
 
        trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
 
@@ -521,6 +521,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
                break;
        }
 
+out:
        dev_kfree_skb(skb);
 }
 
index 0fabe689179c8a8ab3d150bada5f50bc4300a6a2..6c046c244705fe69f23fa9207113c6cefec9a78e 100644 (file)
@@ -27,6 +27,7 @@
 #include "testmode.h"
 #include "wmi-ops.h"
 #include "p2p.h"
+#include "hw.h"
 
 /* MAIN WMI cmd track */
 static struct wmi_cmd_map wmi_cmd_map = {
@@ -1450,6 +1451,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
        ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg);
        if (ret) {
                ath10k_warn(ar, "failed to parse mgmt rx event: %d\n", ret);
+               dev_kfree_skb(skb);
                return ret;
        }
 
@@ -1636,20 +1638,22 @@ void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb)
        }
 
        if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) {
-               /* During scanning chan info is reported twice for each
-                * visited channel. The reported cycle count is global
-                * and per-channel cycle count must be calculated */
-
-               cycle_count -= ar->survey_last_cycle_count;
-               rx_clear_count -= ar->survey_last_rx_clear_count;
-
-               survey = &ar->survey[idx];
-               survey->time = WMI_CHAN_INFO_MSEC(cycle_count);
-               survey->time_busy = WMI_CHAN_INFO_MSEC(rx_clear_count);
-               survey->noise = noise_floor;
-               survey->filled = SURVEY_INFO_TIME |
-                                SURVEY_INFO_TIME_BUSY |
-                                SURVEY_INFO_NOISE_DBM;
+               if (ar->ch_info_can_report_survey) {
+                       survey = &ar->survey[idx];
+                       survey->noise = noise_floor;
+                       survey->filled = SURVEY_INFO_NOISE_DBM;
+
+                       ath10k_hw_fill_survey_time(ar,
+                                                  survey,
+                                                  cycle_count,
+                                                  rx_clear_count,
+                                                  ar->survey_last_cycle_count,
+                                                  ar->survey_last_rx_clear_count);
+               }
+
+               ar->ch_info_can_report_survey = false;
+       } else {
+               ar->ch_info_can_report_survey = true;
        }
 
        ar->survey_last_rx_clear_count = rx_clear_count;
@@ -3219,7 +3223,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
        id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
 
        if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-               return;
+               goto out;
 
        trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
 
@@ -3323,6 +3327,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
                break;
        }
 
+out:
        dev_kfree_skb(skb);
 }
 
@@ -3336,7 +3341,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
        id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
 
        if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-               return;
+               goto out;
 
        trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
 
@@ -3459,7 +3464,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
        id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
 
        if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
-               return;
+               goto out;
 
        trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
 
@@ -3567,6 +3572,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
                break;
        }
 
+out:
        dev_kfree_skb(skb);
 }
 
index cad72ae76253362cf0e7f28ba9930a71814d35f4..cf44a3d080a38c7a58b454d7e82419e98f1733a4 100644 (file)
@@ -4665,7 +4665,6 @@ struct wmi_peer_sta_kickout_event {
 } __packed;
 
 #define WMI_CHAN_INFO_FLAG_COMPLETE BIT(0)
-#define WMI_CHAN_INFO_MSEC(x) ((x) / 88000)
 
 /* Beacon filter wmi command info */
 #define BCN_FLT_MAX_SUPPORTED_IES      256
index 19f88b4a24fbcef48bb31888abcd92a5bb0ce354..05d25a94c781139a0097676f32817126d72f5e5c 100644 (file)
@@ -1527,8 +1527,8 @@ struct wmi_connect_event {
                        __le32 nw_type;
                } sta;
                struct {
-                       u8 phymode;
                        u8 aid;
+                       u8 phymode;
                        u8 mac_addr[ETH_ALEN];
                        u8 auth;
                        u8 keymgmt;
index dbfcdd16628a25ddb4238d51988c9c5759fdf6b9..c79cfe02ec80a62ded454689cee393261484d5ec 100644 (file)
@@ -289,6 +289,26 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
        }
 
        wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
+       wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
+
+       for (i = 0; i < request->n_ssids; i++) {
+               wil_dbg_misc(wil, "SSID[%d]", i);
+               print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
+                                    request->ssids[i].ssid,
+                                    request->ssids[i].ssid_len);
+       }
+
+       if (request->n_ssids)
+               rc = wmi_set_ssid(wil, request->ssids[0].ssid_len,
+                                 request->ssids[0].ssid);
+       else
+               rc = wmi_set_ssid(wil, 0, NULL);
+
+       if (rc) {
+               wil_err(wil, "set SSID for scan request failed: %d\n", rc);
+               return rc;
+       }
+
        wil->scan_request = request;
        mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
 
@@ -778,6 +798,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
        size_t hlen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
        const u8 *pr_ies = NULL;
        size_t pr_ies_len = 0;
+       u8 hidden_ssid;
 
        wil_dbg_misc(wil, "%s()\n", __func__);
 
@@ -790,6 +811,8 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
                     channel->center_freq, info->privacy ? "secure" : "open");
        wil_dbg_misc(wil, "Privacy: %d auth_type %d\n",
                     info->privacy, info->auth_type);
+       wil_dbg_misc(wil, "Hidden SSID mode: %d\n",
+                    info->hidden_ssid);
        wil_dbg_misc(wil, "BI %d DTIM %d\n", info->beacon_interval,
                     info->dtim_period);
        print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
@@ -835,10 +858,28 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy,
 
        wil->privacy = info->privacy;
 
+       switch (info->hidden_ssid) {
+       case NL80211_HIDDEN_SSID_NOT_IN_USE:
+               hidden_ssid = WMI_HIDDEN_SSID_DISABLED;
+               break;
+
+       case NL80211_HIDDEN_SSID_ZERO_LEN:
+               hidden_ssid = WMI_HIDDEN_SSID_SEND_EMPTY;
+               break;
+
+       case NL80211_HIDDEN_SSID_ZERO_CONTENTS:
+               hidden_ssid = WMI_HIDDEN_SSID_CLEAR;
+               break;
+
+       default:
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
        netif_carrier_on(ndev);
 
        rc = wmi_pcp_start(wil, info->beacon_interval, wmi_nettype,
-                          channel->hw_value);
+                          channel->hw_value, hidden_ssid);
        if (rc)
                goto err_pcp_start;
 
@@ -1023,8 +1064,7 @@ static struct cfg80211_ops wil_cfg80211_ops = {
 
 static void wil_wiphy_init(struct wiphy *wiphy)
 {
-       /* TODO: set real value */
-       wiphy->max_scan_ssids = 10;
+       wiphy->max_scan_ssids = 1;
        wiphy->max_scan_ie_len = WMI_MAX_IE_LEN;
        wiphy->max_num_pmkids = 0 /* TODO: */;
        wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
index 8f9c0722a8018b605242a26307015a69ad3e48ee..75219a1b8805135c5cc751db9f70c50e55ddf285 100644 (file)
@@ -1360,7 +1360,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
 __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
 {
        struct wil6210_priv *wil = s->private;
-       int i, tid;
+       int i, tid, mcs;
 
        for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
                struct wil_sta_info *p = &wil->sta[i];
@@ -1390,6 +1390,12 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
                                }
                        }
                        spin_unlock_bh(&p->tid_rx_lock);
+                       seq_puts(s, "Rx/MCS:");
+                       for (mcs = 0; mcs < ARRAY_SIZE(p->stats.rx_per_mcs);
+                            mcs++)
+                               seq_printf(s, " %lld",
+                                          p->stats.rx_per_mcs[mcs]);
+                       seq_puts(s, "\n");
                }
        }
 
index 6d704aee3afd0f083fdb8861c1aa22a07d45bcd0..b9febab8916735f113b99fa2e08d81662b13390a 100644 (file)
@@ -100,6 +100,8 @@ module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO);
 MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
 module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO);
 MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
+module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, S_IRUGO);
+MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order");
 
 #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
 #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
index 6042f61b016c010568c3b9f5903cff8ff668f0eb..8ef18ace110ffffde2e4a954c20c2a0e0632858e 100644 (file)
@@ -132,7 +132,7 @@ static void wil_dev_setup(struct net_device *dev)
        dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
 }
 
-void *wil_if_alloc(struct device *dev, void __iomem *csr)
+void *wil_if_alloc(struct device *dev)
 {
        struct net_device *ndev;
        struct wireless_dev *wdev;
@@ -147,7 +147,6 @@ void *wil_if_alloc(struct device *dev, void __iomem *csr)
        }
 
        wil = wdev_to_wil(wdev);
-       wil->csr = csr;
        wil->wdev = wdev;
 
        wil_dbg_misc(wil, "%s()\n", __func__);
index 58c79166a6d11a5d676b857ccee5f55f0b71a415..aa3ecc607ca31abae2879bea058a2505006e1495 100644 (file)
@@ -163,7 +163,6 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct wil6210_priv *wil;
        struct device *dev = &pdev->dev;
-       void __iomem *csr;
        int rc;
 
        /* check HW */
@@ -178,9 +177,28 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                return -ENODEV;
        }
 
+       wil = wil_if_alloc(dev);
+       if (IS_ERR(wil)) {
+               rc = (int)PTR_ERR(wil);
+               dev_err(dev, "wil_if_alloc failed: %d\n", rc);
+               return rc;
+       }
+       wil->pdev = pdev;
+       pci_set_drvdata(pdev, wil);
+       /* rollback to if_free */
+
+       wil->platform_handle =
+                       wil_platform_init(&pdev->dev, &wil->platform_ops);
+       if (!wil->platform_handle) {
+               rc = -ENODEV;
+               wil_err(wil, "wil_platform_init failed\n");
+               goto if_free;
+       }
+       /* rollback to err_plat */
+
        rc = pci_enable_device(pdev);
        if (rc) {
-               dev_err(&pdev->dev,
+               wil_err(wil,
                        "pci_enable_device failed, retry with MSI only\n");
                /* Work around for platforms that can't allocate IRQ:
                 * retry with MSI only
@@ -188,47 +206,37 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                pdev->msi_enabled = 1;
                rc = pci_enable_device(pdev);
        }
-       if (rc)
-               return -ENODEV;
+       if (rc) {
+               wil_err(wil,
+                       "pci_enable_device failed, even with MSI only\n");
+               goto err_plat;
+       }
        /* rollback to err_disable_pdev */
 
        rc = pci_request_region(pdev, 0, WIL_NAME);
        if (rc) {
-               dev_err(&pdev->dev, "pci_request_region failed\n");
+               wil_err(wil, "pci_request_region failed\n");
                goto err_disable_pdev;
        }
        /* rollback to err_release_reg */
 
-       csr = pci_ioremap_bar(pdev, 0);
-       if (!csr) {
-               dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
+       wil->csr = pci_ioremap_bar(pdev, 0);
+       if (!wil->csr) {
+               wil_err(wil, "pci_ioremap_bar failed\n");
                rc = -ENODEV;
                goto err_release_reg;
        }
        /* rollback to err_iounmap */
-       dev_info(&pdev->dev, "CSR at %pR -> 0x%p\n", &pdev->resource[0], csr);
+       wil_info(wil, "CSR at %pR -> 0x%p\n", &pdev->resource[0], wil->csr);
 
-       wil = wil_if_alloc(dev, csr);
-       if (IS_ERR(wil)) {
-               rc = (int)PTR_ERR(wil);
-               dev_err(dev, "wil_if_alloc failed: %d\n", rc);
-               goto err_iounmap;
-       }
-       /* rollback to if_free */
-
-       pci_set_drvdata(pdev, wil);
-       wil->pdev = pdev;
        wil_set_capabilities(wil);
        wil6210_clear_irq(wil);
 
-       wil->platform_handle =
-                       wil_platform_init(&pdev->dev, &wil->platform_ops);
-
        /* FW should raise IRQ when ready */
        rc = wil_if_pcie_enable(wil);
        if (rc) {
                wil_err(wil, "Enable device failed\n");
-               goto if_free;
+               goto err_iounmap;
        }
        /* rollback to bus_disable */
 
@@ -243,18 +251,19 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        return 0;
 
- bus_disable:
+bus_disable:
        wil_if_pcie_disable(wil);
- if_free:
+err_iounmap:
+       pci_iounmap(pdev, wil->csr);
+err_release_reg:
+       pci_release_region(pdev, 0);
+err_disable_pdev:
+       pci_disable_device(pdev);
+err_plat:
        if (wil->platform_ops.uninit)
                wil->platform_ops.uninit(wil->platform_handle);
+if_free:
        wil_if_free(wil);
- err_iounmap:
-       pci_iounmap(pdev, csr);
- err_release_reg:
-       pci_release_region(pdev, 0);
- err_disable_pdev:
-       pci_disable_device(pdev);
 
        return rc;
 }
@@ -269,12 +278,12 @@ static void wil_pcie_remove(struct pci_dev *pdev)
        wil6210_debugfs_remove(wil);
        wil_if_remove(wil);
        wil_if_pcie_disable(wil);
-       if (wil->platform_ops.uninit)
-               wil->platform_ops.uninit(wil->platform_handle);
-       wil_if_free(wil);
        pci_iounmap(pdev, csr);
        pci_release_region(pdev, 0);
        pci_disable_device(pdev);
+       if (wil->platform_ops.uninit)
+               wil->platform_ops.uninit(wil->platform_handle);
+       wil_if_free(wil);
 }
 
 static const struct pci_device_id wil6210_pcie_ids[] = {
@@ -291,7 +300,27 @@ static struct pci_driver wil6210_driver = {
        .name           = WIL_NAME,
 };
 
-module_pci_driver(wil6210_driver);
+static int __init wil6210_driver_init(void)
+{
+       int rc;
+
+       rc = wil_platform_modinit();
+       if (rc)
+               return rc;
+
+       rc = pci_register_driver(&wil6210_driver);
+       if (rc)
+               wil_platform_modexit();
+       return rc;
+}
+module_init(wil6210_driver_init);
+
+static void __exit wil6210_driver_exit(void)
+{
+       pci_unregister_driver(&wil6210_driver);
+       wil_platform_modexit();
+}
+module_exit(wil6210_driver_exit);
 
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>");
index 0113dac3a9a9f33b6190609e26057777a35aa8ff..aa20af86e1d61e790a4ba054c9db383ec2968b15 100644 (file)
@@ -427,6 +427,8 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
        cid = wil_rxdesc_cid(d);
        stats = &wil->sta[cid].stats;
        stats->last_mcs_rx = wil_rxdesc_mcs(d);
+       if (stats->last_mcs_rx < ARRAY_SIZE(stats->rx_per_mcs))
+               stats->rx_per_mcs[stats->last_mcs_rx]++;
 
        /* use radiotap header only if required */
        if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
index f3513a1fa4240d8b44504c987e07aa948c99953e..275355d46a36fc8c2ae85585fc7188c0a7e64473 100644 (file)
@@ -281,7 +281,7 @@ struct fw_map {
 };
 
 /* array size should be in sync with actual definition in the wmi.c */
-extern const struct fw_map fw_mapping[7];
+extern const struct fw_map fw_mapping[8];
 
 /**
  * mk_cidxtid - construct @cidxtid field
@@ -464,6 +464,7 @@ enum wil_sta_status {
 };
 
 #define WIL_STA_TID_NUM (16)
+#define WIL_MCS_MAX (12) /* Maximum MCS supported */
 
 struct wil_net_stats {
        unsigned long   rx_packets;
@@ -473,6 +474,7 @@ struct wil_net_stats {
        unsigned long   tx_errors;
        unsigned long   rx_dropped;
        u16 last_mcs_rx;
+       u64 rx_per_mcs[WIL_MCS_MAX + 1];
 };
 
 /**
@@ -684,7 +686,7 @@ void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
 void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
                        size_t count);
 
-void *wil_if_alloc(struct device *dev, void __iomem *csr);
+void *wil_if_alloc(struct device *dev);
 void wil_if_free(struct wil6210_priv *wil);
 int wil_if_add(struct wil6210_priv *wil);
 void wil_if_remove(struct wil6210_priv *wil);
@@ -762,7 +764,8 @@ struct wireless_dev *wil_cfg80211_init(struct device *dev);
 void wil_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);
+int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
+                 u8 chan, u8 hidden_ssid);
 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 976a071ba74e95dd79669a33ff9dd256c09e29bb..de15f1422fe9faefe225dd618aecbe688c7a443d 100644 (file)
 #include "linux/device.h"
 #include "wil_platform.h"
 
+int __init wil_platform_modinit(void)
+{
+       return 0;
+}
+
+void wil_platform_modexit(void)
+{
+}
+
 /**
  * wil_platform_init() - wil6210 platform module init
  *
  */
 void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops)
 {
-       void *handle = NULL;
+       void *handle = ops; /* to return some non-NULL for 'void' impl. */
 
        if (!ops) {
-               dev_err(dev, "Invalid parameter. Cannot init platform module\n");
+               dev_err(dev,
+                       "Invalid parameter. Cannot init platform module\n");
                return NULL;
        }
 
index 158c73b049a9b583602b54763d322d9bfd27bffa..d7fa19b7886dddf7bc08e3c15daabd95d319a476 100644 (file)
@@ -31,4 +31,7 @@ struct wil_platform_ops {
 
 void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops);
 
+int __init wil_platform_modinit(void);
+void wil_platform_modexit(void);
+
 #endif /* __WIL_PLATFORM_H__ */
index 3dc8daf69bd2309bdcf9d0719e71bac6b707771d..c759759afbb2dfe63f8d2f7dd20f718d16d2591b 100644 (file)
@@ -85,6 +85,7 @@ const struct fw_map fw_mapping[] = {
        {0x880000, 0x88a000, 0x880000, "rgf"},     /* various RGF       40k */
        {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table          4k */
        {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf       4k */
+       {0x88c000, 0x88c200, 0x88c000, "mac_rgf_ext"}, /* mac_ext_rgf  512b */
        {0x8c0000, 0x949000, 0x8c0000, "upper"},   /* upper area       548k */
        /*
         * 920000..930000 ucode code RAM
@@ -824,7 +825,8 @@ int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
        return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
 }
 
-int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan)
+int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
+                 u8 chan, u8 hidden_ssid)
 {
        int rc;
 
@@ -834,6 +836,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan)
                .disable_sec_offload = 1,
                .channel = chan - 1,
                .pcp_max_assoc_sta = max_assoc_sta,
+               .hidden_ssid = hidden_ssid,
        };
        struct {
                struct wil6210_mbox_hdr_wmi wmi;
index cc04ab73b398c83c74675e0137b02b9818d61f63..6e90e78f1554c84c3f0ab820ede5ed4c5437ce3d 100644 (file)
@@ -495,10 +495,18 @@ struct wmi_power_mgmt_cfg_cmd {
 /*
  * WMI_PCP_START_CMDID
  */
+
+enum wmi_hidden_ssid {
+       WMI_HIDDEN_SSID_DISABLED        = 0,
+       WMI_HIDDEN_SSID_SEND_EMPTY      = 1,
+       WMI_HIDDEN_SSID_CLEAR   = 2,
+};
+
 struct wmi_pcp_start_cmd {
        __le16 bcon_interval;
        u8 pcp_max_assoc_sta;
-       u8 reserved0[9];
+       u8 hidden_ssid;
+       u8 reserved0[8];
        u8 network_type;
        u8 channel;
        u8 disable_sec_offload;