Merge tag 'wireless-drivers-next-for-davem-2015-06-18' of git://git.kernel.org/pub...
authorDavid S. Miller <davem@davemloft.net>
Tue, 23 Jun 2015 08:03:18 +0000 (01:03 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 23 Jun 2015 08:03:18 +0000 (01:03 -0700)
Kalle Valo says:

====================
Major changes:

mwifiex:

* enhancements for AP mode: support verbose information in station
  dump command and also information about AP link.
* enable power save by default

brcmfmac:

* fix module reload issue for PCIe
* improving msgbuf protocol for PCIe devices
* rework .get_station() cfg80211 callback operation
* determine interface combinations upon device feature support

ath9k:

* ath9k_htc: add support of channel switch

wil6210:

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

Signed-off-by: David S. Miller <davem@davemloft.net>
86 files changed:
MAINTAINERS
drivers/bcma/Kconfig
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/ath9k/htc.h
drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
drivers/net/wireless/ath/ath9k/htc_drv_init.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/main.c
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
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/commonring.c
drivers/net/wireless/brcm80211/brcmfmac/commonring.h
drivers/net/wireless/brcm80211/brcmfmac/core.c
drivers/net/wireless/brcm80211/brcmfmac/debug.c
drivers/net/wireless/brcm80211/brcmfmac/feature.c
drivers/net/wireless/brcm80211/brcmfmac/feature.h
drivers/net/wireless/brcm80211/brcmfmac/firmware.c
drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/brcm80211/brcmfmac/sdio.c
drivers/net/wireless/mediatek/mt7601u/dma.c
drivers/net/wireless/mediatek/mt7601u/eeprom.c
drivers/net/wireless/mediatek/mt7601u/init.c
drivers/net/wireless/mediatek/mt7601u/mac.c
drivers/net/wireless/mediatek/mt7601u/main.c
drivers/net/wireless/mediatek/mt7601u/usb.c
drivers/net/wireless/mwifiex/11h.c
drivers/net/wireless/mwifiex/11n.c
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/decl.h
drivers/net/wireless/mwifiex/fw.h
drivers/net/wireless/mwifiex/ie.c
drivers/net/wireless/mwifiex/ioctl.h
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/mwifiex/uap_cmd.c
drivers/net/wireless/mwifiex/uap_event.c
drivers/net/wireless/mwifiex/uap_txrx.c
drivers/net/wireless/mwifiex/util.c
drivers/net/wireless/rt2x00/rt2800.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rtlwifi/rtl8188ee/dm.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/wireless/rtlwifi/rtl8192de/dm.c
drivers/net/wireless/rtlwifi/rtl8192se/dm.c
drivers/net/wireless/rtlwifi/rtl8723be/dm.c
drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/ti/wl1251/acx.c
include/linux/bcma/bcma_driver_pci.h

index a7d9bfe04c6bf2c63c98ed6242e1024bbe43f12d..2e122946692c0dd305ae02aad7082484182b1d8f 100644 (file)
@@ -8169,8 +8169,6 @@ P:        rt2x00 project
 M:     Stanislaw Gruszka <sgruszka@redhat.com>
 M:     Helmut Schaa <helmut.schaa@googlemail.com>
 L:     linux-wireless@vger.kernel.org
-L:     users@rt2x00.serialmonkey.com (moderated for non-subscribers)
-W:     http://rt2x00.serialmonkey.com/
 S:     Maintained
 F:     drivers/net/wireless/rt2x00/
 
index fc6ffcfa80618efded04b72b1501ca505683a3b0..be5fffb6da2480845d14f920bd012db184887734 100644 (file)
@@ -29,12 +29,6 @@ config BCMA_HOST_PCI
        select BCMA_DRIVER_PCI
        default y
 
-config BCMA_DRIVER_PCI_HOSTMODE
-       bool "Driver for PCI core working in hostmode"
-       depends on BCMA && MIPS && BCMA_HOST_PCI
-       help
-         PCI core hostmode operation (external PCI bus).
-
 config BCMA_HOST_SOC
        bool "Support for BCMA in a SoC"
        depends on BCMA
@@ -61,6 +55,12 @@ config BCMA_DRIVER_PCI
          This driver is also prerequisite for a hostmode PCIe core
          support.
 
+config BCMA_DRIVER_PCI_HOSTMODE
+       bool "Driver for PCI core working in hostmode"
+       depends on BCMA && MIPS && BCMA_DRIVER_PCI
+       help
+         PCI core hostmode operation (external PCI bus).
+
 config BCMA_DRIVER_MIPS
        bool "BCMA Broadcom MIPS core driver"
        depends on BCMA && MIPS
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 609ca8619ebde1747a695a490d507f13aa5bef36..218b6af63447458fa81960479afeeecf9a1520e9 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 5dbc617ecf8a824eb61e5cf8d0bd231717f72a3f..16dff4b89a86fc43635f0e91c2981372e575eda6 100644 (file)
@@ -531,6 +531,7 @@ struct ath9k_htc_priv {
        struct ath9k_debug debug;
 #endif
        struct mutex mutex;
+       struct ieee80211_vif *csa_vif;
 };
 
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
@@ -584,6 +585,7 @@ void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
 void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
 void ath9k_tx_failed_tasklet(unsigned long data);
 void ath9k_htc_tx_cleanup_timer(unsigned long data);
+bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv);
 
 int ath9k_rx_init(struct ath9k_htc_priv *priv);
 void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
index e8b6ec3c1dbbb01bd2ea7d122dbe747c9d8f6d96..e6bcb4c90fa0120c9e96abe2f2d586877b6f12cf 100644 (file)
@@ -257,6 +257,8 @@ static void ath9k_htc_send_beacon(struct ath9k_htc_priv *priv,
        }
 
        spin_unlock_bh(&priv->beacon_lock);
+
+       ath9k_htc_csa_is_finished(priv);
 }
 
 static int ath9k_htc_choose_bslot(struct ath9k_htc_priv *priv,
@@ -503,3 +505,20 @@ void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv)
                return;
        }
 }
+
+bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv)
+{
+       struct ieee80211_vif *vif;
+
+       vif = priv->csa_vif;
+       if (!vif || !vif->csa_active)
+               return false;
+
+       if (!ieee80211_csa_is_complete(vif))
+               return false;
+
+       ieee80211_csa_finish(vif);
+
+       priv->csa_vif = NULL;
+       return true;
+}
index 36218ee2bdbe86184a205614e10aebcc50f32a7e..39eaf9b6e9b45c610dbf40208151431bbf51b64c 100644 (file)
@@ -744,7 +744,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
        hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
-                           WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+                           WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
+                           WIPHY_FLAG_HAS_CHANNEL_SWITCH;
 
        hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
 
index b71f3072fd9a937ca5f67f2471d85e05761b1d32..dab1323dfec76a1b09183bb8779e482dd7299c49 100644 (file)
@@ -1134,6 +1134,9 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw,
        priv->nvifs--;
        priv->vif_slot &= ~(1 << avp->index);
 
+       if (priv->csa_vif == vif)
+               priv->csa_vif = NULL;
+
        ath9k_htc_remove_station(priv, vif, NULL);
 
        DEC_VIF(priv, vif->type);
@@ -1841,6 +1844,19 @@ static int ath9k_htc_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant,
        return 0;
 }
 
+static void ath9k_htc_channel_switch_beacon(struct ieee80211_hw *hw,
+                                           struct ieee80211_vif *vif,
+                                           struct cfg80211_chan_def *chandef)
+{
+       struct ath9k_htc_priv *priv = hw->priv;
+
+       /* mac80211 does not support CSA in multi-if cases (yet) */
+       if (WARN_ON(priv->csa_vif))
+               return;
+
+       priv->csa_vif = vif;
+}
+
 struct ieee80211_ops ath9k_htc_ops = {
        .tx                 = ath9k_htc_tx,
        .start              = ath9k_htc_start,
@@ -1867,6 +1883,7 @@ struct ieee80211_ops ath9k_htc_ops = {
        .set_bitrate_mask   = ath9k_htc_set_bitrate_mask,
        .get_stats          = ath9k_htc_get_stats,
        .get_antenna        = ath9k_htc_get_antenna,
+       .channel_switch_beacon  = ath9k_htc_channel_switch_beacon,
 
 #ifdef CONFIG_ATH9K_HTC_DEBUGFS
        .get_et_sset_count  = ath9k_htc_get_et_sset_count,
index d285e3a89853dc3cb9fa968caec77ca2b07f10b5..cfd45cb8ccfc13df856bb4bbe07d8e2bef21228f 100644 (file)
@@ -216,11 +216,13 @@ static bool ath_prepare_reset(struct ath_softc *sc)
        ath_stop_ani(sc);
        ath9k_hw_disable_interrupts(ah);
 
-       if (!ath_drain_all_txq(sc))
-               ret = false;
-
-       if (!ath_stoprecv(sc))
-               ret = false;
+       if (AR_SREV_9300_20_OR_LATER(ah)) {
+               ret &= ath_stoprecv(sc);
+               ret &= ath_drain_all_txq(sc);
+       } else {
+               ret &= ath_drain_all_txq(sc);
+               ret &= ath_stoprecv(sc);
+       }
 
        return ret;
 }
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;
index 575b9f4b5589a157a35a08f20baec1381b251ea0..28490702124a0da53bb2834f1ca880a452d6523b 100644 (file)
@@ -5361,6 +5361,10 @@ static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy,
                *have_5ghz_phy = true;
                return;
        case 0x4321: /* BCM4306 */
+               /* There are 14e4:4321 PCI devs with 2.4 GHz BCM4321 (N-PHY) */
+               if (dev->phy.type != B43_PHYTYPE_G)
+                       break;
+               /* fall through */
        case 0x4313: /* BCM4311 */
        case 0x431a: /* BCM4318 */
        case 0x432a: /* BCM4321 */
index 71779b9e4bbef3569a3543a5bcc69b4d4bb4cf76..410a6645d316ec1c2cf5d09b54847e918dde0045 100644 (file)
@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
 
 static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
 {
+       sdiodev->state = BRCMF_SDIOD_DOWN;
        if (sdiodev->bus) {
                brcmf_sdio_remove(sdiodev->bus);
                sdiodev->bus = NULL;
index e10fa67010c072f4d2377cd2e42ed3c3802157fe..d86d1f1f1c91d70ea803cfd07737ecaab6699400 100644 (file)
@@ -52,8 +52,6 @@
 #define BRCMF_PNO_SCAN_COMPLETE                1
 #define BRCMF_PNO_SCAN_INCOMPLETE      0
 
-#define BRCMF_IFACE_MAX_CNT            3
-
 #define WPA_OUI                                "\x00\x50\xF2"  /* WPA OUI */
 #define WPA_OUI_TYPE                   1
 #define RSN_OUI                                "\x00\x0F\xAC"  /* RSN OUI */
@@ -2398,27 +2396,80 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
                brcmf_err("set wsec error (%d)\n", err);
 }
 
+static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si)
+{
+       struct nl80211_sta_flag_update *sfu;
+
+       brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags);
+       si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS);
+       sfu = &si->sta_flags;
+       sfu->mask = BIT(NL80211_STA_FLAG_WME) |
+                   BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+                   BIT(NL80211_STA_FLAG_ASSOCIATED) |
+                   BIT(NL80211_STA_FLAG_AUTHORIZED);
+       if (fw_sta_flags & BRCMF_STA_WME)
+               sfu->set |= BIT(NL80211_STA_FLAG_WME);
+       if (fw_sta_flags & BRCMF_STA_AUTHE)
+               sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED);
+       if (fw_sta_flags & BRCMF_STA_ASSOC)
+               sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
+       if (fw_sta_flags & BRCMF_STA_AUTHO)
+               sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
+}
+
+static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
+{
+       struct {
+               __le32 len;
+               struct brcmf_bss_info_le bss_le;
+       } *buf;
+       u16 capability;
+       int err;
+
+       buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+       if (!buf)
+               return;
+
+       buf->len = cpu_to_le32(WL_BSS_INFO_MAX);
+       err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf,
+                                    WL_BSS_INFO_MAX);
+       if (err) {
+               brcmf_err("Failed to get bss info (%d)\n", err);
+               return;
+       }
+       si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
+       si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period);
+       si->bss_param.dtim_period = buf->bss_le.dtim_period;
+       capability = le16_to_cpu(buf->bss_le.capability);
+       if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT)
+               si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT;
+       if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+               si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE;
+       if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
+               si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME;
+}
+
 static s32
 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
                           const u8 *mac, struct station_info *sinfo)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
-       struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
-       struct brcmf_scb_val_le scb_val;
-       int rssi;
-       s32 rate;
        s32 err = 0;
-       u8 *bssid = profile->bssid;
        struct brcmf_sta_info_le sta_info_le;
-       u32 beacon_period;
-       u32 dtim_period;
+       u32 sta_flags;
+       u32 is_tdls_peer;
 
        brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac);
        if (!check_vif_up(ifp->vif))
                return -EIO;
 
-       if (brcmf_is_apmode(ifp->vif)) {
-               memcpy(&sta_info_le, mac, ETH_ALEN);
+       memset(&sta_info_le, 0, sizeof(sta_info_le));
+       memcpy(&sta_info_le, mac, ETH_ALEN);
+       err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
+                                      &sta_info_le,
+                                      sizeof(sta_info_le));
+       is_tdls_peer = !err;
+       if (err) {
                err = brcmf_fil_iovar_data_get(ifp, "sta_info",
                                               &sta_info_le,
                                               sizeof(sta_info_le));
@@ -2426,73 +2477,48 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
                        brcmf_err("GET STA INFO failed, %d\n", err);
                        goto done;
                }
-               sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
-               sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
-               if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) {
-                       sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
-                       sinfo->connected_time = le32_to_cpu(sta_info_le.in);
-               }
-               brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n",
-                         sinfo->inactive_time, sinfo->connected_time);
-       } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) {
-               if (memcmp(mac, bssid, ETH_ALEN)) {
-                       brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n",
-                                 mac, bssid);
-                       err = -ENOENT;
-                       goto done;
-               }
-               /* Report the current tx rate */
-               err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
-               if (err) {
-                       brcmf_err("Could not get rate (%d)\n", err);
-                       goto done;
-               } else {
+       }
+       brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver));
+       sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME);
+       sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000;
+       sta_flags = le32_to_cpu(sta_info_le.flags);
+       brcmf_convert_sta_flags(sta_flags, sinfo);
+       sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+       if (is_tdls_peer)
+               sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
+       else
+               sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
+       if (sta_flags & BRCMF_STA_ASSOC) {
+               sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME);
+               sinfo->connected_time = le32_to_cpu(sta_info_le.in);
+               brcmf_fill_bss_param(ifp, sinfo);
+       }
+       if (sta_flags & BRCMF_STA_SCBSTATS) {
+               sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED);
+               sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures);
+               sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS);
+               sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts);
+               sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts);
+               sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
+               sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts);
+               sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts);
+               if (sinfo->tx_packets) {
                        sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
-                       sinfo->txrate.legacy = rate * 5;
-                       brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2);
+                       sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate);
+                       sinfo->txrate.legacy /= 100;
                }
-
-               if (test_bit(BRCMF_VIF_STATUS_CONNECTED,
-                            &ifp->vif->sme_state)) {
-                       memset(&scb_val, 0, sizeof(scb_val));
-                       err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI,
-                                                    &scb_val, sizeof(scb_val));
-                       if (err) {
-                               brcmf_err("Could not get rssi (%d)\n", err);
-                               goto done;
-                       } else {
-                               rssi = le32_to_cpu(scb_val.val);
-                               sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
-                               sinfo->signal = rssi;
-                               brcmf_dbg(CONN, "RSSI %d dBm\n", rssi);
-                       }
-                       err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD,
-                                                   &beacon_period);
-                       if (err) {
-                               brcmf_err("Could not get beacon period (%d)\n",
-                                         err);
-                               goto done;
-                       } else {
-                               sinfo->bss_param.beacon_interval =
-                                       beacon_period;
-                               brcmf_dbg(CONN, "Beacon peroid %d\n",
-                                         beacon_period);
-                       }
-                       err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD,
-                                                   &dtim_period);
-                       if (err) {
-                               brcmf_err("Could not get DTIM period (%d)\n",
-                                         err);
-                               goto done;
-                       } else {
-                               sinfo->bss_param.dtim_period = dtim_period;
-                               brcmf_dbg(CONN, "DTIM peroid %d\n",
-                                         dtim_period);
-                       }
-                       sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM);
+               if (sinfo->rx_packets) {
+                       sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE);
+                       sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate);
+                       sinfo->rxrate.legacy /= 100;
                }
-       } else
-               err = -EPERM;
+               if (le16_to_cpu(sta_info_le.ver) >= 4) {
+                       sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES);
+                       sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes);
+                       sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES);
+                       sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes);
+               }
+       }
 done:
        brcmf_dbg(TRACE, "Exit\n");
        return err;
@@ -5640,53 +5666,6 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
        return 0;
 }
 
-static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
-       {
-               .max = 1,
-               .types = BIT(NL80211_IFTYPE_STATION) |
-                        BIT(NL80211_IFTYPE_ADHOC)
-       },
-       {
-               .max = 4,
-               .types = BIT(NL80211_IFTYPE_AP)
-       },
-       {
-               .max = 1,
-               .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-                        BIT(NL80211_IFTYPE_P2P_GO)
-       },
-       {
-               .max = 1,
-               .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
-       }
-};
-
-static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
-       {
-               .max = 2,
-               .types = BIT(NL80211_IFTYPE_STATION) |
-                        BIT(NL80211_IFTYPE_ADHOC) |
-                        BIT(NL80211_IFTYPE_AP)
-       },
-       {
-               .max = 1,
-               .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
-                        BIT(NL80211_IFTYPE_P2P_GO)
-       },
-       {
-               .max = 1,
-               .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
-       }
-};
-static struct ieee80211_iface_combination brcmf_iface_combos[] = {
-       {
-                .max_interfaces = BRCMF_IFACE_MAX_CNT,
-                .num_different_channels = 1,
-                .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
-                .limits = brcmf_iface_limits_sbss,
-       }
-};
-
 static const struct ieee80211_txrx_stypes
 brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
        [NL80211_IFTYPE_STATION] = {
@@ -5716,6 +5695,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = {
        }
 };
 
+static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp)
+{
+       struct ieee80211_iface_combination *combo = NULL;
+       struct ieee80211_iface_limit *limits = NULL;
+       int i = 0, max_iface_cnt;
+
+       combo = kzalloc(sizeof(*combo), GFP_KERNEL);
+       if (!combo)
+               goto err;
+
+       limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL);
+       if (!limits)
+               goto err;
+
+       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+                                BIT(NL80211_IFTYPE_ADHOC) |
+                                BIT(NL80211_IFTYPE_AP);
+
+       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
+               combo->num_different_channels = 2;
+       else
+               combo->num_different_channels = 1;
+
+       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
+               limits[i].max = 1;
+               limits[i++].types = BIT(NL80211_IFTYPE_STATION);
+               limits[i].max = 4;
+               limits[i++].types = BIT(NL80211_IFTYPE_AP);
+               max_iface_cnt = 5;
+       } else {
+               limits[i].max = 2;
+               limits[i++].types = BIT(NL80211_IFTYPE_STATION) |
+                                   BIT(NL80211_IFTYPE_AP);
+               max_iface_cnt = 2;
+       }
+
+       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) {
+               wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
+                                         BIT(NL80211_IFTYPE_P2P_GO) |
+                                         BIT(NL80211_IFTYPE_P2P_DEVICE);
+               limits[i].max = 1;
+               limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
+                                   BIT(NL80211_IFTYPE_P2P_GO);
+               limits[i].max = 1;
+               limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
+               max_iface_cnt += 2;
+       }
+       combo->max_interfaces = max_iface_cnt;
+       combo->limits = limits;
+       combo->n_limits = i;
+
+       wiphy->iface_combinations = combo;
+       wiphy->n_iface_combinations = 1;
+       return 0;
+
+err:
+       kfree(limits);
+       kfree(combo);
+       return -ENOMEM;
+}
+
 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
 {
        /* scheduled scan settings */
@@ -5746,7 +5786,6 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy)
 static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
 {
        struct ieee80211_supported_band *band;
-       struct ieee80211_iface_combination ifc_combo;
        __le32 bandlist[3];
        u32 n_bands;
        int err, i;
@@ -5754,24 +5793,11 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
        wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
        wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
        wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
-       wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-                                BIT(NL80211_IFTYPE_ADHOC) |
-                                BIT(NL80211_IFTYPE_AP) |
-                                BIT(NL80211_IFTYPE_P2P_CLIENT) |
-                                BIT(NL80211_IFTYPE_P2P_GO) |
-                                BIT(NL80211_IFTYPE_P2P_DEVICE);
-       /* need VSDB firmware feature for concurrent channels */
-       ifc_combo = brcmf_iface_combos[0];
-       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
-               ifc_combo.num_different_channels = 2;
-       if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
-               ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
-               ifc_combo.limits = brcmf_iface_limits_mbss;
-       }
-       wiphy->iface_combinations = kmemdup(&ifc_combo,
-                                           sizeof(ifc_combo),
-                                           GFP_KERNEL);
-       wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos);
+
+       err = brcmf_setup_ifmodes(wiphy, ifp);
+       if (err)
+               return err;
+
        wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
        wiphy->cipher_suites = __wl_cipher_suites;
        wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
@@ -6036,6 +6062,8 @@ static void brcmf_free_wiphy(struct wiphy *wiphy)
        if (!wiphy)
                return;
 
+       if (wiphy->iface_combinations)
+               kfree(wiphy->iface_combinations->limits);
        kfree(wiphy->iface_combinations);
        if (wiphy->bands[IEEE80211_BAND_2GHZ]) {
                kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels);
@@ -6071,6 +6099,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
                brcmf_err("Could not allocate wiphy device\n");
                return NULL;
        }
+       memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN);
        set_wiphy_dev(wiphy, busdev);
 
        cfg = wiphy_priv(wiphy);
@@ -6178,10 +6207,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
        if (!cfg)
                return;
 
-       WARN_ON(!list_empty(&cfg->vif_list));
-       wiphy_unregister(cfg->wiphy);
        brcmf_btcoex_detach(cfg);
-       brcmf_p2p_detach(&cfg->p2p);
+       wiphy_unregister(cfg->wiphy);
        wl_deinit_priv(cfg);
        brcmf_free_wiphy(cfg->wiphy);
 }
index 26c65872dae3b1b7184d377277a7fe86e125d5eb..7b0e52195a85668e91a32163130df5aea55499ee 100644 (file)
@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
 void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
                                    u16 *n_items)
 {
-       void *ret_addr;
-
        if (commonring->cr_update_wptr)
                commonring->cr_update_wptr(commonring->cr_ctx);
 
@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
        if (*n_items == 0)
                return NULL;
 
-       ret_addr = commonring->buf_addr +
-                  (commonring->r_ptr * commonring->item_len);
-
-       commonring->r_ptr += *n_items;
-       if (commonring->r_ptr == commonring->depth)
-               commonring->r_ptr = 0;
-
-       return ret_addr;
+       return commonring->buf_addr +
+              (commonring->r_ptr * commonring->item_len);
 }
 
 
-int brcmf_commonring_read_complete(struct brcmf_commonring *commonring)
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
+                                  u16 n_items)
 {
+       commonring->r_ptr += n_items;
+       if (commonring->r_ptr == commonring->depth)
+               commonring->r_ptr = 0;
+
        if (commonring->cr_write_rptr)
                return commonring->cr_write_rptr(commonring->cr_ctx);
 
index 3d404016a92eb9e5cdcbcf49c9872d0e5a2966bf..b85033611c8d1d156d39cc2d20d4c7dc10b9f32e 100644 (file)
@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
                                   u16 n_items);
 void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
                                    u16 *n_items);
-int brcmf_commonring_read_complete(struct brcmf_commonring *commonring);
+int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
+                                  u16 n_items);
 
 #define brcmf_commonring_n_items(commonring) (commonring->depth)
 #define brcmf_commonring_len_item(commonring) (commonring->item_len)
index f8f47dcfa886278caf5d694bc9d7a0eadadb8ccd..fe9d3fbf5fe21e0c74c5852254c2682f3725ff18 100644 (file)
@@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
                }
                /* unregister will take care of freeing it */
                unregister_netdev(ifp->ndev);
-       } else {
-               kfree(ifp);
        }
 }
 
@@ -1100,6 +1098,8 @@ void brcmf_detach(struct device *dev)
 
        /* stop firmware event handling */
        brcmf_fweh_detach(drvr);
+       if (drvr->config)
+               brcmf_p2p_detach(&drvr->config->p2p);
 
        brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
 
index 9b473d50b0058d68ba8cf60c02f4cbd55b60edb0..2d6d0055385877087a467dfa1ab265538fdb7102 100644 (file)
@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void)
        root_folder = NULL;
 }
 
-static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
-{
-       struct brcmf_bus *bus = dev_get_drvdata(seq->private);
-
-       seq_printf(seq, "chip: %x(%u) rev %u\n",
-                  bus->chip, bus->chip, bus->chiprev);
-       return 0;
-}
-
 int brcmf_debugfs_attach(struct brcmf_pub *drvr)
 {
        struct device *dev = drvr->bus_if->dev;
@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
                return -ENODEV;
 
        drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
-       brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
 
        return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
 }
@@ -74,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
        return drvr->dbgfs_dir;
 }
 
-struct brcmf_debugfs_entry {
-       int (*read)(struct seq_file *seq, void *data);
-       struct brcmf_pub *drvr;
-};
-
-static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
-{
-       struct brcmf_debugfs_entry *entry = inode->i_private;
-
-       return single_open(f, entry->read, entry->drvr->bus_if->dev);
-}
-
-static const struct file_operations brcmf_debugfs_def_ops = {
-       .owner = THIS_MODULE,
-       .open = brcmf_debugfs_entry_open,
-       .release = single_release,
-       .read = seq_read,
-       .llseek = seq_lseek
-};
-
 int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
                            int (*read_fn)(struct seq_file *seq, void *data))
 {
-       struct dentry *dentry =  drvr->dbgfs_dir;
-       struct brcmf_debugfs_entry *entry;
-
-       if (IS_ERR_OR_NULL(dentry))
-               return -ENOENT;
-
-       entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
-       if (!entry)
-               return -ENOMEM;
-
-       entry->read = read_fn;
-       entry->drvr = drvr;
-
-       dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
-                                    &brcmf_debugfs_def_ops);
+       struct dentry *e;
 
-       return PTR_ERR_OR_ZERO(dentry);
+       e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
+                                       drvr->dbgfs_dir, read_fn);
+       return PTR_ERR_OR_ZERO(e);
 }
index 2c5fad3a3aa22523e57dfb97d2d0110d7fbfe820..1e94e94e01dc91c829e45f2efd16559e494e086f 100644 (file)
@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
                brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
        if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
                brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
+       brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
 
        /* set chip related quirks */
        switch (drvr->bus_if->chip) {
index 546962525cd2a1a302bdf43667b894176fbf4a40..6b381f799f228b5cb2e6b0f62c2556b7747a7e3d 100644 (file)
  * MCHAN: multi-channel for concurrent P2P.
  * PNO: preferred network offload.
  * WOWL: Wake-On-WLAN.
+ * P2P: peer-to-peer
  */
 #define BRCMF_FEAT_LIST \
        BRCMF_FEAT_DEF(MBSS) \
        BRCMF_FEAT_DEF(MCHAN) \
        BRCMF_FEAT_DEF(PNO) \
-       BRCMF_FEAT_DEF(WOWL)
+       BRCMF_FEAT_DEF(WOWL) \
+       BRCMF_FEAT_DEF(P2P)
 /*
  * Quirks:
  *
index 7ae6461df932b77bfe97e7add765c48de1e53616..743f16b6a07296e8e5b695598002d78669222870 100644 (file)
@@ -43,7 +43,7 @@ enum nvram_parser_state {
  * struct nvram_parser - internal info for parser.
  *
  * @state: current parser state.
- * @fwnv: input buffer being parsed.
+ * @data: input buffer being parsed.
  * @nvram: output buffer with parse result.
  * @nvram_len: lenght of parse result.
  * @line: current line.
@@ -55,7 +55,7 @@ enum nvram_parser_state {
  */
 struct nvram_parser {
        enum nvram_parser_state state;
-       const struct firmware *fwnv;
+       const u8 *data;
        u8 *nvram;
        u32 nvram_len;
        u32 line;
@@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
 {
        char c;
 
-       c = nvp->fwnv->data[nvp->pos];
+       c = nvp->data[nvp->pos];
        if (c == '\n')
                return COMMENT;
        if (is_whitespace(c))
@@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
        enum nvram_parser_state st = nvp->state;
        char c;
 
-       c = nvp->fwnv->data[nvp->pos];
+       c = nvp->data[nvp->pos];
        if (c == '=') {
                /* ignore RAW1 by treating as comment */
-               if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0)
+               if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
                        st = COMMENT;
                else
                        st = VALUE;
-               if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0)
+               if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
                        nvp->multi_dev_v1 = true;
-               if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0)
+               if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
                        nvp->multi_dev_v2 = true;
        } else if (!is_nvram_char(c) || c == ' ') {
                brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
@@ -145,11 +145,11 @@ brcmf_nvram_handle_value(struct nvram_parser *nvp)
        char *ekv;
        u32 cplen;
 
-       c = nvp->fwnv->data[nvp->pos];
+       c = nvp->data[nvp->pos];
        if (!is_nvram_char(c)) {
                /* key,value pair complete */
-               ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
-               skv = (u8 *)&nvp->fwnv->data[nvp->entry];
+               ekv = (u8 *)&nvp->data[nvp->pos];
+               skv = (u8 *)&nvp->data[nvp->entry];
                cplen = ekv - skv;
                if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
                        return END;
@@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_parser *nvp)
 {
        char *eoc, *sol;
 
-       sol = (char *)&nvp->fwnv->data[nvp->pos];
+       sol = (char *)&nvp->data[nvp->pos];
        eoc = strchr(sol, '\n');
        if (!eoc) {
                eoc = strchr(sol, '\0');
@@ -201,17 +201,17 @@ static enum nvram_parser_state
 };
 
 static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
-                                  const struct firmware *nv)
+                                  const u8 *data, size_t data_len)
 {
        size_t size;
 
        memset(nvp, 0, sizeof(*nvp));
-       nvp->fwnv = nv;
+       nvp->data = data;
        /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
-       if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE)
+       if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
                size = BRCMF_FW_MAX_NVRAM_SIZE;
        else
-               size = nv->size;
+               size = data_len;
        /* Alloc for extra 0 byte + roundup by 4 + length field */
        size += 1 + 3 + sizeof(u32);
        nvp->nvram = kzalloc(size, GFP_KERNEL);
@@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
                                    u16 bus_nr)
 {
        /* Device path with a leading '=' key-value separator */
+       char pci_path[] = "=pci/?/?";
+       size_t pci_len;
        char pcie_path[] = "=pcie/?/?";
        size_t pcie_len;
 
@@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
        /* First search for the devpathX and see if it is the configuration
         * for domain_nr/bus_nr. Search complete nvp
         */
+       snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
+                bus_nr);
+       pci_len = strlen(pci_path);
        snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
                 bus_nr);
        pcie_len = strlen(pcie_path);
@@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
                /* Format: devpathX=pcie/Y/Z/
                 * Y = domain_nr, Z = bus_nr, X = virtual ID
                 */
-               if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) &&
-                   (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) {
+               if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
+                   (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
+                    !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
                        id = nvp->nvram[i + 7] - '0';
                        found = true;
                        break;
@@ -356,18 +362,18 @@ fail:
  * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
  * End of buffer is completed with token identifying length of buffer.
  */
-static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length,
-                                 u16 domain_nr, u16 bus_nr)
+static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
+                                 u32 *new_length, u16 domain_nr, u16 bus_nr)
 {
        struct nvram_parser nvp;
        u32 pad;
        u32 token;
        __le32 token_le;
 
-       if (brcmf_init_nvram_parser(&nvp, nv) < 0)
+       if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
                return NULL;
 
-       while (nvp.pos < nv->size) {
+       while (nvp.pos < data_len) {
                nvp.state = nv_parser_states[nvp.state](&nvp);
                if (nvp.state == END)
                        break;
@@ -426,7 +432,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
                goto fail;
 
        if (fw) {
-               nvram = brcmf_fw_nvram_strip(fw, &nvram_length,
+               nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
                                             fwctx->domain_nr, fwctx->bus_nr);
                release_firmware(fw);
                if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
index 3749209651088b0c21beef1bbff9d240a475775f..297911f38fa0458e27ac1cfdd589dc01c4ef93b9 100644 (file)
 #define        BRCMF_BSS_INFO_VERSION  109 /* curr ver of brcmf_bss_info_le struct */
 #define BRCMF_BSS_RSSI_ON_CHANNEL      0x0002
 
-#define BRCMF_STA_ASSOC                        0x10            /* Associated */
+#define BRCMF_STA_WME              0x00000002      /* WMM association */
+#define BRCMF_STA_AUTHE            0x00000008      /* Authenticated */
+#define BRCMF_STA_ASSOC            0x00000010      /* Associated */
+#define BRCMF_STA_AUTHO            0x00000020      /* Authorized */
+#define BRCMF_STA_SCBSTATS         0x00004000      /* Per STA debug stats */
 
 /* size of brcmf_scan_params not including variable length array */
 #define BRCMF_SCAN_PARAMS_FIXED_SIZE   64
 #define BRCMF_WOWL_MAXPATTERNSIZE      128
 
 #define BRCMF_COUNTRY_BUF_SZ           4
+#define BRCMF_ANT_MAX                  4
 
 /* join preference types for join_pref iovar */
 enum brcmf_join_pref_types {
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
 };
 
 struct brcmf_sta_info_le {
-       __le16  ver;            /* version of this struct */
-       __le16  len;            /* length in bytes of this structure */
-       __le16  cap;            /* sta's advertised capabilities */
-       __le32  flags;          /* flags defined below */
-       __le32  idle;           /* time since data pkt rx'd from sta */
-       u8      ea[ETH_ALEN];           /* Station address */
-       __le32  count;                  /* # rates in this set */
-       u8      rates[BRCMF_MAXRATES_IN_SET];   /* rates in 500kbps units */
+       __le16 ver;             /* version of this struct */
+       __le16 len;             /* length in bytes of this structure */
+       __le16 cap;             /* sta's advertised capabilities */
+       __le32 flags;           /* flags defined below */
+       __le32 idle;            /* time since data pkt rx'd from sta */
+       u8 ea[ETH_ALEN];                /* Station address */
+       __le32 count;                   /* # rates in this set */
+       u8 rates[BRCMF_MAXRATES_IN_SET];        /* rates in 500kbps units */
                                                /* w/hi bit set if basic */
-       __le32  in;             /* seconds elapsed since associated */
-       __le32  listen_interval_inms; /* Min Listen interval in ms for STA */
-       __le32  tx_pkts;        /* # of packets transmitted */
-       __le32  tx_failures;    /* # of packets failed */
-       __le32  rx_ucast_pkts;  /* # of unicast packets received */
-       __le32  rx_mcast_pkts;  /* # of multicast packets received */
-       __le32  tx_rate;        /* Rate of last successful tx frame */
-       __le32  rx_rate;        /* Rate of last successful rx frame */
-       __le32  rx_decrypt_succeeds;    /* # of packet decrypted successfully */
-       __le32  rx_decrypt_failures;    /* # of packet decrypted failed */
+       __le32 in;              /* seconds elapsed since associated */
+       __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
+       __le32 tx_pkts; /* # of packets transmitted */
+       __le32 tx_failures;     /* # of packets failed */
+       __le32 rx_ucast_pkts;   /* # of unicast packets received */
+       __le32 rx_mcast_pkts;   /* # of multicast packets received */
+       __le32 tx_rate; /* Rate of last successful tx frame */
+       __le32 rx_rate; /* Rate of last successful rx frame */
+       __le32 rx_decrypt_succeeds;     /* # of packet decrypted successfully */
+       __le32 rx_decrypt_failures;     /* # of packet decrypted failed */
+       __le32 tx_tot_pkts;    /* # of tx pkts (ucast + mcast) */
+       __le32 rx_tot_pkts;    /* # of data packets recvd (uni + mcast) */
+       __le32 tx_mcast_pkts;  /* # of mcast pkts txed */
+       __le64 tx_tot_bytes;   /* data bytes txed (ucast + mcast) */
+       __le64 rx_tot_bytes;   /* data bytes recvd (ucast + mcast) */
+       __le64 tx_ucast_bytes; /* data bytes txed (ucast) */
+       __le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
+       __le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
+       __le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
+       s8 rssi[BRCMF_ANT_MAX];   /* per antenna rssi */
+       s8 nf[BRCMF_ANT_MAX];     /* per antenna noise floor */
+       __le16 aid;                    /* association ID */
+       __le16 ht_capabilities;        /* advertised ht caps */
+       __le16 vht_flags;              /* converted vht flags */
+       __le32 tx_pkts_retry_cnt;      /* # of frames where a retry was
+                                        * exhausted.
+                                        */
+       __le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
+                                        * was exhausted
+                                        */
+       s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
+                                           * received data frame.
+                                           */
+       /* TX WLAN retry/failure statistics:
+        * Separated for host requested frames and locally generated frames.
+        * Include unicast frame only where the retries/failures can be counted.
+        */
+       __le32 tx_pkts_total;          /* # user frames sent successfully */
+       __le32 tx_pkts_retries;        /* # user frames retries */
+       __le32 tx_pkts_fw_total;       /* # FW generated sent successfully */
+       __le32 tx_pkts_fw_retries;     /* # retries for FW generated frames */
+       __le32 tx_pkts_fw_retry_exhausted;     /* # FW generated where a retry
+                                               * was exhausted
+                                               */
+       __le32 rx_pkts_retried;        /* # rx with retry bit set */
+       __le32 tx_rate_fallback;       /* lowest fallback TX rate */
 };
 
 struct brcmf_chanspec_list {
index 1b47de067d25cbb4b194ca8eae02986a3f196092..898c3801e65874647694d281614e146379da8822 100644 (file)
@@ -75,6 +75,8 @@
 
 #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS       96
 #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS     32
+#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS                48
+
 
 struct msgbuf_common_hdr {
        u8                              msgtype;
@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
 {
        void *buf;
        u16 count;
+       u16 processed;
 
 again:
        buf = brcmf_commonring_get_read_ptr(commonring, &count);
        if (buf == NULL)
                return;
 
+       processed = 0;
        while (count) {
                brcmf_msgbuf_process_msgtype(msgbuf,
                                             buf + msgbuf->rx_dataoffset);
                buf += brcmf_commonring_len_item(commonring);
+               processed++;
+               if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
+                       brcmf_commonring_read_complete(commonring, processed);
+                       processed = 0;
+               }
                count--;
        }
-       brcmf_commonring_read_complete(commonring);
+       if (processed)
+               brcmf_commonring_read_complete(commonring, processed);
 
        if (commonring->r_ptr == 0)
                goto again;
index 710fbe570eb24da1d316c94679b0ed390bc1a29c..a9ba775a24c1c1eb6c17f3717e76e994d849f325 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 #include <net/cfg80211.h>
 
 #include <brcmu_wifi.h>
@@ -1907,105 +1908,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
 }
 
 
-/**
- * brcmf_p2p_attach() - attach for P2P.
- *
- * @cfg: driver private data for cfg80211 interface.
- */
-s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
-{
-       struct brcmf_if *pri_ifp;
-       struct brcmf_if *p2p_ifp;
-       struct brcmf_cfg80211_vif *p2p_vif;
-       struct brcmf_p2p_info *p2p;
-       struct brcmf_pub *drvr;
-       s32 bssidx;
-       s32 err = 0;
-
-       p2p = &cfg->p2p;
-       p2p->cfg = cfg;
-
-       drvr = cfg->pub;
-
-       pri_ifp = drvr->iflist[0];
-       p2p_ifp = drvr->iflist[1];
-
-       p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
-
-       if (p2p_ifp) {
-               p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
-                                         false);
-               if (IS_ERR(p2p_vif)) {
-                       brcmf_err("could not create discovery vif\n");
-                       err = -ENOMEM;
-                       goto exit;
-               }
-
-               p2p_vif->ifp = p2p_ifp;
-               p2p_ifp->vif = p2p_vif;
-               p2p_vif->wdev.netdev = p2p_ifp->ndev;
-               p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
-               SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
-
-               p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
-
-               brcmf_p2p_generate_bss_mac(p2p, NULL);
-               memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
-               brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
-
-               /* Initialize P2P Discovery in the firmware */
-               err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
-               if (err < 0) {
-                       brcmf_err("set p2p_disc error\n");
-                       brcmf_free_vif(p2p_vif);
-                       goto exit;
-               }
-               /* obtain bsscfg index for P2P discovery */
-               err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
-               if (err < 0) {
-                       brcmf_err("retrieving discover bsscfg index failed\n");
-                       brcmf_free_vif(p2p_vif);
-                       goto exit;
-               }
-               /* Verify that firmware uses same bssidx as driver !! */
-               if (p2p_ifp->bssidx != bssidx) {
-                       brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
-                                 bssidx, p2p_ifp->bssidx);
-                       brcmf_free_vif(p2p_vif);
-                       goto exit;
-               }
-
-               init_completion(&p2p->send_af_done);
-               INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
-               init_completion(&p2p->afx_hdl.act_frm_scan);
-               init_completion(&p2p->wait_next_af);
-       }
-exit:
-       return err;
-}
-
-
-/**
- * brcmf_p2p_detach() - detach P2P.
- *
- * @p2p: P2P specific data.
- */
-void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
-{
-       struct brcmf_cfg80211_vif *vif;
-
-       vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
-       if (vif != NULL) {
-               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
-               brcmf_p2p_deinit_discovery(p2p);
-               /* remove discovery interface */
-               brcmf_free_vif(vif);
-               p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
-       }
-       /* just set it all to zero */
-       memset(p2p, 0, sizeof(*p2p));
-}
-
 /**
  * brcmf_p2p_get_current_chanspec() - Get current operation channel.
  *
@@ -2238,6 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
 {
        cfg80211_unregister_wdev(&vif->wdev);
        p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+       brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
        brcmf_free_vif(vif);
 }
 
@@ -2364,6 +2267,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
                break;
 
        case NL80211_IFTYPE_P2P_DEVICE:
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
                brcmf_p2p_delete_p2pdev(p2p, vif);
                return 0;
        default:
@@ -2425,3 +2330,103 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
        clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
        mutex_unlock(&cfg->usr_sync);
 }
+
+/**
+ * brcmf_p2p_attach() - attach for P2P.
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ */
+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
+{
+       struct brcmf_if *pri_ifp;
+       struct brcmf_if *p2p_ifp;
+       struct brcmf_cfg80211_vif *p2p_vif;
+       struct brcmf_p2p_info *p2p;
+       struct brcmf_pub *drvr;
+       s32 bssidx;
+       s32 err = 0;
+
+       p2p = &cfg->p2p;
+       p2p->cfg = cfg;
+
+       drvr = cfg->pub;
+
+       pri_ifp = drvr->iflist[0];
+       p2p_ifp = drvr->iflist[1];
+
+       p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
+
+       if (p2p_ifp) {
+               p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
+                                         false);
+               if (IS_ERR(p2p_vif)) {
+                       brcmf_err("could not create discovery vif\n");
+                       err = -ENOMEM;
+                       goto exit;
+               }
+
+               p2p_vif->ifp = p2p_ifp;
+               p2p_ifp->vif = p2p_vif;
+               p2p_vif->wdev.netdev = p2p_ifp->ndev;
+               p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
+               SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
+
+               p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
+
+               brcmf_p2p_generate_bss_mac(p2p, NULL);
+               memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
+               brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+
+               /* Initialize P2P Discovery in the firmware */
+               err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
+               if (err < 0) {
+                       brcmf_err("set p2p_disc error\n");
+                       brcmf_free_vif(p2p_vif);
+                       goto exit;
+               }
+               /* obtain bsscfg index for P2P discovery */
+               err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
+               if (err < 0) {
+                       brcmf_err("retrieving discover bsscfg index failed\n");
+                       brcmf_free_vif(p2p_vif);
+                       goto exit;
+               }
+               /* Verify that firmware uses same bssidx as driver !! */
+               if (p2p_ifp->bssidx != bssidx) {
+                       brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
+                                 bssidx, p2p_ifp->bssidx);
+                       brcmf_free_vif(p2p_vif);
+                       goto exit;
+               }
+
+               init_completion(&p2p->send_af_done);
+               INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
+               init_completion(&p2p->afx_hdl.act_frm_scan);
+               init_completion(&p2p->wait_next_af);
+       }
+exit:
+       return err;
+}
+
+/**
+ * brcmf_p2p_detach() - detach P2P.
+ *
+ * @p2p: P2P specific data.
+ */
+void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
+{
+       struct brcmf_cfg80211_vif *vif;
+
+       vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+       if (vif != NULL) {
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
+               /* remove discovery interface */
+               rtnl_lock();
+               brcmf_p2p_delete_p2pdev(p2p, vif);
+               rtnl_unlock();
+       }
+       /* just set it all to zero */
+       memset(p2p, 0, sizeof(*p2p));
+}
+
index 37a2624d7bbaed4a79fb3dcf2d6a23f725f3ea97..3a98c4306d1d603c8aa4098510956cad4b0df542 100644 (file)
@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
 
 static int brcmf_pcie_buscoreprep(void *ctx)
 {
-       struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx;
-       int err;
-
-       err = brcmf_pcie_get_resource(devinfo);
-       if (err == 0) {
-               /* Set CC watchdog to reset all the cores on the chip to bring
-                * back dongle to a sane state.
-                */
-               brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
-                                                           watchdog), 4);
-               msleep(100);
-       }
-
-       return err;
+       return brcmf_pcie_get_resource(ctx);
 }
 
 
@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
                brcmf_pcie_intr_disable(devinfo);
 
        brcmf_detach(&pdev->dev);
+       brcmf_pcie_reset_device(devinfo);
 
        kfree(bus->bus_priv.pcie);
        kfree(bus->msgbuf->flowrings);
index bf7a8b1ad91485afa1c15fb9d1e38c5872ca3362..d36f5f3d931b55f1df10da3b30d87fdd9b931611 100644 (file)
@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
        struct brcmf_sdio *bus = sdiodev->bus;
 
        brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
+       if (sdiodev->state != BRCMF_SDIOD_DATA)
+               return -EIO;
 
        /* Add space for the header */
        skb_push(pkt, bus->tx_hdrlen);
@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
        int ret;
 
        brcmf_dbg(TRACE, "Enter\n");
+       if (sdiodev->state != BRCMF_SDIOD_DATA)
+               return -EIO;
 
        /* Send from dpc */
        bus->ctrl_frame_buf = msg;
@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
        struct brcmf_sdio *bus = sdiodev->bus;
 
        brcmf_dbg(TRACE, "Enter\n");
+       if (sdiodev->state != BRCMF_SDIOD_DATA)
+               return -EIO;
 
        /* Wait until control frame is available */
        timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);
index 9c9e1288644bb5ec586b7693f69e293cb3014855..7217da4f1543aed26d965ae7efed4da0f402765b 100644 (file)
@@ -34,56 +34,32 @@ static unsigned int ieee80211_get_hdrlen_from_buf(const u8 *data, unsigned len)
 
 static struct sk_buff *
 mt7601u_rx_skb_from_seg(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
-                       u8 *data, u32 seg_len)
+                       void *data, u32 seg_len, u32 truesize, struct page *p)
 {
        struct sk_buff *skb;
-       u32 true_len;
+       u32 true_len, hdr_len = 0, copy, frag;
 
-       if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD))
-               seg_len -= 2;
-
-       skb = alloc_skb(seg_len, GFP_ATOMIC);
-       if (!skb)
-               return NULL;
-
-       if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
-               int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
-
-               memcpy(skb_put(skb, hdr_len), data, hdr_len);
-               data += hdr_len + 2;
-               seg_len -= hdr_len;
-       }
-
-       memcpy(skb_put(skb, seg_len), data, seg_len);
-
-       true_len = mt76_mac_process_rx(dev, skb, skb->data, rxwi);
-       skb_trim(skb, true_len);
-
-       return skb;
-}
-
-static struct sk_buff *
-mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
-                             struct mt7601u_rxwi *rxwi, void *data,
-                             u32 seg_len, u32 truesize, struct page *p)
-{
-       unsigned int hdr_len = ieee80211_get_hdrlen_from_buf(data, seg_len);
-       unsigned int true_len, copy, frag;
-       struct sk_buff *skb;
-
-       skb = alloc_skb(128, GFP_ATOMIC);
+       skb = alloc_skb(p ? 128 : seg_len, GFP_ATOMIC);
        if (!skb)
                return NULL;
 
        true_len = mt76_mac_process_rx(dev, skb, data, rxwi);
+       if (!true_len || true_len > seg_len)
+               goto bad_frame;
+
+       hdr_len = ieee80211_get_hdrlen_from_buf(data, true_len);
+       if (!hdr_len)
+               goto bad_frame;
 
        if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_L2PAD)) {
                memcpy(skb_put(skb, hdr_len), data, hdr_len);
+
                data += hdr_len + 2;
                true_len -= hdr_len;
                hdr_len = 0;
        }
 
+       /* If not doing paged RX allocated skb will always have enough space */
        copy = (true_len <= skb_tailroom(skb)) ? true_len : hdr_len + 8;
        frag = true_len - copy;
 
@@ -97,10 +73,16 @@ mt7601u_rx_skb_from_seg_paged(struct mt7601u_dev *dev,
        }
 
        return skb;
+
+bad_frame:
+       dev_err_ratelimited(dev->dev, "Error: incorrect frame len:%u hdr:%u\n",
+                           true_len, hdr_len);
+       dev_kfree_skb(skb);
+       return NULL;
 }
 
 static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
-                                  u32 seg_len, struct page *p, bool paged)
+                                  u32 seg_len, struct page *p)
 {
        struct sk_buff *skb;
        struct mt7601u_rxwi *rxwi;
@@ -126,11 +108,7 @@ static void mt7601u_rx_process_seg(struct mt7601u_dev *dev, u8 *data,
 
        trace_mt_rx(dev, rxwi, fce_info);
 
-       if (paged)
-               skb = mt7601u_rx_skb_from_seg_paged(dev, rxwi, data, seg_len,
-                                                   truesize, p);
-       else
-               skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len);
+       skb = mt7601u_rx_skb_from_seg(dev, rxwi, data, seg_len, truesize, p);
        if (!skb)
                return;
 
@@ -158,23 +136,17 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
        u32 seg_len, data_len = e->urb->actual_length;
        u8 *data = page_address(e->p);
        struct page *new_p = NULL;
-       bool paged = true;
        int cnt = 0;
 
        if (!test_bit(MT7601U_STATE_INITIALIZED, &dev->state))
                return;
 
        /* Copy if there is very little data in the buffer. */
-       if (data_len < 512) {
-               paged = false;
-       } else {
+       if (data_len > 512)
                new_p = dev_alloc_pages(MT_RX_ORDER);
-               if (!new_p)
-                       paged = false;
-       }
 
        while ((seg_len = mt7601u_rx_next_seg_len(data, data_len))) {
-               mt7601u_rx_process_seg(dev, data, seg_len, e->p, paged);
+               mt7601u_rx_process_seg(dev, data, seg_len, new_p ? e->p : NULL);
 
                data_len -= seg_len;
                data += seg_len;
@@ -182,9 +154,9 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e)
        }
 
        if (cnt > 1)
-               trace_mt_rx_dma_aggr(dev, cnt, paged);
+               trace_mt_rx_dma_aggr(dev, cnt, !!new_p);
 
-       if (paged) {
+       if (new_p) {
                /* we have one extra ref from the allocator */
                __free_pages(e->p, MT_RX_ORDER);
 
index ce3837f270f086ac2ace44a3b887cbf9e12fa32d..8d8ee0344f7baa9e1315799d2b211cc28cdf6e3f 100644 (file)
@@ -277,6 +277,10 @@ mt7601u_extra_power_over_mac(struct mt7601u_dev *dev)
 static void
 mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value)
 {
+       /* Invalid? Note: vendor driver does not handle this */
+       if (value == 0xff)
+               return;
+
        rate->raw = s6_validate(value);
        rate->bw20 = s6_to_int(value);
        /* Note: vendor driver does cap the value to s6 right away */
index ca1ea2e55ff4f0f3339058b1bb8c76088724d7db..df3dd56199a7ec8a43202c8d40b8d919df846006 100644 (file)
@@ -427,6 +427,9 @@ err:
 
 void mt7601u_cleanup(struct mt7601u_dev *dev)
 {
+       if (!test_and_clear_bit(MT7601U_STATE_INITIALIZED, &dev->state))
+               return;
+
        mt7601u_stop_hardware(dev);
        mt7601u_dma_cleanup(dev);
        mt7601u_mcu_cmd_deinit(dev);
index c161bcc6a7faa9e6bfa713247ca5e5b3c2f68575..7514bce1ac91dfa61bfe82e822c92eac57f1a129 100644 (file)
@@ -450,10 +450,14 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
 {
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct mt7601u_rxwi *rxwi = rxi;
-       u32 ctl = le32_to_cpu(rxwi->ctl);
+       u32 len, ctl = le32_to_cpu(rxwi->ctl);
        u16 rate = le16_to_cpu(rxwi->rate);
        int rssi;
 
+       len = MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+       if (len < 10)
+               return 0;
+
        if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
                status->flag |= RX_FLAG_DECRYPTED;
                status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -474,7 +478,7 @@ u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
                dev->avg_rssi = (dev->avg_rssi * 15) / 16 + (rssi << 8);
        spin_unlock_bh(&dev->con_mon_lock);
 
-       return MT76_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+       return len;
 }
 
 static enum mt76_cipher_type
index ced82abb414ffa8725416e7925ed6d04306b45fd..169384b48b27d785cb43cb3199dedc89b736db84 100644 (file)
@@ -119,6 +119,7 @@ mt76_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,
 
        dev->rxfilter &= ~MT_RX_FILTR_CFG_OTHER_BSS;
 
+       MT76_FILTER(OTHER_BSS, MT_RX_FILTR_CFG_PROMISC);
        MT76_FILTER(FCSFAIL, MT_RX_FILTR_CFG_CRC_ERR);
        MT76_FILTER(PLCPFAIL, MT_RX_FILTR_CFG_PHY_ERR);
        MT76_FILTER(CONTROL, MT_RX_FILTR_CFG_ACK |
index 99e2b3997bfa0dc7dcf8fcbeb67ddb1a83b446b3..54dba400186511bf2842972f631bd2dde51c5a46 100644 (file)
@@ -338,8 +338,15 @@ static int mt7601u_suspend(struct usb_interface *usb_intf, pm_message_t state)
 static int mt7601u_resume(struct usb_interface *usb_intf)
 {
        struct mt7601u_dev *dev = usb_get_intfdata(usb_intf);
+       int ret;
+
+       ret = mt7601u_init_hardware(dev);
+       if (ret)
+               return ret;
+
+       set_bit(MT7601U_STATE_INITIALIZED, &dev->state);
 
-       return mt7601u_init_hardware(dev);
+       return 0;
 }
 
 MODULE_DEVICE_TABLE(usb, mt7601u_device_table);
index 65cd461c88db5505a99d113a9650d26fd84ccb96..71a1b580796f12723e8b6725e938993acfbd1e85 100644 (file)
@@ -161,19 +161,38 @@ int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv,
        cr_req->chan_desc.chan_width = radar_params->chandef->width;
        cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms);
 
-       mwifiex_dbg(priv->adapter, MSG,
-                   "11h: issuing DFS Radar check for channel=%d\n",
-                   radar_params->chandef->chan->hw_value);
+       if (radar_params->cac_time_ms)
+               mwifiex_dbg(priv->adapter, MSG,
+                           "11h: issuing DFS Radar check for channel=%d\n",
+                           radar_params->chandef->chan->hw_value);
+       else
+               mwifiex_dbg(priv->adapter, MSG, "cancelling CAC\n");
 
        return 0;
 }
 
+int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
+                                struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_radar_params radar_params;
+
+       memset(&radar_params, 0, sizeof(struct mwifiex_radar_params));
+       radar_params.chandef = chandef;
+       radar_params.cac_time_ms = 0;
+
+       return mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST,
+                               HostCmd_ACT_GEN_SET, 0, &radar_params, true);
+}
+
 /* This function is to abort ongoing CAC upon stopping AP operations
  * or during unload.
  */
 void mwifiex_abort_cac(struct mwifiex_private *priv)
 {
        if (priv->wdev.cac_started) {
+               if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "failed to stop CAC in FW\n");
                mwifiex_dbg(priv->adapter, MSG,
                            "Aborting delayed work for CAC.\n");
                cancel_delayed_work_sync(&priv->dfs_cac_work);
@@ -245,6 +264,9 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
        if (le32_to_cpu(rdr_event->passed)) {
                mwifiex_dbg(priv->adapter, MSG,
                            "radar detected; indicating kernel\n");
+               if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef))
+                       mwifiex_dbg(priv->adapter, ERROR,
+                                   "Failed to stop CAC in FW\n");
                cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
                                     GFP_KERNEL);
                mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
@@ -252,7 +274,7 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
                mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n",
                            rdr_event->det_type);
        } else {
-               mwifiex_dbg(priv->adapter, ERROR,
+               mwifiex_dbg(priv->adapter, MSG,
                            "false radar detection event!\n");
        }
 
@@ -283,7 +305,7 @@ void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work)
                return;
        }
 
-       mwifiex_uap_set_channel(bss_cfg, priv->dfs_chandef);
+       mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef);
 
        if (mwifiex_config_start_uap(priv, bss_cfg)) {
                mwifiex_dbg(priv->adapter, ERROR,
index 8422986cd7a9137c171f706b123120a6e279d524..c174e79e6df2b656757b37e49d77e9bc446aa093 100644 (file)
@@ -156,7 +156,7 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
 int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
                              struct host_cmd_ds_command *resp)
 {
-       int tid;
+       int tid, tid_down;
        struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp;
        struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl;
        struct mwifiex_ra_list_tbl *ra_list;
@@ -167,7 +167,9 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
 
        tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK)
               >> BLOCKACKPARAM_TID_POS;
-       ra_list = mwifiex_wmm_get_ralist_node(priv, tid, add_ba_rsp->
+
+       tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+       ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp->
                peer_mac_addr);
        if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) {
                if (ra_list) {
@@ -530,13 +532,16 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
        struct mwifiex_tx_ba_stream_tbl *new_node;
        struct mwifiex_ra_list_tbl *ra_list;
        unsigned long flags;
+       int tid_down;
 
        if (!mwifiex_get_ba_tbl(priv, tid, ra)) {
                new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl),
                                   GFP_ATOMIC);
                if (!new_node)
                        return;
-               ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra);
+
+               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra);
                if (ra_list) {
                        ra_list->ba_status = ba_status;
                        ra_list->amsdu_in_ampdu = false;
@@ -642,6 +647,30 @@ int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac,
        return ret;
 }
 
+/*
+ * This function sends delba to specific tid
+ */
+void mwifiex_11n_delba(struct mwifiex_private *priv, int tid)
+{
+       struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
+
+       if (list_empty(&priv->rx_reorder_tbl_ptr)) {
+               dev_dbg(priv->adapter->dev,
+                       "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n");
+               return;
+       }
+
+       list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) {
+               if (rx_reor_tbl_ptr->tid == tid) {
+                       dev_dbg(priv->adapter->dev,
+                               "Send delba to tid=%d, %pM\n",
+                               tid, rx_reor_tbl_ptr->ta);
+                       mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0);
+                       return;
+               }
+       }
+}
+
 /*
  * This function handles the command response of a delete BA request.
  */
@@ -814,3 +843,72 @@ u8 mwifiex_get_sec_chan_offset(int chan)
 
        return sec_offset;
 }
+
+/* This function will send DELBA to entries in the priv's
+ * Tx BA stream table
+ */
+static void
+mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr;
+
+       if (list_empty(&priv->tx_ba_stream_tbl_ptr))
+               return;
+
+       list_for_each_entry(tx_ba_stream_tbl_ptr,
+                           &priv->tx_ba_stream_tbl_ptr, list) {
+               if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) {
+                       if (tid == tx_ba_stream_tbl_ptr->tid) {
+                               dev_dbg(adapter->dev,
+                                       "Tx:Send delba to tid=%d, %pM\n", tid,
+                                       tx_ba_stream_tbl_ptr->ra);
+                               mwifiex_send_delba(priv,
+                                                  tx_ba_stream_tbl_ptr->tid,
+                                                  tx_ba_stream_tbl_ptr->ra, 1);
+                               return;
+                       }
+               }
+       }
+}
+
+/* This function updates all the tx_win_size
+ */
+void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter)
+{
+       u8 i;
+       u32 tx_win_size;
+       struct mwifiex_private *priv;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i])
+                       continue;
+               priv = adapter->priv[i];
+               tx_win_size = priv->add_ba_param.tx_win_size;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_STA_AMPDU_DEF_TXWINSIZE;
+
+               if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                       priv->add_ba_param.tx_win_size =
+                               MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE;
+
+               if (adapter->coex_win_size) {
+                       if (adapter->coex_tx_win_size)
+                               priv->add_ba_param.tx_win_size =
+                                       adapter->coex_tx_win_size;
+               }
+
+               if (tx_win_size != priv->add_ba_param.tx_win_size) {
+                       if (!priv->media_connected)
+                               continue;
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               mwifiex_send_delba_txbastream_tbl(priv, i);
+               }
+       }
+}
index 39d7a957674c2b6cd83d3593e7a10a08745ad56d..2906cd543532aa514de2e2c6ed14bd19167fbdc0 100644 (file)
@@ -663,6 +663,7 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
        struct mwifiex_ra_list_tbl *ra_list;
        u8 cleanup_rx_reorder_tbl;
        unsigned long flags;
+       int tid_down;
 
        if (type == TYPE_DELBA_RECEIVE)
                cleanup_rx_reorder_tbl = (initiator) ? true : false;
@@ -688,7 +689,9 @@ mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac,
                                    "event: TID, RA not found in table\n");
                        return;
                }
-               ra_list = mwifiex_wmm_get_ralist_node(priv, tid, peer_mac);
+
+               tid_down = mwifiex_wmm_downgrade_tid(priv, tid);
+               ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac);
                if (ra_list) {
                        ra_list->amsdu_in_ampdu = false;
                        ra_list->ba_status = BA_SETUP_NONE;
@@ -825,3 +828,83 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
 
        return;
 }
+
+/* This function update all the rx_win_size based on coex flag
+ */
+static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter,
+                                          bool coex_flag)
+{
+       u8 i;
+       u32 rx_win_size;
+       struct mwifiex_private *priv;
+
+       dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag);
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (!adapter->priv[i])
+                       continue;
+               priv = adapter->priv[i];
+               rx_win_size = priv->add_ba_param.rx_win_size;
+               if (coex_flag) {
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE;
+               } else {
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_STA)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_STA_AMPDU_DEF_RXWINSIZE;
+                       if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP)
+                               priv->add_ba_param.rx_win_size =
+                                       MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE;
+               }
+
+               if (adapter->coex_win_size && adapter->coex_rx_win_size)
+                       priv->add_ba_param.rx_win_size =
+                                       adapter->coex_rx_win_size;
+
+               if (rx_win_size != priv->add_ba_param.rx_win_size) {
+                       if (!priv->media_connected)
+                               continue;
+                       for (i = 0; i < MAX_NUM_TID; i++)
+                               mwifiex_11n_delba(priv, i);
+               }
+       }
+}
+
+/* This function check coex for RX BA
+ */
+void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter)
+{
+       u8 i;
+       struct mwifiex_private *priv;
+       u8 count = 0;
+
+       for (i = 0; i < adapter->priv_num; i++) {
+               if (adapter->priv[i]) {
+                       priv = adapter->priv[i];
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
+                               if (priv->media_connected)
+                                       count++;
+                       }
+                       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+                               if (priv->bss_started)
+                                       count++;
+                       }
+               }
+               if (count >= MWIFIEX_BSS_COEX_COUNT)
+                       break;
+       }
+       if (count >= MWIFIEX_BSS_COEX_COUNT)
+               mwifiex_update_ampdu_rxwinsize(adapter, true);
+       else
+               mwifiex_update_ampdu_rxwinsize(adapter, false);
+}
index 4eecedadefbff64c7a2656444809c21470ab73e8..b15e4c7acbecd2ed44b1e76360464ef23f3fd9f3 100644 (file)
@@ -67,6 +67,22 @@ u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
        }
 }
 
+/* This function maps IEEE HT secondary channel type to NL80211 channel type
+ */
+u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset)
+{
+       switch (second_chan_offset) {
+       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+               return NL80211_CHAN_HT20;
+       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               return NL80211_CHAN_HT40PLUS;
+       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+               return NL80211_CHAN_HT40MINUS;
+       default:
+               return NL80211_CHAN_HT20;
+       }
+}
+
 /*
  * This function checks whether WEP is set.
  */
@@ -1213,6 +1229,7 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo,
  */
 static int
 mwifiex_dump_station_info(struct mwifiex_private *priv,
+                         struct mwifiex_sta_node *node,
                          struct station_info *sinfo)
 {
        u32 rate;
@@ -1222,6 +1239,30 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
                        BIT(NL80211_STA_INFO_TX_BITRATE) |
                        BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG);
 
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               if (!node)
+                       return -ENOENT;
+
+               sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) |
+                               BIT(NL80211_STA_INFO_TX_FAILED);
+               sinfo->inactive_time =
+                       jiffies_to_msecs(jiffies - node->stats.last_rx);
+
+               sinfo->signal = node->stats.rssi;
+               sinfo->signal_avg = node->stats.rssi;
+               sinfo->rx_bytes = node->stats.rx_bytes;
+               sinfo->tx_bytes = node->stats.tx_bytes;
+               sinfo->rx_packets = node->stats.rx_packets;
+               sinfo->tx_packets = node->stats.tx_packets;
+               sinfo->tx_failed = node->stats.tx_failed;
+
+               mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo,
+                                    &sinfo->txrate);
+               sinfo->txrate.legacy = node->stats.last_tx_rate * 5;
+
+               return 0;
+       }
+
        /* Get signal information from the firmware */
        if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO,
                             HostCmd_ACT_GEN_GET, 0, NULL, true)) {
@@ -1288,7 +1329,7 @@ mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
        if (memcmp(mac, priv->cfg_bssid, ETH_ALEN))
                return -ENOENT;
 
-       return mwifiex_dump_station_info(priv, sinfo);
+       return mwifiex_dump_station_info(priv, NULL, sinfo);
 }
 
 /*
@@ -1299,13 +1340,29 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
                              int idx, u8 *mac, struct station_info *sinfo)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
+       static struct mwifiex_sta_node *node;
 
-       if (!priv->media_connected || idx)
-               return -ENOENT;
+       if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
+           priv->media_connected && idx == 0) {
+               ether_addr_copy(mac, priv->cfg_bssid);
+               return mwifiex_dump_station_info(priv, NULL, sinfo);
+       } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST,
+                                HostCmd_ACT_GEN_GET, 0, NULL, true);
+
+               if (node && (&node->list == &priv->sta_list)) {
+                       node = NULL;
+                       return -ENOENT;
+               }
 
-       memcpy(mac, priv->cfg_bssid, ETH_ALEN);
+               node = list_prepare_entry(node, &priv->sta_list, list);
+               list_for_each_entry_continue(node, &priv->sta_list, list) {
+                       ether_addr_copy(mac, node->mac_addr);
+                       return mwifiex_dump_station_info(priv, node, sinfo);
+               }
+       }
 
-       return mwifiex_dump_station_info(priv, sinfo);
+       return -ENOENT;
 }
 
 static int
@@ -1725,6 +1782,13 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
                return -1;
        }
 
+       if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "Failed to reset BSS\n");
+               return -1;
+       }
+
        return 0;
 }
 
@@ -1778,7 +1842,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
                return -EINVAL;
        }
 
-       mwifiex_uap_set_channel(bss_cfg, params->chandef);
+       mwifiex_uap_set_channel(priv, bss_cfg, params->chandef);
        mwifiex_set_uap_rates(bss_cfg, params);
 
        if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
@@ -1803,6 +1867,9 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
 
        mwifiex_set_wmm_params(priv, bss_cfg, params);
 
+       if (mwifiex_is_11h_active(priv))
+               mwifiex_set_tpc_params(priv, bss_cfg, params);
+
        if (mwifiex_is_11h_active(priv) &&
            !cfg80211_chandef_dfs_required(wiphy, &params->chandef,
                                           priv->bss_mode)) {
@@ -1813,7 +1880,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
                                    "Failed to disable 11h extensions!!");
                        return -1;
                }
-               priv->state_11h.is_11h_active = true;
+               priv->state_11h.is_11h_active = false;
        }
 
        if (mwifiex_config_start_uap(priv, bss_cfg)) {
@@ -2518,7 +2585,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
                priv->bss_priority = 0;
                priv->bss_role = MWIFIEX_BSS_ROLE_STA;
-               priv->bss_num = 0;
+               priv->bss_num = adapter->curr_iface_comb.sta_intf;
 
                break;
        case NL80211_IFTYPE_AP:
@@ -2544,7 +2611,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                priv->bss_priority = 0;
                priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
                priv->bss_started = 0;
-               priv->bss_num = 0;
+               priv->bss_num = adapter->curr_iface_comb.uap_intf;
                priv->bss_mode = type;
 
                break;
@@ -2580,7 +2647,7 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
                priv->bss_role = MWIFIEX_BSS_ROLE_STA;
                priv->bss_started = 0;
-               priv->bss_num = 0;
+               priv->bss_num = adapter->curr_iface_comb.p2p_intf;
 
                if (mwifiex_cfg80211_init_p2p_client(priv)) {
                        memset(&priv->wdev, 0, sizeof(priv->wdev));
@@ -3366,6 +3433,45 @@ mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        return 0;
 }
 
+static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy,
+                                       struct wireless_dev *wdev,
+                                       struct cfg80211_chan_def *chandef)
+{
+       struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
+       struct mwifiex_bssdescriptor *curr_bss;
+       struct ieee80211_channel *chan;
+       u8 second_chan_offset;
+       enum nl80211_channel_type chan_type;
+       enum ieee80211_band band;
+       int freq;
+       int ret = -ENODATA;
+
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP &&
+           cfg80211_chandef_valid(&priv->bss_chandef)) {
+               *chandef = priv->bss_chandef;
+               ret = 0;
+       } else if (priv->media_connected) {
+               curr_bss = &priv->curr_bss_params.bss_descriptor;
+               band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
+               freq = ieee80211_channel_to_frequency(curr_bss->channel, band);
+               chan = ieee80211_get_channel(wiphy, freq);
+
+               if (curr_bss->bcn_ht_oper) {
+                       second_chan_offset = curr_bss->bcn_ht_oper->ht_param &
+                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
+                       chan_type = mwifiex_sec_chan_offset_to_chan_type
+                                                       (second_chan_offset);
+                       cfg80211_chandef_create(chandef, chan, chan_type);
+               } else {
+                       cfg80211_chandef_create(chandef, chan,
+                                               NL80211_CHAN_NO_HT);
+               }
+               ret = 0;
+       }
+
+       return ret;
+}
+
 static int
 mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy,
                                       struct net_device *dev,
@@ -3471,6 +3577,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = {
        .tdls_oper = mwifiex_cfg80211_tdls_oper,
        .add_station = mwifiex_cfg80211_add_station,
        .change_station = mwifiex_cfg80211_change_station,
+       .get_channel = mwifiex_cfg80211_get_channel,
        .start_radar_detection = mwifiex_cfg80211_start_radar_detection,
        .channel_switch = mwifiex_cfg80211_channel_switch,
 };
@@ -3578,7 +3685,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
                        WIPHY_FLAG_AP_UAPSD |
                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
-                       WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+                       WIPHY_FLAG_HAS_CHANNEL_SWITCH |
+                       WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info))
                wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS |
index a1de83fd1dbe4a0c2f535844ef6978fd256d5cea..207da40500f4309fcdd0405e99365f4aa274f502 100644 (file)
@@ -469,10 +469,11 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
                memset(rx_info, 0, sizeof(*rx_info));
                rx_info->bss_num = priv->bss_num;
                rx_info->bss_type = priv->bss_type;
+               mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:",
+                                skb->data, skb->len);
        }
 
        mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause);
-       mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", skb->data, skb->len);
 
        if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
                ret = mwifiex_process_uap_event(priv);
@@ -574,6 +575,8 @@ int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no,
                case HostCmd_CMD_UAP_BSS_START:
                case HostCmd_CMD_UAP_BSS_STOP:
                case HostCmd_CMD_UAP_STA_DEAUTH:
+               case HOST_CMD_APCMD_SYS_RESET:
+               case HOST_CMD_APCMD_STA_LIST:
                        ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action,
                                                      cmd_oid, data_buf,
                                                      cmd_ptr);
index 38f24e0427d28b02a979eaec1ce066e648829048..51e344789ba214bbbd5cfe7dc29a0a6ac1244527 100644 (file)
@@ -29,7 +29,7 @@
 #include <uapi/linux/if_arp.h>
 #include <net/mac80211.h>
 
-
+#define MWIFIEX_BSS_COEX_COUNT      2
 #define MWIFIEX_MAX_BSS_NUM         (3)
 
 #define MWIFIEX_DMA_ALIGN_SZ       64
 
 #define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE        64
 #define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE        64
+#define MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE   16
+
 #define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE        32
+
+#define MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE   16
+
 #define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE        16
 #define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE   64
 #define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE   64
index c404390cb0fa42b8d7778fcf23c121600ee48811..cd09051710e6cee82c624e6960f4c8accd452338 100644 (file)
@@ -128,6 +128,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 
 #define TLV_TYPE_UAP_SSID                      0x0000
 #define TLV_TYPE_UAP_RATES                     0x0001
+#define TLV_TYPE_PWR_CONSTRAINT                        0x0020
 
 #define PROPRIETARY_TLV_BASE_ID                 0x0100
 #define TLV_TYPE_KEY_MATERIAL       (PROPRIETARY_TLV_BASE_ID + 0)
@@ -174,6 +175,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define TLV_TYPE_SCAN_CHANNEL_GAP   (PROPRIETARY_TLV_BASE_ID + 197)
 #define TLV_TYPE_API_REV            (PROPRIETARY_TLV_BASE_ID + 199)
 #define TLV_TYPE_CHANNEL_STATS      (PROPRIETARY_TLV_BASE_ID + 198)
+#define TLV_BTCOEX_WL_AGGR_WINSIZE  (PROPRIETARY_TLV_BASE_ID + 202)
+#define TLV_BTCOEX_WL_SCANTIME      (PROPRIETARY_TLV_BASE_ID + 203)
 
 #define MWIFIEX_TX_DATA_BUF_SIZE_2K        2048
 
@@ -330,9 +333,11 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
 #define HostCmd_CMD_RSSI_INFO                         0x00a4
 #define HostCmd_CMD_FUNC_INIT                         0x00a9
 #define HostCmd_CMD_FUNC_SHUTDOWN                     0x00aa
+#define HOST_CMD_APCMD_SYS_RESET                      0x00af
 #define HostCmd_CMD_UAP_SYS_CONFIG                    0x00b0
 #define HostCmd_CMD_UAP_BSS_START                     0x00b1
 #define HostCmd_CMD_UAP_BSS_STOP                      0x00b2
+#define HOST_CMD_APCMD_STA_LIST                       0x00b3
 #define HostCmd_CMD_UAP_STA_DEAUTH                    0x00b5
 #define HostCmd_CMD_11N_CFG                           0x00cd
 #define HostCmd_CMD_11N_ADDBA_REQ                     0x00ce
@@ -419,8 +424,12 @@ enum P2P_MODES {
 #define HS_CFG_COND_MAC_EVENT          0x00000004
 #define HS_CFG_COND_MULTICAST_DATA     0x00000008
 
-#define MWIFIEX_TIMEOUT_FOR_AP_RESP            0xfffc
-#define MWIFIEX_STATUS_CODE_AUTH_TIMEOUT       2
+#define CONNECT_ERR_AUTH_ERR_STA_FAILURE       0xFFFB
+#define CONNECT_ERR_ASSOC_ERR_TIMEOUT          0xFFFC
+#define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED     0xFFFD
+#define CONNECT_ERR_AUTH_MSG_UNHANDLED         0xFFFE
+#define CONNECT_ERR_STA_FAILURE                        0xFFFF
+
 
 #define CMD_F_HOSTCMD           (1 << 0)
 #define CMD_F_CANCELED          (1 << 1)
@@ -503,6 +512,7 @@ enum P2P_MODES {
 #define EVENT_EXT_SCAN_REPORT           0x00000058
 #define EVENT_REMAIN_ON_CHAN_EXPIRED    0x0000005f
 #define EVENT_TX_STATUS_REPORT         0x00000074
+#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076
 
 #define EVENT_ID_MASK                   0xffff
 #define BSS_NUM_MASK                    0xf
@@ -627,7 +637,12 @@ struct uap_rxpd {
        __le16 rx_pkt_type;
        __le16 seq_num;
        u8 priority;
-       u8 reserved1;
+       u8 rx_rate;
+       s8 snr;
+       s8 nf;
+       u8 ht_info;
+       u8 reserved[3];
+       u8 flags;
 };
 
 struct mwifiex_fw_chan_stats {
@@ -1151,6 +1166,13 @@ enum SNMP_MIB_INDEX {
        DOT11H_I = 10,
 };
 
+enum mwifiex_assocmd_failurepoint {
+       MWIFIEX_ASSOC_CMD_SUCCESS = 0,
+       MWIFIEX_ASSOC_CMD_FAILURE_ASSOC,
+       MWIFIEX_ASSOC_CMD_FAILURE_AUTH,
+       MWIFIEX_ASSOC_CMD_FAILURE_JOIN
+};
+
 #define MAX_SNMP_BUF_SIZE   128
 
 struct host_cmd_ds_802_11_snmp_mib {
@@ -1448,6 +1470,18 @@ struct host_cmd_ds_sta_deauth {
        __le16 reason;
 } __packed;
 
+struct mwifiex_ie_types_sta_info {
+       struct mwifiex_ie_types_header header;
+       u8 mac[ETH_ALEN];
+       u8 power_mfg_status;
+       s8 rssi;
+};
+
+struct host_cmd_ds_sta_list {
+       u16 sta_count;
+       u8 tlv[0];
+} __packed;
+
 struct mwifiex_ie_types_pwr_capability {
        struct mwifiex_ie_types_header header;
        s8 min_pwr;
@@ -1750,6 +1784,27 @@ struct host_cmd_tlv_ageout_timer {
        __le32 sta_ao_timer;
 } __packed;
 
+struct host_cmd_tlv_power_constraint {
+       struct mwifiex_ie_types_header header;
+       u8 constraint;
+} __packed;
+
+struct mwifiex_ie_types_btcoex_scan_time {
+       struct mwifiex_ie_types_header header;
+       u8 coex_scan;
+       u8 reserved;
+       u16 min_scan_time;
+       u16 max_scan_time;
+} __packed;
+
+struct mwifiex_ie_types_btcoex_aggr_win_size {
+       struct mwifiex_ie_types_header header;
+       u8 coex_win_size;
+       u8 tx_win_size;
+       u8 rx_win_size;
+       u8 reserved;
+} __packed;
+
 struct host_cmd_ds_version_ext {
        u8 version_str_sel;
        char version_str[128];
@@ -1977,6 +2032,7 @@ struct host_cmd_ds_command {
                struct host_cmd_ds_802_11_subsc_evt subsc_evt;
                struct host_cmd_ds_sys_config uap_sys_config;
                struct host_cmd_ds_sta_deauth sta_deauth;
+               struct host_cmd_ds_sta_list sta_list;
                struct host_cmd_11ac_vht_cfg vht_cfg;
                struct host_cmd_ds_coalesce_cfg coalesce_cfg;
                struct host_cmd_ds_tdls_oper tdls_oper;
index f3b6ed249403909deaa228b57e7f414c478759a0..0ba8945094139c5e02374a11034e66777186c074 100644 (file)
@@ -320,63 +320,81 @@ done:
 /* This function parses  head and tail IEs, from cfg80211_beacon_data and sets
  * these IE to FW.
  */
-static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
-                                        struct cfg80211_beacon_data *info)
+static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
+                                     struct cfg80211_beacon_data *info)
 {
        struct mwifiex_ie *gen_ie;
-       struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
-       struct ieee_types_header *chsw_ie = NULL;
+       struct ieee_types_header *hdr;
+       struct ieee80211_vendor_ie *vendorhdr;
        u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
-       const u8 *vendor_ie;
+       int left_len, parsed_len = 0;
+
+       if (!info->tail || !info->tail_len)
+               return 0;
 
        gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
        if (!gen_ie)
                return -ENOMEM;
-       gen_ie->ie_index = cpu_to_le16(gen_idx);
-       gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
-                                               MGMT_MASK_PROBE_RESP |
-                                               MGMT_MASK_ASSOC_RESP);
 
-       if (info->tail && info->tail_len) {
-               rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
-                                                 info->tail, info->tail_len);
-               if (rsn_ie) {
-                       memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2);
-                       ie_len = rsn_ie->len + 2;
-                       gen_ie->ie_length = cpu_to_le16(ie_len);
+       left_len = info->tail_len;
+
+       /* Many IEs are generated in FW by parsing bss configuration.
+        * Let's not add them here; else we may end up duplicating these IEs
+        */
+       while (left_len > sizeof(struct ieee_types_header)) {
+               hdr = (void *)(info->tail + parsed_len);
+               switch (hdr->element_id) {
+               case WLAN_EID_SSID:
+               case WLAN_EID_SUPP_RATES:
+               case WLAN_EID_COUNTRY:
+               case WLAN_EID_PWR_CONSTRAINT:
+               case WLAN_EID_EXT_SUPP_RATES:
+               case WLAN_EID_HT_CAPABILITY:
+               case WLAN_EID_HT_OPERATION:
+               case WLAN_EID_VHT_CAPABILITY:
+               case WLAN_EID_VHT_OPERATION:
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       break;
+               default:
+                       memcpy(gen_ie->ie_buffer + ie_len, hdr,
+                              hdr->len + sizeof(struct ieee_types_header));
+                       ie_len += hdr->len + sizeof(struct ieee_types_header);
+                       break;
                }
+               left_len -= hdr->len + sizeof(struct ieee_types_header);
+               parsed_len += hdr->len + sizeof(struct ieee_types_header);
+       }
 
-               vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+       /* parse only WPA vendor IE from tail, WMM IE is configured by
+        * bss_config command
+        */
+       vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
                                                    WLAN_OUI_TYPE_MICROSOFT_WPA,
-                                                   info->tail,
-                                                   info->tail_len);
-               if (vendor_ie) {
-                       wpa_ie = (struct ieee_types_header *)vendor_ie;
-                       memcpy(gen_ie->ie_buffer + ie_len,
-                              wpa_ie, wpa_ie->len + 2);
-                       ie_len += wpa_ie->len + 2;
-                       gen_ie->ie_length = cpu_to_le16(ie_len);
-               }
+                                                   info->tail, info->tail_len);
+       if (vendorhdr) {
+               memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
+                      vendorhdr->len + sizeof(struct ieee_types_header));
+               ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
+       }
 
-               chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
-                                                  info->tail, info->tail_len);
-               if (chsw_ie) {
-                       memcpy(gen_ie->ie_buffer + ie_len,
-                              chsw_ie, chsw_ie->len + 2);
-                       ie_len += chsw_ie->len + 2;
-                       gen_ie->ie_length = cpu_to_le16(ie_len);
-               }
+       if (!ie_len) {
+               kfree(gen_ie);
+               return 0;
        }
 
-       if (rsn_ie || wpa_ie || chsw_ie) {
-               if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL,
-                                                NULL, NULL, NULL)) {
-                       kfree(gen_ie);
-                       return -1;
-               }
-               priv->gen_idx = gen_idx;
+       gen_ie->ie_index = cpu_to_le16(gen_idx);
+       gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
+                                               MGMT_MASK_PROBE_RESP |
+                                               MGMT_MASK_ASSOC_RESP);
+       gen_ie->ie_length = cpu_to_le16(ie_len);
+
+       if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
+                                        NULL, NULL)) {
+               kfree(gen_ie);
+               return -1;
        }
 
+       priv->gen_idx = gen_idx;
        kfree(gen_ie);
        return 0;
 }
@@ -390,7 +408,7 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
 {
        int ret;
 
-       ret = mwifiex_uap_set_head_tail_ies(priv, info);
+       ret = mwifiex_uap_parse_tail_ies(priv, info);
                return ret;
 
        return mwifiex_set_mgmt_beacon_data_ies(priv, info);
index 6f11a25a6b49d86498303f7a4647053eb8c22123..4f0174c649461ed3ac219419cb676921f31a66e6 100644 (file)
@@ -113,6 +113,7 @@ struct mwifiex_uap_bss_param {
        u32 sta_ao_timer;
        u32 ps_sta_ao_timer;
        u8 qos_info;
+       u8 power_constraint;
        struct mwifiex_types_wmm_info wmm_info;
 };
 
index cce8e39aa45e456e66dad6d4f762f07c96b9c9d2..56b024a6aaa58d2b89ca25692c37163367eda597 100644 (file)
@@ -556,6 +556,23 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
        return 0;
 }
 
+static const char *assoc_failure_reason_to_str(u16 cap_info)
+{
+       switch (cap_info) {
+       case CONNECT_ERR_AUTH_ERR_STA_FAILURE:
+               return "CONNECT_ERR_AUTH_ERR_STA_FAILURE";
+       case CONNECT_ERR_AUTH_MSG_UNHANDLED:
+               return "CONNECT_ERR_AUTH_MSG_UNHANDLED";
+       case CONNECT_ERR_ASSOC_ERR_TIMEOUT:
+               return "CONNECT_ERR_ASSOC_ERR_TIMEOUT";
+       case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED:
+               return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED";
+       case CONNECT_ERR_STA_FAILURE:
+               return "CONNECT_ERR_STA_FAILURE";
+       }
+
+       return "Unknown connect failure";
+}
 /*
  * Association firmware command response handler
  *
@@ -656,11 +673,18 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
                            status_code, cap_info,
                            le16_to_cpu(assoc_rsp->a_id));
 
-               if (cap_info == MWIFIEX_TIMEOUT_FOR_AP_RESP) {
-                       if (status_code == MWIFIEX_STATUS_CODE_AUTH_TIMEOUT)
+               mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n",
+                           assoc_failure_reason_to_str(cap_info));
+               if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) {
+                       if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) {
                                ret = WLAN_STATUS_AUTH_TIMEOUT;
-                       else
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "ASSOC_RESP: AUTH timeout\n");
+                       } else {
                                ret = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               mwifiex_dbg(priv->adapter, ERROR,
+                                           "ASSOC_RESP: UNSPECIFIED failure\n");
+                       }
                } else {
                        ret = status_code;
                }
index 5a6c1c76b33bc173c0ab55465ec1ad2885675dde..ae98b5b83b1f0133cc216c2942095081ded5b52d 100644 (file)
@@ -642,6 +642,7 @@ struct mwifiex_private {
        u8 del_list_idx;
        bool hs2_enabled;
        struct mwifiex_uap_bss_param bss_cfg;
+       struct cfg80211_chan_def bss_chandef;
        struct station_parameters *sta_params;
        struct sk_buff_head tdls_txq;
        u8 check_tdls_tx;
@@ -740,6 +741,18 @@ struct mwifiex_tdls_capab {
        struct ieee80211_vht_operation vhtoper;
 };
 
+struct mwifiex_station_stats {
+       u64 last_rx;
+       s8 rssi;
+       u64 rx_bytes;
+       u64 tx_bytes;
+       u32 rx_packets;
+       u32 tx_packets;
+       u32 tx_failed;
+       u8 last_tx_rate;
+       u8 last_tx_htinfo;
+};
+
 /* This is AP/TDLS specific structure which stores information
  * about associated/peer STA
  */
@@ -754,6 +767,7 @@ struct mwifiex_sta_node {
        u16 max_amsdu;
        u8 tdls_status;
        struct mwifiex_tdls_capab tdls_cap;
+       struct mwifiex_station_stats stats;
 };
 
 struct mwifiex_auto_tdls_peer {
@@ -959,6 +973,12 @@ struct mwifiex_adapter {
        u32 num_in_chan_stats;
        int survey_idx;
        bool auto_tdls;
+       u8 coex_scan;
+       u8 coex_min_scan_time;
+       u8 coex_max_scan_time;
+       u8 coex_win_size;
+       u8 coex_tx_win_size;
+       u8 coex_rx_win_size;
 };
 
 void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter);
@@ -1135,6 +1155,9 @@ void mwifiex_set_ht_params(struct mwifiex_private *priv,
 void mwifiex_set_vht_params(struct mwifiex_private *priv,
                            struct mwifiex_uap_bss_param *bss_cfg,
                            struct cfg80211_ap_settings *params);
+void mwifiex_set_tpc_params(struct mwifiex_private *priv,
+                           struct mwifiex_uap_bss_param *bss_cfg,
+                           struct cfg80211_ap_settings *params);
 void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
                           struct cfg80211_ap_settings *params);
 void mwifiex_set_vht_width(struct mwifiex_private *priv,
@@ -1145,6 +1168,11 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
                       struct mwifiex_uap_bss_param *bss_cfg,
                       struct cfg80211_ap_settings *params);
 void mwifiex_set_ba_params(struct mwifiex_private *priv);
+
+void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *pmadapter);
+void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
+                                            struct sk_buff *event_skb);
+
 void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
 int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
                                struct host_cmd_ds_command *cmd,
@@ -1382,6 +1410,7 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
                                        struct mwifiex_bssdescriptor *bss_desc);
 
 u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type);
+u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset);
 
 struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
                                              const char *name,
@@ -1399,7 +1428,8 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
                         struct cfg80211_beacon_data *data);
 int mwifiex_del_mgmt_ies(struct mwifiex_private *priv);
 u8 *mwifiex_11d_code_2_region(u8 code);
-void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
+void mwifiex_uap_set_channel(struct mwifiex_private *priv,
+                            struct mwifiex_uap_bss_param *bss_cfg,
                             struct cfg80211_chan_def chandef);
 int mwifiex_config_start_uap(struct mwifiex_private *priv,
                             struct mwifiex_uap_bss_param *bss_cfg);
@@ -1473,6 +1503,8 @@ mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
 void mwifiex_dfs_cac_work_queue(struct work_struct *work);
 void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work);
 void mwifiex_abort_cac(struct mwifiex_private *priv);
+int mwifiex_stop_radar_detection(struct mwifiex_private *priv,
+                                struct cfg80211_chan_def *chandef);
 int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
                                      struct sk_buff *skb);
 
@@ -1488,7 +1520,8 @@ void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter);
 void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter);
 void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags);
 void mwifiex_queue_main_work(struct mwifiex_adapter *adapter);
-
+void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter);
+void mwifiex_11n_delba(struct mwifiex_private *priv, int tid);
 #ifdef CONFIG_DEBUG_FS
 void mwifiex_debugfs_init(void);
 void mwifiex_debugfs_remove(void);
index aa5b9a310340df972dd5142ede815366d25a0d5b..b645884b3b97a2c1491f745e436d217dec3b5f4d 100644 (file)
@@ -958,6 +958,27 @@ static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv,
        return 0;
 }
 
+static int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv,
+                                   struct host_cmd_ds_command *resp)
+{
+       struct host_cmd_ds_sta_list *sta_list =
+               &resp->params.sta_list;
+       struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv;
+       int i;
+       struct mwifiex_sta_node *sta_node;
+
+       for (i = 0; i < sta_list->sta_count; i++) {
+               sta_node = mwifiex_get_sta_entry(priv, sta_info->mac);
+               if (unlikely(!sta_node))
+                       continue;
+
+               sta_node->stats.rssi = sta_info->rssi;
+               sta_info++;
+       }
+
+       return 0;
+}
+
 /* This function handles the command response of set_cfg_data */
 static int mwifiex_ret_cfg_data(struct mwifiex_private *priv,
                                struct host_cmd_ds_command *resp)
@@ -1148,6 +1169,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                break;
        case HostCmd_CMD_UAP_SYS_CONFIG:
                break;
+       case HOST_CMD_APCMD_STA_LIST:
+               ret = mwifiex_ret_uap_sta_list(priv, resp);
+               break;
        case HostCmd_CMD_UAP_BSS_START:
                adapter->tx_lock_flag = false;
                adapter->pps_uapsd_mode = false;
@@ -1159,6 +1183,8 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
                break;
        case HostCmd_CMD_UAP_STA_DEAUTH:
                break;
+       case HOST_CMD_APCMD_SYS_RESET:
+               break;
        case HostCmd_CMD_MEF_CFG:
                break;
        case HostCmd_CMD_COALESCE_CFG:
index 95203780010ae5a0887120c85969f9fdac22a1d6..848de2621958cfaacbcd500ae7317fddf6d92085 100644 (file)
@@ -182,6 +182,63 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv,
        return ret;
 }
 
+/*
+* This function handles coex events generated by firmware
+*/
+void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv,
+                                            struct sk_buff *event_skb)
+{
+       struct mwifiex_adapter *adapter = priv->adapter;
+       struct mwifiex_ie_types_header *tlv;
+       struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv;
+       struct mwifiex_ie_types_btcoex_scan_time *scantlv;
+       s32 len = event_skb->len - sizeof(u32);
+       u8 *cur_ptr = event_skb->data + sizeof(u32);
+       u16 tlv_type, tlv_len;
+
+       while (len >= sizeof(struct mwifiex_ie_types_header)) {
+               tlv = (struct mwifiex_ie_types_header *)cur_ptr;
+               tlv_len = le16_to_cpu(tlv->len);
+               tlv_type = le16_to_cpu(tlv->type);
+
+               if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len)
+                       break;
+               switch (tlv_type) {
+               case TLV_BTCOEX_WL_AGGR_WINSIZE:
+                       winsizetlv =
+                           (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv;
+                       adapter->coex_win_size = winsizetlv->coex_win_size;
+                       adapter->coex_tx_win_size =
+                               winsizetlv->tx_win_size;
+                       adapter->coex_rx_win_size =
+                               winsizetlv->rx_win_size;
+                       mwifiex_coex_ampdu_rxwinsize(adapter);
+                       mwifiex_update_ampdu_txwinsize(adapter);
+                       break;
+
+               case TLV_BTCOEX_WL_SCANTIME:
+                       scantlv =
+                           (struct mwifiex_ie_types_btcoex_scan_time *)tlv;
+                       adapter->coex_scan = scantlv->coex_scan;
+                       adapter->coex_min_scan_time = scantlv->min_scan_time;
+                       adapter->coex_max_scan_time = scantlv->max_scan_time;
+                       break;
+
+               default:
+                       break;
+               }
+
+               len -= tlv_len + sizeof(struct mwifiex_ie_types_header);
+               cur_ptr += tlv_len +
+                       sizeof(struct mwifiex_ie_types_header);
+       }
+
+       dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n",
+               adapter->coex_scan, adapter->coex_min_scan_time,
+               adapter->coex_win_size, adapter->coex_tx_win_size,
+               adapter->coex_rx_win_size);
+}
+
 /*
  * This function handles events generated by firmware.
  *
@@ -531,6 +588,11 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                ret = mwifiex_11h_handle_radar_detected(priv,
                                                        adapter->event_skb);
                break;
+       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+               dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n");
+               mwifiex_bt_coex_wlan_param_update_event(priv,
+                                                       adapter->event_skb);
+               break;
        default:
                mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n",
                            eventcause);
index 28dcc84a34d2b2c1878cace213c8893b033c0580..5ed9b794053e760163dda372f205fd28463a9efe 100644 (file)
@@ -88,13 +88,22 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
        struct mwifiex_adapter *adapter = priv->adapter;
        u8 *head_ptr;
        struct txpd *local_tx_pd = NULL;
+       struct mwifiex_sta_node *dest_node;
+       struct ethhdr *hdr = (void *)skb->data;
 
        hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
 
-       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+       if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
+               dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest);
+               if (dest_node) {
+                       dest_node->stats.tx_bytes += skb->len;
+                       dest_node->stats.tx_packets++;
+               }
+
                head_ptr = mwifiex_process_uap_txpd(priv, skb);
-       else
+       } else {
                head_ptr = mwifiex_process_sta_txpd(priv, skb);
+       }
 
        if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) {
                skb_queue_tail(&adapter->tx_data_q, skb);
@@ -310,11 +319,11 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
                priv->stats.tx_errors++;
        }
 
-       if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) {
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
                atomic_dec_return(&adapter->pending_bridged_pkts);
-               if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
-                       goto done;
-       }
+
+       if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT)
+               goto done;
 
        if (aggr)
                /* For skb_aggr, do not wake up tx queue */
index a4ae28353b6d8bb2fd80c977aad8a7c06d78d6a3..b74930054b8c0b1f1cc2066ef2d22f2ca542ebb4 100644 (file)
@@ -222,6 +222,23 @@ void mwifiex_set_vht_params(struct mwifiex_private *priv,
        return;
 }
 
+/* This function updates 11ac related parameters from IE
+ * and sets them into bss_config structure.
+ */
+void mwifiex_set_tpc_params(struct mwifiex_private *priv,
+                           struct mwifiex_uap_bss_param *bss_cfg,
+                           struct cfg80211_ap_settings *params)
+{
+       const u8 *tpc_ie;
+
+       tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail,
+                                 params->beacon.tail_len);
+       if (tpc_ie)
+               bss_cfg->power_constraint = *(tpc_ie + 2);
+       else
+               bss_cfg->power_constraint = 0;
+}
+
 /* Enable VHT only when cfg80211_ap_settings has VHT IE.
  * Otherwise disable VHT.
  */
@@ -466,6 +483,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
        struct host_cmd_tlv_auth_type *auth_type;
        struct host_cmd_tlv_rates *tlv_rates;
        struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer;
+       struct host_cmd_tlv_power_constraint *pwr_ct;
        struct mwifiex_ie_types_htcap *htcap;
        struct mwifiex_ie_types_wmmcap *wmm_cap;
        struct mwifiex_uap_bss_param *bss_cfg = cmd_buf;
@@ -644,6 +662,15 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
                tlv += sizeof(*ao_timer);
        }
 
+       if (bss_cfg->power_constraint) {
+               pwr_ct = (void *)tlv;
+               pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT);
+               pwr_ct->header.len = cpu_to_le16(sizeof(u8));
+               pwr_ct->constraint = bss_cfg->power_constraint;
+               cmd_size += sizeof(*pwr_ct);
+               tlv += sizeof(*pwr_ct);
+       }
+
        if (bss_cfg->ps_sta_ao_timer) {
                ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv;
                ps_ao_timer->header.type =
@@ -754,6 +781,8 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
                break;
        case HostCmd_CMD_UAP_BSS_START:
        case HostCmd_CMD_UAP_BSS_STOP:
+       case HOST_CMD_APCMD_SYS_RESET:
+       case HOST_CMD_APCMD_STA_LIST:
                cmd->command = cpu_to_le16(cmd_no);
                cmd->size = cpu_to_le16(S_DS_GEN);
                break;
@@ -775,11 +804,14 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no,
        return 0;
 }
 
-void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
+void mwifiex_uap_set_channel(struct mwifiex_private *priv,
+                            struct mwifiex_uap_bss_param *bss_cfg,
                             struct cfg80211_chan_def chandef)
 {
        u8 config_bands = 0;
 
+       priv->bss_chandef = chandef;
+
        bss_cfg->channel = ieee80211_frequency_to_channel(
                                                     chandef.chan->center_freq);
 
@@ -800,19 +832,28 @@ void mwifiex_uap_set_channel(struct mwifiex_uap_bss_param *bss_cfg,
                if (chandef.width > NL80211_CHAN_WIDTH_40)
                        config_bands |= BAND_AAC;
        }
+
+       priv->adapter->config_bands = config_bands;
 }
 
 int mwifiex_config_start_uap(struct mwifiex_private *priv,
                             struct mwifiex_uap_bss_param *bss_cfg)
 {
+       enum state_11d_t state_11d;
+
        if (mwifiex_del_mgmt_ies(priv))
                mwifiex_dbg(priv->adapter, ERROR,
                            "Failed to delete mgmt IEs!\n");
 
        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP,
                             HostCmd_ACT_GEN_SET, 0, NULL, true)) {
-               mwifiex_dbg(priv->adapter, ERROR,
-                           "Failed to stop the BSS\n");
+               mwifiex_dbg(priv->adapter, ERROR, "Failed to stop the BSS\n");
+               return -1;
+       }
+
+       if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET,
+                            HostCmd_ACT_GEN_SET, 0, NULL, true)) {
+               mwifiex_dbg(priv->adapter, ERROR, "Failed to reset BSS\n");
                return -1;
        }
 
@@ -824,6 +865,16 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv,
                return -1;
        }
 
+       /* Send cmd to FW to enable 11D function */
+       state_11d = ENABLE_11D;
+       if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
+                            HostCmd_ACT_GEN_SET, DOT11D_I,
+                            &state_11d, true)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: failed to enable 11D\n");
+               return -1;
+       }
+
        if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
                             HostCmd_ACT_GEN_SET, 0, NULL, false)) {
                mwifiex_dbg(priv->adapter, ERROR,
index 06ce3fe660f138d51873838eda532207d9665004..7bc1f850e3b7195302577738ef3c546f4fddd92a 100644 (file)
 #include "main.h"
 #include "11n.h"
 
+#define MWIFIEX_BSS_START_EVT_FIX_SIZE    12
 
+static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv,
+                                        struct sk_buff *event)
+{
+       int evt_len;
+       u8 *curr;
+       u16 tlv_len;
+       struct mwifiex_ie_types_data *tlv_hdr;
+       struct ieee_types_wmm_parameter *wmm_param_ie = NULL;
+       int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK;
+
+       priv->wmm_enabled = false;
+       skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE);
+       evt_len = event->len;
+       curr = event->data;
+
+       mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:",
+                        event->data, event->len);
 
+       while ((evt_len >= sizeof(tlv_hdr->header))) {
+               tlv_hdr = (struct mwifiex_ie_types_data *)curr;
+               tlv_len = le16_to_cpu(tlv_hdr->header.len);
+
+               if (evt_len < tlv_len + sizeof(tlv_hdr->header))
+                       break;
+
+               switch (le16_to_cpu(tlv_hdr->header.type)) {
+               case WLAN_EID_HT_CAPABILITY:
+                       priv->ap_11n_enabled = true;
+                       break;
+
+               case WLAN_EID_VHT_CAPABILITY:
+                       priv->ap_11ac_enabled = true;
+                       break;
+
+               case WLAN_EID_VENDOR_SPECIFIC:
+                       /* Point the regular IEEE IE 2 bytes into the Marvell IE
+                        * and setup the IEEE IE type and length byte fields
+                        */
+                       wmm_param_ie = (void *)(curr + 2);
+                       wmm_param_ie->vend_hdr.len = (u8)tlv_len;
+                       wmm_param_ie->vend_hdr.element_id =
+                                               WLAN_EID_VENDOR_SPECIFIC;
+                       mwifiex_dbg(priv->adapter, EVENT,
+                                   "info: check uap capabilities:\t"
+                                   "wmm parameter set count: %d\n",
+                                   wmm_param_ie->qos_info_bitmap & mask);
+
+                       mwifiex_wmm_setup_ac_downgrade(priv);
+                       priv->wmm_enabled = true;
+                       mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie);
+                       break;
+
+               default:
+                       break;
+               }
+
+               curr += (tlv_len + sizeof(tlv_hdr->header));
+               evt_len -= (tlv_len + sizeof(tlv_hdr->header));
+       }
+
+       return 0;
+}
 
 /*
  * This function handles AP interface specific events generated by firmware.
@@ -134,6 +196,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                       ETH_ALEN);
                if (priv->hist_data)
                        mwifiex_hist_data_reset(priv);
+               mwifiex_check_uap_capabilties(priv, adapter->event_skb);
                break;
        case EVENT_UAP_MIC_COUNTERMEASURES:
                /* For future development */
@@ -229,6 +292,11 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
                mwifiex_dbg(adapter, EVENT, "event: Radar detected\n");
                mwifiex_11h_handle_radar_detected(priv, adapter->event_skb);
                break;
+       case EVENT_BT_COEX_WLAN_PARA_CHANGE:
+               dev_err(adapter->dev, "EVENT: BT coex wlan param update\n");
+               mwifiex_bt_coex_wlan_param_update_event(priv,
+                                                       adapter->event_skb);
+               break;
        default:
                mwifiex_dbg(adapter, EVENT,
                            "event: unknown event id: %#x\n", eventcause);
index 61c52fdf945d42140c000e2c8a298f1f4d08dc60..87667418af5ff528d2100f8674c293fc564067ab 100644 (file)
@@ -97,6 +97,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        struct mwifiex_txinfo *tx_info;
        int hdr_chop;
        struct ethhdr *p_ethhdr;
+       struct mwifiex_sta_node *src_node;
 
        uap_rx_pd = (struct uap_rxpd *)(skb->data);
        rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
@@ -180,6 +181,15 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
        tx_info->bss_type = priv->bss_type;
        tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
 
+       src_node = mwifiex_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source);
+       if (src_node) {
+               src_node->stats.last_rx = jiffies;
+               src_node->stats.rx_bytes += skb->len;
+               src_node->stats.rx_packets++;
+               src_node->stats.last_tx_rate = uap_rx_pd->rx_rate;
+               src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info;
+       }
+
        if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) {
                /* Update bridge packet statistics as the
                 * packet is not going to kernel/upper layer.
@@ -275,6 +285,8 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
        rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
        rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
 
+       ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source);
+
        if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
             le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
                mwifiex_dbg(adapter, ERROR,
@@ -282,6 +294,11 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
                            skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
                            le16_to_cpu(uap_rx_pd->rx_pkt_length));
                priv->stats.rx_dropped++;
+
+               node = mwifiex_get_sta_entry(priv, ta);
+               if (node)
+                       node->stats.tx_failed++;
+
                dev_kfree_skb_any(skb);
                return 0;
        }
@@ -295,7 +312,6 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
                return ret;
        }
 
-       memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
 
        if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
                spin_lock_irqsave(&priv->sta_list_spinlock, flags);
index 370323a47ecb99d3c246b94fc86e0e3eb0f8ffde..790e61953abffc8218ea3ecc6ec5cc2d4d9c630f 100644 (file)
@@ -329,7 +329,7 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
                          struct rxpd *rx_pd)
 {
        u16 stype;
-       u8 category, action_code;
+       u8 category, action_code, *addr2;
        struct ieee80211_hdr *ieee_hdr = (void *)payload;
 
        stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
@@ -337,21 +337,35 @@ mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
        switch (stype) {
        case IEEE80211_STYPE_ACTION:
                category = *(payload + sizeof(struct ieee80211_hdr));
-               action_code = *(payload + sizeof(struct ieee80211_hdr) + 1);
-               if (category == WLAN_CATEGORY_PUBLIC &&
-                   action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
+               switch (category) {
+               case WLAN_CATEGORY_PUBLIC:
+                       action_code = *(payload + sizeof(struct ieee80211_hdr)
+                                       + 1);
+                       if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
+                               addr2 = ieee_hdr->addr2;
+                               mwifiex_dbg(priv->adapter, INFO,
+                                           "TDLS discovery response %pM nf=%d, snr=%d\n",
+                                           addr2, rx_pd->nf, rx_pd->snr);
+                               mwifiex_auto_tdls_update_peer_signal(priv,
+                                                                    addr2,
+                                                                    rx_pd->snr,
+                                                                    rx_pd->nf);
+                       }
+                       break;
+               case WLAN_CATEGORY_BACK:
+                       /*we dont indicate BACK action frames to cfg80211*/
+                       mwifiex_dbg(priv->adapter, INFO,
+                                   "drop BACK action frames");
+                       return -1;
+               default:
                        mwifiex_dbg(priv->adapter, INFO,
-                                   "TDLS discovery response %pM nf=%d, snr=%d\n",
-                                   ieee_hdr->addr2, rx_pd->nf, rx_pd->snr);
-                       mwifiex_auto_tdls_update_peer_signal(priv,
-                                                            ieee_hdr->addr2,
-                                                            rx_pd->snr,
-                                                            rx_pd->nf);
+                                   "unknown public action frame category %d\n",
+                                   category);
                }
-               break;
        default:
                mwifiex_dbg(priv->adapter, INFO,
-                           "unknown mgmt frame subtype %#x\n", stype);
+                   "unknown mgmt frame subtype %#x\n", stype);
+               return 0;
        }
 
        return 0;
@@ -387,8 +401,9 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
 
        ieee_hdr = (void *)skb->data;
        if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
-               mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
-                                         pkt_len, rx_pd);
+               if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
+                                             pkt_len, rx_pd))
+                       return -1;
        }
        /* Remove address4 */
        memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
@@ -416,12 +431,25 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
  */
 int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
 {
+       struct mwifiex_sta_node *src_node;
+       struct ethhdr *p_ethhdr;
+
        if (!skb)
                return -1;
 
        priv->stats.rx_bytes += skb->len;
        priv->stats.rx_packets++;
 
+       if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
+               p_ethhdr = (void *)skb->data;
+               src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source);
+               if (src_node) {
+                       src_node->stats.last_rx = jiffies;
+                       src_node->stats.rx_bytes += skb->len;
+                       src_node->stats.rx_packets++;
+               }
+       }
+
        skb->dev = priv->netdev;
        skb->protocol = eth_type_trans(skb, priv->netdev);
        skb->ip_summed = CHECKSUM_NONE;
index ebd5625d13f1832767f266f932ef012122f72e8e..95c1d7c0a2f388803aedda326087b11e03e438cb 100644 (file)
@@ -2960,6 +2960,15 @@ enum rt2800_eeprom_word {
  */
 #define BCN_TBTT_OFFSET 64
 
+/*
+ * Hardware has 255 WCID table entries. First 32 entries are reserved for
+ * shared keys. Since parts of the pairwise key table might be shared with
+ * the beacon frame buffers 6 & 7 we could only use the first 222 entries.
+ */
+#define WCID_START     33
+#define WCID_END       222
+#define STA_IDS_SIZE   (WCID_END - WCID_START + 2)
+
 /*
  * RT2800 driver data structure
  */
@@ -2971,6 +2980,7 @@ struct rt2800_drv_data {
        u8 txmixer_gain_24g;
        u8 txmixer_gain_5g;
        unsigned int tbtt_tick;
+       DECLARE_BITMAP(sta_ids, STA_IDS_SIZE);
 };
 
 #endif /* RT2800_H */
index 0bc5ac56f283fdc9e3f43f9e4554664d2c6a97f5..9524564f873bc8c71e736451a3032a089faa61c1 100644 (file)
@@ -1381,38 +1381,6 @@ int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
 
-static inline int rt2800_find_wcid(struct rt2x00_dev *rt2x00dev)
-{
-       struct mac_wcid_entry wcid_entry;
-       int idx;
-       u32 offset;
-
-       /*
-        * Search for the first free WCID entry and return the corresponding
-        * index.
-        *
-        * Make sure the WCID starts _after_ the last possible shared key
-        * entry (>32).
-        *
-        * Since parts of the pairwise key table might be shared with
-        * the beacon frame buffers 6 & 7 we should only write into the
-        * first 222 entries.
-        */
-       for (idx = 33; idx <= 222; idx++) {
-               offset = MAC_WCID_ENTRY(idx);
-               rt2800_register_multiread(rt2x00dev, offset, &wcid_entry,
-                                         sizeof(wcid_entry));
-               if (is_broadcast_ether_addr(wcid_entry.mac))
-                       return idx;
-       }
-
-       /*
-        * Use -1 to indicate that we don't have any more space in the WCID
-        * table.
-        */
-       return -1;
-}
-
 int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                               struct rt2x00lib_crypto *crypto,
                               struct ieee80211_key_conf *key)
@@ -1425,7 +1393,7 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
                 * Allow key configuration only for STAs that are
                 * known by the hw.
                 */
-               if (crypto->wcid < 0)
+               if (crypto->wcid > WCID_END)
                        return -ENOSPC;
                key->hw_key_idx = crypto->wcid;
 
@@ -1455,11 +1423,13 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
 {
        int wcid;
        struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
 
        /*
-        * Find next free WCID.
+        * Search for the first free WCID entry and return the corresponding
+        * index.
         */
-       wcid = rt2800_find_wcid(rt2x00dev);
+       wcid = find_first_zero_bit(drv_data->sta_ids, STA_IDS_SIZE) + WCID_START;
 
        /*
         * Store selected wcid even if it is invalid so that we can
@@ -1471,9 +1441,11 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif,
         * No space left in the device, however, we can still communicate
         * with the STA -> No error.
         */
-       if (wcid < 0)
+       if (wcid > WCID_END)
                return 0;
 
+       __set_bit(wcid - WCID_START, drv_data->sta_ids);
+
        /*
         * Clean up WCID attributes and write STA address to the device.
         */
@@ -1487,11 +1459,16 @@ EXPORT_SYMBOL_GPL(rt2800_sta_add);
 
 int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid)
 {
+       struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
+
+       if (wcid > WCID_END)
+               return 0;
        /*
         * Remove WCID entry, no need to clean the attributes as they will
         * get renewed when the WCID is reused.
         */
        rt2800_config_wcid(rt2x00dev, NULL, wcid);
+       __clear_bit(wcid - WCID_START, drv_data->sta_ids);
 
        return 0;
 }
@@ -7968,11 +7945,11 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        /*
         * Don't allow aggregation for stations the hardware isn't aware
         * of because tx status reports for frames to an unknown station
-        * always contain wcid=255 and thus we can't distinguish between
-        * multiple stations which leads to unwanted situations when the
-        * hw reorders frames due to aggregation.
+        * always contain wcid=WCID_END+1 and thus we can't distinguish
+        * between multiple stations which leads to unwanted situations
+        * when the hw reorders frames due to aggregation.
         */
-       if (sta_priv->wcid < 0)
+       if (sta_priv->wcid > WCID_END)
                return 1;
 
        switch (action) {
index 1b8a459a412ba68af39734afe91c8667b239163c..3c26ee65a41513127cbc999416ee90fabc11d890 100644 (file)
@@ -535,16 +535,8 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                      struct ieee80211_sta *sta)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
 
-       /*
-        * If there's no space left in the device table store
-        * -1 as wcid but tell mac80211 everything went ok.
-        */
-       if (rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta))
-               sta_priv->wcid = -1;
-
-       return 0;
+       return rt2x00dev->ops->lib->sta_add(rt2x00dev, vif, sta);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sta_add);
 
@@ -554,12 +546,6 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta);
 
-       /*
-        * If we never sent the STA to the device no need to clean it up.
-        */
-       if (sta_priv->wcid < 0)
-               return 0;
-
        return rt2x00dev->ops->lib->sta_remove(rt2x00dev, sta_priv->wcid);
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
index d930c1f787219413f17dbaa436a719b02c91ab73..ce4da9d79fbd9e44d55eb298379c7de4a28c0eee 100644 (file)
@@ -1123,23 +1123,22 @@ static void rtl88e_dm_init_txpower_tracking(struct ieee80211_hw *hw)
 void rtl88e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       static u8 tm_trigger;
 
        if (!rtlpriv->dm.txpower_tracking)
                return;
 
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17)|BIT(16),
                              0x03);
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Trigger 88E Thermal Meter!!\n");
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
                return;
        } else {
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Schedule TxPowerTracking !!\n");
                                dm_txpower_track_cb_therm(hw);
-               tm_trigger = 0;
+               rtlpriv->dm.tm_trigger = 0;
        }
 }
 
index f5ee67cda73a6920185d9a7241be988d8e6b126b..0aca6f47487c2fe293f082ec562f13172dc13c38 100644 (file)
@@ -1169,23 +1169,22 @@ static void rtl92c_dm_check_txpower_tracking_thermal_meter(
                                                struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       static u8 tm_trigger;
 
        if (!rtlpriv->dm.txpower_tracking)
                return;
 
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
                              0x60);
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Trigger 92S Thermal Meter!!\n");
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
                return;
        } else {
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Schedule TxPowerTracking direct call!!\n");
                rtl92c_dm_txpower_tracking_directcall(hw);
-               tm_trigger = 0;
+               rtlpriv->dm.tm_trigger = 0;
        }
 }
 
index 29983bc96a89289187617a5cf202386f74386639..14b819ea8b71886cc6e6b46ec949e5ce1a87c39d 100644 (file)
@@ -233,13 +233,14 @@ int rtl92c_download_fw(struct ieee80211_hw *hw)
        pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
        pfwdata = (u8 *)rtlhal->pfirmware;
        fwsize = rtlhal->fwsize;
-
        if (IS_FW_HEADER_EXIST(pfwheader)) {
                RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
                         "Firmware Version(%d), Signature(%#x),Size(%d)\n",
                          pfwheader->version, pfwheader->signature,
                          (int)sizeof(struct rtl92c_firmware_header));
 
+               rtlhal->fw_version = pfwheader->version;
+               rtlhal->fw_subversion = pfwheader->subversion;
                pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
                fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
        }
index 189859617db803e4440cff48568a3165790f4a45..767358a553fb083dcc39297fe6f7ef6be74cbad4 100644 (file)
@@ -840,6 +840,26 @@ static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw)
        rtl92c_set_data_filter(hw, value16);
 }
 
+static void _rtl92cu_init_beacon_parameters(struct ieee80211_hw *hw)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+       rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010);
+
+       /* TODO: Remove these magic number */
+       rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);
+       rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
+       rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
+       /* Change beacon AIFS to the largest number
+        * beacause test chip does not contension before sending beacon.
+        */
+       if (IS_NORMAL_CHIP(rtlhal->version))
+               rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
+       else
+               rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
+}
+
 static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -887,7 +907,7 @@ static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
        _rtl92cu_init_usb_aggregation(hw);
        rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20);
        rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version));
-       rtl92c_init_beacon_parameters(hw, rtlhal->version);
+       _rtl92cu_init_beacon_parameters(hw);
        rtl92c_init_ampdu_aggregation(hw);
        rtl92c_init_beacon_max_error(hw);
        return err;
@@ -987,7 +1007,6 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
        int err = 0;
-       static bool iqk_initialized;
        unsigned long flags;
 
        /* As this function can take a very long time (up to 350 ms)
@@ -1038,11 +1057,11 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
        rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
        if (ppsc->rfpwr_state == ERFON) {
                rtl92c_phy_set_rfpath_switch(hw, 1);
-               if (iqk_initialized) {
+               if (rtlphy->iqk_initialized) {
                        rtl92c_phy_iq_calibrate(hw, true);
                } else {
                        rtl92c_phy_iq_calibrate(hw, false);
-                       iqk_initialized = true;
+                       rtlphy->iqk_initialized = true;
                }
                rtl92c_dm_check_txpower_tracking(hw);
                rtl92c_phy_lc_calibrate(hw);
@@ -1391,6 +1410,9 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
                _CardDisableHWSM(hw);
        else
                _CardDisableWithoutHWSM(hw);
+
+       /* after power off we should do iqk again */
+       rtlpriv->phy.iqk_initialized = false;
 }
 
 void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
@@ -1451,25 +1473,6 @@ int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
        return 0;
 }
 
-static void _InitBeaconParameters(struct ieee80211_hw *hw)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
-
-       rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010);
-
-       /* TODO: Remove these magic number */
-       rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);
-       rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
-       rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
-       /* Change beacon AIFS to the largest number
-        * beacause test chip does not contension before sending beacon. */
-       if (IS_NORMAL_CHIP(rtlhal->version))
-               rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
-       else
-               rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
-}
-
 static void _beacon_function_enable(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1490,7 +1493,7 @@ void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw)
        atim_window = 2;        /*FIX MERGE */
        rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
        rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
-       _InitBeaconParameters(hw);
+       _rtl92cu_init_beacon_parameters(hw);
        rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
        /*
         * Force beacon frame transmission even after receiving beacon frame
index f3db6bc8596a3143436eb7db2710d825d7dee8d6..490a7cf7c702fa263b0f392b2ed103d0c4df6848 100644 (file)
@@ -641,21 +641,6 @@ void rtl92c_init_retry_function(struct ieee80211_hw *hw)
        rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
 }
 
-void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
-                                  enum version_8192c version)
-{
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
-
-       rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
-       rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
-       rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
-       if (IS_NORMAL_CHIP(rtlhal->version))
-               rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
-       else
-               rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
-}
-
 void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
index 58548e8f2c41b64276ec1c696b6bf03fd79fc4b9..e34f0f14ccd775954e56840fdddd1a736dc71aae 100644 (file)
@@ -70,9 +70,6 @@ void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw);
 void rtl92c_init_rdg_setting(struct ieee80211_hw *hw);
 void rtl92c_init_retry_function(struct ieee80211_hw *hw);
 
-void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
-                                  enum version_8192c version);
-
 void rtl92c_disable_fast_edca(struct ieee80211_hw *hw);
 void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T);
 
index 12f6d474b492e3b4ff74ed29c76dd972f241a8c0..c972fa50926dfc05fb65ff581b8103e2f7e03285 100644 (file)
@@ -108,13 +108,8 @@ void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
 bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
 {
        bool rtstatus;
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-       bool is92c = IS_92C_SERIAL(rtlhal->version);
 
        rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
-       if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal))
-               rtl_write_byte(rtlpriv, 0x14, 0x71);
        return rtstatus;
 }
 
@@ -122,7 +117,6 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
 {
        bool rtstatus = true;
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
        u16 regval;
        u32 regval32;
        u8 b_reg_hwparafile = 1;
@@ -134,17 +128,11 @@ bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
        rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
-       if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
-               rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
-                              FEN_DIO_PCIE |   FEN_BB_GLB_RSTn | FEN_BBRSTB);
-       } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
-               rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
-                              FEN_BB_GLB_RSTn | FEN_BBRSTB);
-       }
+       rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
+                      FEN_BB_GLB_RSTn | FEN_BBRSTB);
        regval32 = rtl_read_dword(rtlpriv, 0x87c);
        rtl_write_dword(rtlpriv, 0x87c, regval32 & (~BIT(31)));
-       if (IS_HARDWARE_TYPE_8192CU(rtlhal))
-               rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
+       rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
        rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
        if (b_reg_hwparafile == 1)
                rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
@@ -162,7 +150,7 @@ bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
        arraylength =  rtlphy->hwparam_tables[MAC_REG].length ;
        ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
-       RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n");
+       RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CUMAC_2T_ARRAY\n");
        for (i = 0; i < arraylength; i = i + 2)
                rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
        return true;
@@ -259,18 +247,18 @@ bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
                radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
                radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-                        "Radio_A:RTL8192CERADIOA_2TARRAY\n");
+                        "Radio_A:RTL8192CURADIOA_2TARRAY\n");
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-                        "Radio_B:RTL8192CE_RADIOB_2TARRAY\n");
+                        "Radio_B:RTL8192CU_RADIOB_2TARRAY\n");
        } else {
                radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
                radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
                radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
                radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-                        "Radio_A:RTL8192CE_RADIOA_1TARRAY\n");
+                        "Radio_A:RTL8192CU_RADIOA_1TARRAY\n");
                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-                        "Radio_B:RTL8192CE_RADIOB_1TARRAY\n");
+                        "Radio_B:RTL8192CU_RADIOB_1TARRAY\n");
        }
        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath);
        switch (rfpath) {
index b878d56d2f4df6020449e223dfed618c4d36edbc..5624ade92cc047b7891d9de3e081e2e4c51596df 100644 (file)
@@ -66,7 +66,6 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
-       struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
        u32 tx_agc[2] = { 0, 0 }, tmpval = 0;
@@ -74,14 +73,8 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
        u8 idx1, idx2;
        u8 *ptr;
 
-       if (rtlhal->interface == INTF_PCI) {
-               if (rtlefuse->eeprom_regulatory != 0)
-                       turbo_scanoff = true;
-       } else {
-               if ((rtlefuse->eeprom_regulatory != 0) ||
-                   (rtlefuse->external_pa))
-                       turbo_scanoff = true;
-       }
+       if ((rtlefuse->eeprom_regulatory != 0) || (rtlefuse->external_pa))
+               turbo_scanoff = true;
        if (mac->act_scanning) {
                tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
                tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
@@ -90,11 +83,8 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
                            (ppowerlevel[idx1] << 8) |
                            (ppowerlevel[idx1] << 16) |
                            (ppowerlevel[idx1] << 24);
-                       if (rtlhal->interface == INTF_USB) {
-                               if (tx_agc[idx1] > 0x20 &&
-                                   rtlefuse->external_pa)
-                                       tx_agc[idx1] = 0x20;
-                       }
+                       if (tx_agc[idx1] > 0x20 && rtlefuse->external_pa)
+                               tx_agc[idx1] = 0x20;
                }
        } else {
                if (rtlpriv->dm.dynamic_txhighpower_lvl ==
@@ -452,9 +442,6 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
                udelay(1);
                switch (rfpath) {
                case RF90_PATH_A:
-                       rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
-                                       (enum radio_path) rfpath);
-                       break;
                case RF90_PATH_B:
                        rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
                                        (enum radio_path) rfpath);
@@ -483,7 +470,6 @@ static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
                }
        }
        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "<---\n");
-       return rtstatus;
 phy_rf_cfg_fail:
        return rtstatus;
 }
index cbead007171fe52df19fe1b4e40feee833030b36..95880fe4106ef5da88cffa38995a7e2e4a55326b 100644 (file)
@@ -321,7 +321,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
        stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc);
        stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
        stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
-       stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+       stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1)
                                   && (GET_RX_DESC_FAGGR(pdesc) == 1));
        stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
        stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
index a1be5a68edfb4804b35c3747ad2e646b2d432ebc..587b8c505a7625e11b810fefc0b63af3367708e8 100644 (file)
@@ -1240,23 +1240,22 @@ static void rtl92d_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
 void rtl92d_dm_check_txpower_tracking_thermal_meter(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       static u8 tm_trigger;
 
        if (!rtlpriv->dm.txpower_tracking)
                return;
 
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) |
                              BIT(16), 0x03);
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Trigger 92S Thermal Meter!!\n");
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
                return;
        } else {
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Schedule TxPowerTracking direct call!!\n");
                rtl92d_dm_txpower_tracking_callback_thermalmeter(hw);
-               tm_trigger = 0;
+               rtlpriv->dm.tm_trigger = 0;
        }
 }
 
index 575980b88658aeebacfc8646c79a445c83d30a06..9bae5a92e30fba4b50f2d67408882d1e4b61720d 100644 (file)
@@ -200,7 +200,6 @@ static void _rtl92s_dm_check_txpowertracking_thermalmeter(
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_phy *rtlphy = &(rtlpriv->phy);
-       static u8 tm_trigger;
        u8 tx_power_checkcnt = 5;
 
        /* 2T2R TP issue */
@@ -215,13 +214,13 @@ static void _rtl92s_dm_check_txpowertracking_thermalmeter(
                return;
        }
 
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER,
                              RFREG_OFFSET_MASK, 0x60);
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
        } else {
                _rtl92s_dm_txpowertracking_callback_thermalmeter(hw);
-               tm_trigger = 0;
+               rtlpriv->dm.tm_trigger = 0;
        }
 }
 
index e77c3a46c94a65ff0bad9578fdf22b725a50320f..3a81cdba8ca3ef1316d093db9137e779b24fdc04 100644 (file)
@@ -909,23 +909,22 @@ static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       static u8 tm_trigger;
 
        if (!rtlpriv->dm.txpower_tracking)
                return;
 
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
                              0x03);
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Trigger 8723be Thermal Meter!!\n");
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
                return;
        } else {
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Schedule TxPowerTracking !!\n");
                rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
-               tm_trigger = 0;
+               rtlpriv->dm.tm_trigger = 0;
        }
 }
 
index 342678d2ed427d8549d446f5cb5ec0bbc5f3c41d..b57cfd9651968a51e2e77ae31b86712e824057fb 100644 (file)
@@ -1068,20 +1068,18 @@ static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
                struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       static u8 tm_trigger;
 
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
                              BIT(17) | BIT(16), 0x03);
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Trigger 8812 Thermal Meter!!\n");
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
                return;
        }
        RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                 "Schedule TxPowerTracking direct call!!\n");
        rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
-       tm_trigger = 0;
 }
 
 static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
@@ -2519,21 +2517,19 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
 void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       static u8 tm_trigger;
-
-       if (!tm_trigger) {
+       if (!rtlpriv->dm.tm_trigger) {
                rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
                              0x03);
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Trigger 8821ae Thermal Meter!!\n");
-               tm_trigger = 1;
+               rtlpriv->dm.tm_trigger = 1;
                return;
        } else {
                RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
                         "Schedule TxPowerTracking !!\n");
 
                rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
-               tm_trigger = 0;
+               rtlpriv->dm.tm_trigger = 0;
        }
 }
 
index 51572912c53dc27794038d04623c0435e62384e9..2b770b5e2620fc629ea2eca7ef1b499b300eaf8d 100644 (file)
@@ -1665,6 +1665,7 @@ struct rtl_dm {
        u8 last_dtp_lvl;
        u8 thermalvalue_avg[AVG_THERMAL_NUM];
        u8 thermalvalue_avg_index;
+       u8 tm_trigger;
        bool done_txpower;
        u8 dynamic_txhighpower_lvl;     /*Tx high power level */
        u8 dm_flag;             /*Indicate each dynamic mechanism's status. */
index 5695628757ee17db6c4da9ba40d81000f9fa57b5..d6fbdda2cba39bfbacd90fa193ce3aafd8738f9c 100644 (file)
@@ -53,10 +53,7 @@ int wl1251_acx_station_id(struct wl1251 *wl)
                mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i];
 
        ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac));
-       if (ret < 0)
-               goto out;
 
-out:
        kfree(mac);
        return ret;
 }
index 5ba6918ca20bc9d3bc30993c21b7ef10a6c42243..9657f11d48a7547cbf63639c23f0de9bc07920c4 100644 (file)
@@ -246,7 +246,18 @@ static inline void bcma_core_pci_power_save(struct bcma_bus *bus, bool up)
 }
 #endif
 
+#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
 extern int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev);
 extern int bcma_core_pci_plat_dev_init(struct pci_dev *dev);
+#else
+static inline int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
+{
+       return -ENOTSUPP;
+}
+static inline int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
+{
+       return -ENOTSUPP;
+}
+#endif
 
 #endif /* LINUX_BCMA_DRIVER_PCI_H_ */