Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
authorJohn W. Linville <linville@tuxdriver.com>
Wed, 9 Nov 2011 19:49:23 +0000 (14:49 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 9 Nov 2011 19:49:23 +0000 (14:49 -0500)
66 files changed:
drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath9k/Makefile
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9462_2p0_initvals.h
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/mci.c [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/mci.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/brcm80211/brcmfmac/dhd.h
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
drivers/net/wireless/brcm80211/brcmsmac/aiutils.h
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/brcm80211/brcmsmac/dma.h
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
drivers/net/wireless/brcm80211/brcmsmac/main.c
drivers/net/wireless/brcm80211/brcmsmac/main.h
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_cmn.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_int.h
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
drivers/net/wireless/brcm80211/brcmsmac/pmu.c
drivers/net/wireless/brcm80211/brcmsmac/pub.h
drivers/net/wireless/brcm80211/brcmsmac/rate.h
drivers/net/wireless/brcm80211/brcmsmac/srom.c
drivers/net/wireless/brcm80211/brcmsmac/srom.h
drivers/net/wireless/brcm80211/brcmutil/utils.c
drivers/net/wireless/brcm80211/include/brcmu_utils.h
drivers/net/wireless/brcm80211/include/defs.h
drivers/net/wireless/brcm80211/include/soc.h
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-csr.h
drivers/net/wireless/iwlwifi/iwl-devtrace.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwmc3200wifi/cfg80211.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
include/net/mac80211.h
net/mac80211/agg-rx.c
net/mac80211/agg-tx.c
net/mac80211/cfg.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/mesh.c
net/mac80211/mesh.h
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_plink.c
net/mac80211/rx.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/work.c
net/mac80211/wpa.c
net/wireless/nl80211.c

index 908fdbc..fe4bf4d 100644 (file)
@@ -240,6 +240,7 @@ enum ATH_DEBUG {
        ATH_DBG_BTCOEX          = 0x00002000,
        ATH_DBG_WMI             = 0x00004000,
        ATH_DBG_BSTUCK          = 0x00008000,
+       ATH_DBG_MCI             = 0x00010000,
        ATH_DBG_ANY             = 0xffffffff
 };
 
index 36ed3c4..49d3f25 100644 (file)
@@ -4,6 +4,7 @@ ath9k-y +=      beacon.o \
                main.o \
                recv.o \
                xmit.o \
+               mci.o \
 
 ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_ATH9K_PCI) += pci.o
index fe96997..04b060a 100644 (file)
@@ -198,12 +198,14 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
                        synth_freq = chan->channel;
                }
        } else {
-               range = 10;
+               range = AR_SREV_9462(ah) ? 5 : 10;
                max_spur_cnts = 4;
                synth_freq = chan->channel;
        }
 
        for (i = 0; i < max_spur_cnts; i++) {
+               if (AR_SREV_9462(ah) && (i == 0 || i == 3))
+                       continue;
                negative = 0;
                if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
                        cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
index 9c51b39..259a6f3 100644 (file)
@@ -43,16 +43,16 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
        {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
-       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
-       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x00009824, 0x5ac640de, 0x5ac640d0, 0x5ac640d0, 0x5ac640de},
+       {0x00009828, 0x0796be89, 0x0696b081, 0x0696b881, 0x0796be89},
        {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
        {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
        {0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
        {0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
        {0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020},
        {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
-       {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
-       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3039605e, 0x33795d5e},
+       {0x00009e10, 0x92c88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x92c84d2e},
+       {0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
        {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
        {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
@@ -688,8 +688,8 @@ static const u32 ar9462_2p0_mac_postamble_emulation[][5] = {
 static const u32 ar9462_2p0_radio_postamble_sys3ant[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
-       {0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
-       {0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
 };
 
 static const u32 ar9462_2p0_baseband_postamble_emulation[][5] = {
@@ -717,8 +717,8 @@ static const u32 ar9462_2p0_baseband_postamble_emulation[][5] = {
 static const u32 ar9462_2p0_radio_postamble_sys2ant[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
        {0x000160ac, 0xa4646c08, 0xa4646c08, 0x24645808, 0x24645808},
-       {0x00016140, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
-       {0x00016540, 0x10804008, 0x10804008, 0x90804008, 0x90804008},
+       {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
+       {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
 };
 
 static const u32 ar9462_common_wo_xlna_rx_gain_table_2p0[][2] = {
@@ -1059,7 +1059,7 @@ static const u32 ar9462_modes_low_ob_db_tx_gain_table_2p0[][5] = {
 
 static const u32 ar9462_2p0_soc_postamble[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x00007010, 0x00002233, 0x00002233, 0x00002233, 0x00002233},
+       {0x00007010, 0x00000033, 0x00000033, 0x00000033, 0x00000033},
 };
 
 static const u32 ar9462_2p0_baseband_core[][2] = {
@@ -1257,8 +1257,8 @@ static const u32 ar9462_modes_high_ob_db_tx_gain_table_2p0[][5] = {
        {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
        {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
        {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
-       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
-       {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+       {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
        {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
        {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
        {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
@@ -1850,8 +1850,8 @@ static const u32 ar9462_modes_green_ob_db_tx_gain_table_2p0[][5] = {
        {0x0000a540, 0x48025e6c, 0x48025e6c, 0x38001660, 0x38001660},
        {0x0000a544, 0x4e025e8e, 0x4e025e8e, 0x3b001861, 0x3b001861},
        {0x0000a548, 0x53025eb2, 0x53025eb2, 0x3e001a81, 0x3e001a81},
-       {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83},
-       {0x0000a550, 0x5f025ef6, 0x5f025ef6, 0x44001c84, 0x44001c84},
+       {0x0000a54c, 0x59025eb6, 0x59025eb6, 0x42001a83, 0x42001a83},
+       {0x0000a550, 0x5d025ef6, 0x5d025ef6, 0x44001c84, 0x44001c84},
        {0x0000a554, 0x62025f56, 0x62025f56, 0x48001ce3, 0x48001ce3},
        {0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
        {0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
index 1c269f5..4415e89 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "debug.h"
 #include "common.h"
+#include "mci.h"
 
 /*
  * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
@@ -443,7 +444,9 @@ struct ath_btcoex {
        u32 btcoex_no_stomp; /* in usec */
        u32 btcoex_period; /* in usec */
        u32 btscan_no_stomp; /* in usec */
+       u32 duty_cycle;
        struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
+       struct ath_mci_profile mci;
 };
 
 int ath_init_btcoex_timer(struct ath_softc *sc);
index 655576c..2c279dc 100644 (file)
@@ -189,8 +189,8 @@ static void ath_btcoex_period_timer(unsigned long data)
        bool is_btscan;
 
        ath9k_ps_wakeup(sc);
-       ath_detect_bt_priority(sc);
-
+       if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+               ath_detect_bt_priority(sc);
        is_btscan = sc->sc_flags & SC_OP_BT_SCAN;
 
        spin_lock_bh(&btcoex->btcoex_lock);
@@ -212,8 +212,9 @@ static void ath_btcoex_period_timer(unsigned long data)
        }
 
        ath9k_ps_restore(sc);
+       timer_period = btcoex->btcoex_period / 1000;
        mod_timer(&btcoex->period_timer, jiffies +
-                                 msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
+                                 msecs_to_jiffies(timer_period));
 }
 
 /*
index b479160..27471f8 100644 (file)
@@ -2334,7 +2334,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                        ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
        }
        if (AR_SREV_9462(ah))
-               pCap->hw_caps |= ATH9K_HW_CAP_RTT;
+               pCap->hw_caps |= ATH9K_HW_CAP_RTT | ATH9K_HW_CAP_MCI;
 
        return 0;
 }
@@ -2582,7 +2582,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
        struct ath9k_channel *chan = ah->curchan;
        struct ieee80211_channel *channel = chan->chan;
 
-       reg->power_limit = min_t(int, limit, MAX_RATE_POWER);
+       reg->power_limit = min_t(u32, limit, MAX_RATE_POWER);
        if (test)
                channel->max_power = MAX_RATE_POWER / 2;
 
index f389b3c..33e8f2f 100644 (file)
@@ -203,6 +203,7 @@ enum ath9k_hw_caps {
        ATH9K_HW_CAP_5GHZ                       = BIT(14),
        ATH9K_HW_CAP_APM                        = BIT(15),
        ATH9K_HW_CAP_RTT                        = BIT(16),
+       ATH9K_HW_CAP_MCI                        = BIT(17),
 };
 
 struct ath9k_hw_capabilities {
@@ -419,6 +420,16 @@ enum ath9k_rx_qtype {
        ATH9K_RX_QUEUE_MAX,
 };
 
+enum ath_mci_gpm_coex_profile_type {
+       MCI_GPM_COEX_PROFILE_UNKNOWN,
+       MCI_GPM_COEX_PROFILE_RFCOMM,
+       MCI_GPM_COEX_PROFILE_A2DP,
+       MCI_GPM_COEX_PROFILE_HID,
+       MCI_GPM_COEX_PROFILE_BNEP,
+       MCI_GPM_COEX_PROFILE_VOICE,
+       MCI_GPM_COEX_PROFILE_MAX
+};
+
 struct ath9k_beacon_state {
        u32 bs_nexttbtt;
        u32 bs_nextdtim;
index af1b325..e8af582 100644 (file)
@@ -423,6 +423,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
                txq = sc->tx.txq_map[WME_AC_BE];
                ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
                sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+               sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
+               INIT_LIST_HEAD(&sc->btcoex.mci.info);
                break;
        default:
                WARN_ON(1);
index 93fbe6f..e1e006d 100644 (file)
@@ -1133,8 +1133,9 @@ static int ath9k_start(struct ieee80211_hw *hw)
 
        if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
            !ah->btcoex_hw.enabled) {
-               ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
-                                          AR_STOMP_LOW_WLAN_WGHT);
+               if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
+                       ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
+                                                  AR_STOMP_LOW_WLAN_WGHT);
                ath9k_hw_btcoex_enable(ah);
 
                if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
@@ -1237,6 +1238,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
                ath9k_hw_btcoex_disable(ah);
                if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
                        ath9k_btcoex_timer_pause(sc);
+               ath_mci_flush_profile(&sc->btcoex.mci);
        }
 
        spin_lock_bh(&sc->sc_pcu_lock);
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c
new file mode 100644 (file)
index 0000000..0fbb141
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ath9k.h"
+#include "mci.h"
+
+u8 ath_mci_duty_cycle[] = { 0, 50, 60, 70, 80, 85, 90, 95, 98 };
+
+static struct ath_mci_profile_info*
+ath_mci_find_profile(struct ath_mci_profile *mci,
+                    struct ath_mci_profile_info *info)
+{
+       struct ath_mci_profile_info *entry;
+
+       list_for_each_entry(entry, &mci->info, list) {
+               if (entry->conn_handle == info->conn_handle)
+                       break;
+       }
+       return entry;
+}
+
+static bool ath_mci_add_profile(struct ath_common *common,
+                               struct ath_mci_profile *mci,
+                               struct ath_mci_profile_info *info)
+{
+       struct ath_mci_profile_info *entry;
+
+       if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
+           (info->type == MCI_GPM_COEX_PROFILE_VOICE)) {
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Too many SCO profile, failed to add new profile\n");
+               return false;
+       }
+
+       if (((NUM_PROF(mci) - mci->num_sco) == ATH_MCI_MAX_ACL_PROFILE) &&
+           (info->type != MCI_GPM_COEX_PROFILE_VOICE)) {
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Too many ACL profile, failed to add new profile\n");
+               return false;
+       }
+
+       entry = ath_mci_find_profile(mci, info);
+
+       if (entry)
+               memcpy(entry, info, 10);
+       else {
+               entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+               if (!entry)
+                       return false;
+
+               memcpy(entry, info, 10);
+               INC_PROF(mci, info);
+               list_add_tail(&info->list, &mci->info);
+       }
+       return true;
+}
+
+static void ath_mci_del_profile(struct ath_common *common,
+                               struct ath_mci_profile *mci,
+                               struct ath_mci_profile_info *info)
+{
+       struct ath_mci_profile_info *entry;
+
+       entry = ath_mci_find_profile(mci, info);
+
+       if (!entry) {
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Profile to be deleted not found\n");
+               return;
+       }
+       DEC_PROF(mci, entry);
+       list_del(&entry->list);
+       kfree(entry);
+}
+
+void ath_mci_flush_profile(struct ath_mci_profile *mci)
+{
+       struct ath_mci_profile_info *info, *tinfo;
+
+       list_for_each_entry_safe(info, tinfo, &mci->info, list) {
+               list_del(&info->list);
+               DEC_PROF(mci, info);
+               kfree(info);
+       }
+       mci->aggr_limit = 0;
+}
+
+static void ath_mci_adjust_aggr_limit(struct ath_btcoex *btcoex)
+{
+       struct ath_mci_profile *mci = &btcoex->mci;
+       u32 wlan_airtime = btcoex->btcoex_period *
+                               (100 - btcoex->duty_cycle) / 100;
+
+       /*
+        * Scale: wlan_airtime is in ms, aggr_limit is in 0.25 ms.
+        * When wlan_airtime is less than 4ms, aggregation limit has to be
+        * adjusted half of wlan_airtime to ensure that the aggregation can fit
+        * without collision with BT traffic.
+        */
+       if ((wlan_airtime <= 4) &&
+           (!mci->aggr_limit || (mci->aggr_limit > (2 * wlan_airtime))))
+               mci->aggr_limit = 2 * wlan_airtime;
+}
+
+static void ath_mci_update_scheme(struct ath_softc *sc)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       struct ath_mci_profile_info *info;
+       u32 num_profile = NUM_PROF(mci);
+
+       if (num_profile == 1) {
+               info = list_first_entry(&mci->info,
+                                       struct ath_mci_profile_info,
+                                       list);
+               if (mci->num_sco && info->T == 12) {
+                       mci->aggr_limit = 8;
+                       ath_dbg(common, ATH_DBG_MCI,
+                               "Single SCO, aggregation limit 2 ms\n");
+               } else if ((info->type == MCI_GPM_COEX_PROFILE_BNEP) &&
+                          !info->master) {
+                       btcoex->btcoex_period = 60;
+                       ath_dbg(common, ATH_DBG_MCI,
+                               "Single slave PAN/FTP, bt period 60 ms\n");
+               } else if ((info->type == MCI_GPM_COEX_PROFILE_HID) &&
+                        (info->T > 0 && info->T < 50) &&
+                        (info->A > 1 || info->W > 1)) {
+                       btcoex->duty_cycle = 30;
+                       mci->aggr_limit = 8;
+                       ath_dbg(common, ATH_DBG_MCI,
+                               "Multiple attempt/timeout single HID "
+                               "aggregation limit 2 ms dutycycle 30%%\n");
+               }
+       } else if ((num_profile == 2) && (mci->num_hid == 2)) {
+               btcoex->duty_cycle = 30;
+               mci->aggr_limit = 8;
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Two HIDs aggregation limit 2 ms dutycycle 30%%\n");
+       } else if (num_profile > 3) {
+               mci->aggr_limit = 6;
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Three or more profiles aggregation limit 1.5 ms\n");
+       }
+
+       if (IS_CHAN_2GHZ(sc->sc_ah->curchan)) {
+               if (IS_CHAN_HT(sc->sc_ah->curchan))
+                       ath_mci_adjust_aggr_limit(btcoex);
+               else
+                       btcoex->btcoex_period >>= 1;
+       }
+
+       ath9k_hw_btcoex_disable(sc->sc_ah);
+       ath9k_btcoex_timer_pause(sc);
+
+       if (IS_CHAN_5GHZ(sc->sc_ah->curchan))
+               return;
+
+       btcoex->duty_cycle += (mci->num_bdr ? ATH_MCI_MAX_DUTY_CYCLE : 0);
+       if (btcoex->duty_cycle > ATH_MCI_MAX_DUTY_CYCLE)
+               btcoex->duty_cycle = ATH_MCI_MAX_DUTY_CYCLE;
+
+       btcoex->btcoex_period *= 1000;
+       btcoex->btcoex_no_stomp =  btcoex->btcoex_period *
+                                       (100 - btcoex->duty_cycle) / 100;
+
+       ath9k_hw_btcoex_enable(sc->sc_ah);
+       ath9k_btcoex_timer_resume(sc);
+}
+
+void ath_mci_process_profile(struct ath_softc *sc,
+                            struct ath_mci_profile_info *info)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+
+       if (info->start) {
+               if (!ath_mci_add_profile(common, mci, info))
+                       return;
+       } else
+               ath_mci_del_profile(common, mci, info);
+
+       btcoex->btcoex_period = ATH_MCI_DEF_BT_PERIOD;
+       mci->aggr_limit = mci->num_sco ? 6 : 0;
+       if (NUM_PROF(mci)) {
+               btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
+               btcoex->duty_cycle = ath_mci_duty_cycle[NUM_PROF(mci)];
+       } else {
+               btcoex->bt_stomp_type = mci->num_mgmt ? ATH_BTCOEX_STOMP_ALL :
+                                                       ATH_BTCOEX_STOMP_LOW;
+               btcoex->duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
+       }
+
+       ath_mci_update_scheme(sc);
+}
+
+void ath_mci_process_status(struct ath_softc *sc,
+                           struct ath_mci_profile_status *status)
+{
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_btcoex *btcoex = &sc->btcoex;
+       struct ath_mci_profile *mci = &btcoex->mci;
+       struct ath_mci_profile_info info;
+       int i = 0, old_num_mgmt = mci->num_mgmt;
+
+       /* Link status type are not handled */
+       if (status->is_link) {
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Skip link type status update\n");
+               return;
+       }
+
+       memset(&info, 0, sizeof(struct ath_mci_profile_info));
+
+       info.conn_handle = status->conn_handle;
+       if (ath_mci_find_profile(mci, &info)) {
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Skip non link state update for existing profile %d\n",
+                       status->conn_handle);
+               return;
+       }
+       if (status->conn_handle >= ATH_MCI_MAX_PROFILE) {
+               ath_dbg(common, ATH_DBG_MCI,
+                       "Ignore too many non-link update\n");
+               return;
+       }
+       if (status->is_critical)
+               __set_bit(status->conn_handle, mci->status);
+       else
+               __clear_bit(status->conn_handle, mci->status);
+
+       mci->num_mgmt = 0;
+       do {
+               if (test_bit(i, mci->status))
+                       mci->num_mgmt++;
+       } while (++i < ATH_MCI_MAX_PROFILE);
+
+       if (old_num_mgmt != mci->num_mgmt)
+               ath_mci_update_scheme(sc);
+}
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h
new file mode 100644 (file)
index 0000000..9590c61
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2010-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MCI_H
+#define MCI_H
+
+#define ATH_MCI_DEF_BT_PERIOD          40
+#define ATH_MCI_BDR_DUTY_CYCLE         20
+#define ATH_MCI_MAX_DUTY_CYCLE         90
+
+#define ATH_MCI_DEF_AGGR_LIMIT         6 /* in 0.24 ms */
+#define ATH_MCI_MAX_ACL_PROFILE                7
+#define ATH_MCI_MAX_SCO_PROFILE                1
+#define ATH_MCI_MAX_PROFILE            (ATH_MCI_MAX_ACL_PROFILE +\
+                                        ATH_MCI_MAX_SCO_PROFILE)
+
+#define INC_PROF(_mci, _info) do {              \
+               switch (_info->type) {           \
+               case MCI_GPM_COEX_PROFILE_RFCOMM:\
+                       _mci->num_other_acl++;   \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_A2DP:  \
+                       _mci->num_a2dp++;        \
+                       if (!_info->edr)         \
+                               _mci->num_bdr++; \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_HID:   \
+                       _mci->num_hid++;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_BNEP:  \
+                       _mci->num_pan++;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_VOICE: \
+                       _mci->num_sco++;         \
+                       break;                   \
+               default:                         \
+                       break;                   \
+               }                                \
+       } while (0)
+
+#define DEC_PROF(_mci, _info) do {              \
+               switch (_info->type) {           \
+               case MCI_GPM_COEX_PROFILE_RFCOMM:\
+                       _mci->num_other_acl--;   \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_A2DP:  \
+                       _mci->num_a2dp--;        \
+                       if (!_info->edr)         \
+                               _mci->num_bdr--; \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_HID:   \
+                       _mci->num_hid--;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_BNEP:  \
+                       _mci->num_pan--;         \
+                       break;                   \
+               case MCI_GPM_COEX_PROFILE_VOICE: \
+                       _mci->num_sco--;         \
+                       break;                   \
+               default:                         \
+                       break;                   \
+               }                                \
+       } while (0)
+
+#define NUM_PROF(_mci) (_mci->num_other_acl + _mci->num_a2dp + \
+                        _mci->num_hid + _mci->num_pan + _mci->num_sco)
+
+struct ath_mci_profile_info {
+       u8 type;
+       u8 conn_handle;
+       bool start;
+       bool master;
+       bool edr;
+       u8 voice_type;
+       u16 T;          /* Voice: Tvoice, HID: Tsniff,        in slots */
+       u8 W;           /* Voice: Wvoice, HID: Sniff timeout, in slots */
+       u8 A;           /*                HID: Sniff attempt, in slots */
+       struct list_head list;
+};
+
+struct ath_mci_profile_status {
+       bool is_critical;
+       bool is_link;
+       u8 conn_handle;
+};
+
+struct ath_mci_profile {
+       struct list_head info;
+       DECLARE_BITMAP(status, ATH_MCI_MAX_PROFILE);
+       u16 aggr_limit;
+       u8 num_mgmt;
+       u8 num_sco;
+       u8 num_a2dp;
+       u8 num_hid;
+       u8 num_pan;
+       u8 num_other_acl;
+       u8 num_bdr;
+};
+
+void ath_mci_flush_profile(struct ath_mci_profile *mci);
+void ath_mci_process_profile(struct ath_softc *sc,
+                            struct ath_mci_profile_info *info);
+void ath_mci_process_status(struct ath_softc *sc,
+                           struct ath_mci_profile_status *status);
+#endif
index 03b0a65..55d077e 100644 (file)
@@ -601,6 +601,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
        struct sk_buff *skb;
        struct ieee80211_tx_info *tx_info;
        struct ieee80211_tx_rate *rates;
+       struct ath_mci_profile *mci = &sc->btcoex.mci;
        u32 max_4ms_framelen, frmlen;
        u16 aggr_limit, legacy = 0;
        int i;
@@ -645,7 +646,9 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
        if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
                return 0;
 
-       if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED)
+       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit)
+               aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4;
+       else if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED)
                aggr_limit = min((max_4ms_framelen * 3) / 8,
                                 (u32)ATH_AMPDU_LIMIT_MAX);
        else
index 4645766..6da519e 100644 (file)
@@ -87,7 +87,7 @@
 #define TOE_TX_CSUM_OL         0x00000001
 #define TOE_RX_CSUM_OL         0x00000002
 
-#define        BRCMF_BSS_INFO_VERSION  108 /* current ver of brcmf_bss_info struct */
+#define        BRCMF_BSS_INFO_VERSION  108 /* curr ver of brcmf_bss_info_le struct */
 
 /* size of brcmf_scan_params not including variable length array */
 #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
 
 /* For supporting multiple interfaces */
 #define BRCMF_MAX_IFS  16
-#define BRCMF_DEL_IF   -0xe
-#define BRCMF_BAD_IF   -0xf
 
 #define DOT11_BSSTYPE_ANY                      2
 #define DOT11_MAX_DEFAULT_KEYS 4
@@ -365,7 +363,7 @@ struct brcmf_pkt_filter_enable_le {
  * Applications MUST CHECK ie_offset field and length field to access IEs and
  * next bss_info structure in a vector (in struct brcmf_scan_results)
  */
-struct brcmf_bss_info {
+struct brcmf_bss_info_le {
        __le32 version;         /* version field */
        __le32 length;          /* byte length of data in this record,
                                 * starting at version and including IEs
@@ -466,14 +464,13 @@ struct brcmf_scan_results {
        u32 buflen;
        u32 version;
        u32 count;
-       struct brcmf_bss_info bss_info[1];
+       struct brcmf_bss_info_le bss_info_le[];
 };
 
 struct brcmf_scan_results_le {
        __le32 buflen;
        __le32 version;
        __le32 count;
-       struct brcmf_bss_info bss_info[1];
 };
 
 /* used for association with a specific BSSID and chanspec list */
@@ -493,10 +490,6 @@ struct brcmf_join_params {
        struct brcmf_assoc_params_le params_le;
 };
 
-/* size of brcmf_scan_results not including variable length array */
-#define BRCMF_SCAN_RESULTS_FIXED_SIZE \
-       (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info))
-
 /* incremental scan results struct */
 struct brcmf_iscan_results {
        union {
@@ -511,7 +504,7 @@ struct brcmf_iscan_results {
 
 /* size of brcmf_iscan_results not including variable length array */
 #define BRCMF_ISCAN_RESULTS_FIXED_SIZE \
-       (BRCMF_SCAN_RESULTS_FIXED_SIZE + \
+       (sizeof(struct brcmf_scan_results) + \
         offsetof(struct brcmf_iscan_results, results))
 
 struct brcmf_wsec_key {
@@ -734,8 +727,7 @@ extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx,
 extern void brcmf_c_init(void);
 
 extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx,
-                       struct net_device *ndev, char *name, u8 *mac_addr,
-                       u32 flags, u8 bssidx);
+                       char *name, u8 *mac_addr);
 extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx);
 
 /* Send packet to dongle via data channel */
index 8918261..40928e5 100644 (file)
@@ -488,10 +488,9 @@ brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata,
 
                if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
                        if (ifevent->action == BRCMF_E_IF_ADD)
-                               brcmf_add_if(drvr_priv, ifevent->ifidx, NULL,
+                               brcmf_add_if(drvr_priv, ifevent->ifidx,
                                             event->ifname,
-                                            pvt_data->eth.h_dest,
-                                            ifevent->flags, ifevent->bssidx);
+                                            pvt_data->eth.h_dest);
                        else
                                brcmf_del_if(drvr_priv, ifevent->ifidx);
                } else {
index 4acbac5..719fd93 100644 (file)
@@ -58,7 +58,6 @@ struct brcmf_if {
        struct net_device *ndev;
        struct net_device_stats stats;
        int idx;                /* iface idx in dongle */
-       int state;              /* interface state */
        u8 mac_addr[ETH_ALEN];  /* assigned MAC address */
 };
 
@@ -80,20 +79,6 @@ struct brcmf_info {
 /* Error bits */
 module_param(brcmf_msg_level, int, 0);
 
-
-static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *ndev)
-{
-       int i = 0;
-
-       while (i < BRCMF_MAX_IFS) {
-               if (drvr_priv->iflist[i] && drvr_priv->iflist[i]->ndev == ndev)
-                       return i;
-               i++;
-       }
-
-       return BRCMF_BAD_IF;
-}
-
 int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name)
 {
        int i = BRCMF_MAX_IFS;
@@ -285,14 +270,9 @@ _brcmf_set_mac_address(struct work_struct *work)
 
 static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
        struct sockaddr *sa = (struct sockaddr *)addr;
-       int ifidx;
-
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF)
-               return -1;
 
        memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN);
        schedule_work(&drvr_priv->setmacaddr_work);
@@ -301,13 +281,8 @@ static int brcmf_netdev_set_mac_address(struct net_device *ndev, void *addr)
 
 static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
-
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF)
-               return;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        schedule_work(&drvr_priv->multicast_work);
 }
@@ -341,9 +316,8 @@ int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf)
 static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        int ret;
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -355,9 +329,8 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                return -ENODEV;
        }
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF) {
-               brcmf_dbg(ERROR, "bad ifidx %d\n", ifidx);
+       if (!drvr_priv->iflist[ifp->idx]) {
+               brcmf_dbg(ERROR, "bad ifidx %d\n", ifp->idx);
                netif_stop_queue(ndev);
                return -ENODEV;
        }
@@ -367,20 +340,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                struct sk_buff *skb2;
 
                brcmf_dbg(INFO, "%s: insufficient headroom\n",
-                         brcmf_ifname(&drvr_priv->pub, ifidx));
+                         brcmf_ifname(&drvr_priv->pub, ifp->idx));
                drvr_priv->pub.tx_realloc++;
                skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen);
                dev_kfree_skb(skb);
                skb = skb2;
                if (skb == NULL) {
                        brcmf_dbg(ERROR, "%s: skb_realloc_headroom failed\n",
-                                 brcmf_ifname(&drvr_priv->pub, ifidx));
+                                 brcmf_ifname(&drvr_priv->pub, ifp->idx));
                        ret = -ENOMEM;
                        goto done;
                }
        }
 
-       ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb);
+       ret = brcmf_sendpkt(&drvr_priv->pub, ifp->idx, skb);
 
 done:
        if (ret)
@@ -482,12 +455,10 @@ void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb,
                                          skb_mac_header(skb),
                                          &event, &data);
 
-               if (drvr_priv->iflist[ifidx] &&
-                   !drvr_priv->iflist[ifidx]->state)
+               if (drvr_priv->iflist[ifidx]) {
                        ifp = drvr_priv->iflist[ifidx];
-
-               if (ifp->ndev)
                        ifp->ndev->last_rx = jiffies;
+               }
 
                drvr->dstats.rx_bytes += skb->len;
                drvr->rx_packets++;     /* Local count */
@@ -524,19 +495,11 @@ void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success)
 
 static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       struct brcmf_if *ifp;
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       if (ifidx == BRCMF_BAD_IF)
-               return NULL;
-
-       ifp = drvr_priv->iflist[ifidx];
-
        if (drvr_priv->pub.up)
                /* Use the protocol to get dongle stats */
                brcmf_proto_dstats(&drvr_priv->pub);
@@ -637,8 +600,8 @@ static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol)
 static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
                                    struct ethtool_drvinfo *info)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        sprintf(info->driver, KBUILD_MODNAME);
        sprintf(info->version, "%lu", drvr_priv->pub.drv_version);
@@ -765,14 +728,12 @@ static int brcmf_ethtool(struct brcmf_info *drvr_priv, void __user *uaddr)
 static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
                                    int cmd)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-       brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifidx, cmd);
+       brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd);
 
-       if (ifidx == BRCMF_BAD_IF)
+       if (!drvr_priv->iflist[ifp->idx])
                return -1;
 
        if (cmd == SIOCETHTOOL)
@@ -788,17 +749,14 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
        s32 err = 0;
        int buflen = 0;
        bool is_set_key_cmd;
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
-       int ifidx;
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
 
        memset(&dcmd, 0, sizeof(dcmd));
        dcmd.cmd = cmd;
        dcmd.buf = arg;
        dcmd.len = len;
 
-       ifidx = brcmf_net2idx(drvr_priv, ndev);
-
        if (dcmd.buf != NULL)
                buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
 
@@ -826,7 +784,7 @@ s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
        if (is_set_key_cmd)
                brcmf_netdev_wait_pend8021x(ndev);
 
-       err = brcmf_proto_dcmd(&drvr_priv->pub, ifidx, &dcmd, buflen);
+       err = brcmf_proto_dcmd(&drvr_priv->pub, ifp->idx, &dcmd, buflen);
 
 done:
        if (err > 0)
@@ -837,7 +795,8 @@ done:
 
 static int brcmf_netdev_stop(struct net_device *ndev)
 {
-       struct brcmf_pub *drvr = *(struct brcmf_pub **) netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_pub *drvr = &ifp->info->pub;
 
        brcmf_dbg(TRACE, "Enter\n");
        brcmf_cfg80211_down(drvr->config);
@@ -853,16 +812,14 @@ static int brcmf_netdev_stop(struct net_device *ndev)
 
 static int brcmf_netdev_open(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)
-                                       netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
        u32 toe_ol;
-       int ifidx = brcmf_net2idx(drvr_priv, ndev);
        s32 ret = 0;
 
-       brcmf_dbg(TRACE, "ifidx %d\n", ifidx);
-
-       if (ifidx == 0) {       /* do it only for primary eth0 */
+       brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
 
+       if (ifp->idx == 0) {    /* do it only for primary eth0 */
                /* try to bring up bus */
                ret = brcmf_bus_start(&drvr_priv->pub);
                if (ret != 0) {
@@ -874,12 +831,12 @@ static int brcmf_netdev_open(struct net_device *ndev)
                memcpy(ndev->dev_addr, drvr_priv->pub.mac, ETH_ALEN);
 
                /* Get current TOE mode from dongle */
-               if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0
+               if (brcmf_toe_get(drvr_priv, ifp->idx, &toe_ol) >= 0
                    && (toe_ol & TOE_TX_CSUM_OL) != 0)
-                       drvr_priv->iflist[ifidx]->ndev->features |=
+                       drvr_priv->iflist[ifp->idx]->ndev->features |=
                                NETIF_F_IP_CSUM;
                else
-                       drvr_priv->iflist[ifidx]->ndev->features &=
+                       drvr_priv->iflist[ifp->idx]->ndev->features &=
                                ~NETIF_F_IP_CSUM;
        }
        /* Allow transmit calls */
@@ -893,75 +850,62 @@ static int brcmf_netdev_open(struct net_device *ndev)
        return ret;
 }
 
+static const struct net_device_ops brcmf_netdev_ops_pri = {
+       .ndo_open = brcmf_netdev_open,
+       .ndo_stop = brcmf_netdev_stop,
+       .ndo_get_stats = brcmf_netdev_get_stats,
+       .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
+       .ndo_start_xmit = brcmf_netdev_start_xmit,
+       .ndo_set_mac_address = brcmf_netdev_set_mac_address,
+       .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
+};
+
 int
-brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, struct net_device *ndev,
-            char *name, u8 *mac_addr, u32 flags, u8 bssidx)
+brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, char *name, u8 *mac_addr)
 {
        struct brcmf_if *ifp;
-       int ret = 0, err = 0;
+       struct net_device *ndev;
 
-       brcmf_dbg(TRACE, "idx %d, handle->%p\n", ifidx, ndev);
+       brcmf_dbg(TRACE, "idx %d\n", ifidx);
 
        ifp = drvr_priv->iflist[ifidx];
-       if (!ifp) {
-               ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC);
-               if (!ifp)
-                       return -ENOMEM;
+       /*
+        * Delete the existing interface before overwriting it
+        * in case we missed the BRCMF_E_IF_DEL event.
+        */
+       if (ifp) {
+               brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
+                         ifp->ndev->name);
+               netif_stop_queue(ifp->ndev);
+               unregister_netdev(ifp->ndev);
+               free_netdev(ifp->ndev);
+               drvr_priv->iflist[ifidx] = NULL;
+       }
+
+       /* Allocate netdev, including space for private structure */
+       ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
+       if (!ndev) {
+               brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
+               return -ENOMEM;
        }
 
-       memset(ifp, 0, sizeof(struct brcmf_if));
+       ifp = netdev_priv(ndev);
+       ifp->ndev = ndev;
        ifp->info = drvr_priv;
        drvr_priv->iflist[ifidx] = ifp;
+       ifp->idx = ifidx;
        if (mac_addr != NULL)
                memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
 
-       if (ndev == NULL) {
-               ifp->state = BRCMF_E_IF_ADD;
-               ifp->idx = ifidx;
-               /*
-                * Delete the existing interface before overwriting it
-                * in case we missed the BRCMF_E_IF_DEL event.
-                */
-               if (ifp->ndev != NULL) {
-                       brcmf_dbg(ERROR, "ERROR: netdev:%s already exists, try free & unregister\n",
-                                 ifp->ndev->name);
-                       netif_stop_queue(ifp->ndev);
-                       unregister_netdev(ifp->ndev);
-                       free_netdev(ifp->ndev);
-               }
-
-               /* Allocate netdev, including space for private structure */
-               ifp->ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d",
-                                        ether_setup);
-               if (!ifp->ndev) {
-                       brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
-                       ret = -ENOMEM;
-               }
-
-               if (ret == 0) {
-                       memcpy(netdev_priv(ifp->ndev), &drvr_priv,
-                              sizeof(drvr_priv));
-                       err = brcmf_net_attach(&drvr_priv->pub, ifp->idx);
-                       if (err != 0) {
-                               brcmf_dbg(ERROR, "brcmf_net_attach failed, err %d\n",
-                                         err);
-                               ret = -EOPNOTSUPP;
-                       } else {
-                               brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
-                                         current->pid, ifp->ndev->name);
-                               ifp->state = 0;
-                       }
-               }
-
-               if (ret < 0) {
-                       if (ifp->ndev)
-                               free_netdev(ifp->ndev);
+       if (brcmf_net_attach(&drvr_priv->pub, ifp->idx)) {
+               brcmf_dbg(ERROR, "brcmf_net_attach failed");
+               free_netdev(ifp->ndev);
+               drvr_priv->iflist[ifidx] = NULL;
+               return -EOPNOTSUPP;
+       }
 
-                       drvr_priv->iflist[ifp->idx] = NULL;
-                       kfree(ifp);
-               }
-       } else
-               ifp->ndev = ndev;
+       brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
+                 current->pid, ifp->ndev->name);
 
        return 0;
 }
@@ -977,47 +921,36 @@ void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx)
                brcmf_dbg(ERROR, "Null interface\n");
                return;
        }
+       if (ifp->ndev) {
+               if (ifidx == 0) {
+                       if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
+                               rtnl_lock();
+                               brcmf_netdev_stop(ifp->ndev);
+                               rtnl_unlock();
+                       }
+               } else {
+                       netif_stop_queue(ifp->ndev);
+               }
 
-       ifp->state = BRCMF_E_IF_DEL;
-       ifp->idx = ifidx;
-       if (ifp->ndev != NULL) {
-               netif_stop_queue(ifp->ndev);
                unregister_netdev(ifp->ndev);
-               free_netdev(ifp->ndev);
                drvr_priv->iflist[ifidx] = NULL;
-               kfree(ifp);
+               if (ifidx == 0)
+                       brcmf_cfg80211_detach(drvr_priv->pub.config);
+               free_netdev(ifp->ndev);
        }
 }
 
 struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
 {
        struct brcmf_info *drvr_priv = NULL;
-       struct net_device *ndev;
 
        brcmf_dbg(TRACE, "Enter\n");
 
-       /* Allocate netdev, including space for private structure */
-       ndev = alloc_netdev(sizeof(drvr_priv), "wlan%d", ether_setup);
-       if (!ndev) {
-               brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
-               goto fail;
-       }
-
        /* Allocate primary brcmf_info */
        drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC);
        if (!drvr_priv)
                goto fail;
 
-       /*
-        * Save the brcmf_info into the priv
-        */
-       memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
-
-       if (brcmf_add_if(drvr_priv, 0, ndev, ndev->name, NULL, 0, 0) ==
-           BRCMF_BAD_IF)
-               goto fail;
-
-       ndev->netdev_ops = NULL;
        mutex_init(&drvr_priv->proto_block);
 
        /* Link to info module */
@@ -1033,29 +966,12 @@ struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen)
                goto fail;
        }
 
-       /* Attach and link in the cfg80211 */
-       drvr_priv->pub.config =
-                       brcmf_cfg80211_attach(ndev,
-                                             brcmf_bus_get_device(bus),
-                                             &drvr_priv->pub);
-       if (drvr_priv->pub.config == NULL) {
-               brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
-               goto fail;
-       }
-
        INIT_WORK(&drvr_priv->setmacaddr_work, _brcmf_set_mac_address);
        INIT_WORK(&drvr_priv->multicast_work, _brcmf_set_multicast_list);
 
-       /*
-        * Save the brcmf_info into the priv
-        */
-       memcpy(netdev_priv(ndev), &drvr_priv, sizeof(drvr_priv));
-
        return &drvr_priv->pub;
 
 fail:
-       if (ndev)
-               free_netdev(ndev);
        if (drvr_priv)
                brcmf_detach(&drvr_priv->pub);
 
@@ -1123,16 +1039,6 @@ int brcmf_bus_start(struct brcmf_pub *drvr)
        return 0;
 }
 
-static struct net_device_ops brcmf_netdev_ops_pri = {
-       .ndo_open = brcmf_netdev_open,
-       .ndo_stop = brcmf_netdev_stop,
-       .ndo_get_stats = brcmf_netdev_get_stats,
-       .ndo_do_ioctl = brcmf_netdev_ioctl_entry,
-       .ndo_start_xmit = brcmf_netdev_start_xmit,
-       .ndo_set_mac_address = brcmf_netdev_set_mac_address,
-       .ndo_set_rx_mode = brcmf_netdev_set_multicast_list
-};
-
 int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
 {
        struct brcmf_info *drvr_priv = drvr->info;
@@ -1169,6 +1075,18 @@ int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx)
 
        memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
 
+       /* attach to cfg80211 for primary interface */
+       if (!ifidx) {
+               drvr->config =
+                       brcmf_cfg80211_attach(ndev,
+                                             brcmf_bus_get_device(drvr->bus),
+                                             drvr);
+               if (drvr->config == NULL) {
+                       brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
+                       goto fail;
+               }
+       }
+
        if (register_netdev(ndev) != 0) {
                brcmf_dbg(ERROR, "couldn't register the net device\n");
                goto fail;
@@ -1210,21 +1128,13 @@ void brcmf_detach(struct brcmf_pub *drvr)
        if (drvr) {
                drvr_priv = drvr->info;
                if (drvr_priv) {
-                       struct brcmf_if *ifp;
                        int i;
 
-                       for (i = 1; i < BRCMF_MAX_IFS; i++)
+                       /* make sure primary interface removed last */
+                       for (i = BRCMF_MAX_IFS-1; i > -1; i--)
                                if (drvr_priv->iflist[i])
                                        brcmf_del_if(drvr_priv, i);
 
-                       ifp = drvr_priv->iflist[0];
-                       if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
-                               rtnl_lock();
-                               brcmf_netdev_stop(ifp->ndev);
-                               rtnl_unlock();
-                               unregister_netdev(ifp->ndev);
-                       }
-
                        cancel_work_sync(&drvr_priv->setmacaddr_work);
                        cancel_work_sync(&drvr_priv->multicast_work);
 
@@ -1233,10 +1143,6 @@ void brcmf_detach(struct brcmf_pub *drvr)
                        if (drvr->prot)
                                brcmf_proto_detach(drvr);
 
-                       brcmf_cfg80211_detach(drvr->config);
-
-                       free_netdev(ifp->ndev);
-                       kfree(ifp);
                        kfree(drvr_priv);
                }
        }
@@ -1302,7 +1208,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv)
 
 int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
 {
-       struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(ndev);
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       struct brcmf_info *drvr_priv = ifp->info;
        int timeout = 10 * HZ / 1000;
        int ntimes = MAX_WAIT_FOR_8021X_TX;
        int pend = brcmf_get_pend_8021x_cnt(drvr_priv);
index 313b8bf..6de489b 100644 (file)
@@ -574,7 +574,7 @@ struct brcmf_bus {
        uint txminmax;
 
        struct sk_buff *glomd;  /* Packet containing glomming descriptor */
-       struct sk_buff *glom;   /* Packet chain for glommed superframe */
+       struct sk_buff_head glom; /* Packet list for glommed superframe */
        uint glomerr;           /* Glom packet read errors */
 
        u8 *rxbuf;              /* Buffer for receiving control packets */
@@ -1222,6 +1222,29 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_bus *bus, bool abort, bool rtx)
                bus->drvr->busstate = BRCMF_BUS_DOWN;
 }
 
+/* copy a buffer into a pkt buffer chain */
+static uint brcmf_sdbrcm_glom_from_buf(struct brcmf_bus *bus, uint len)
+{
+       uint n, ret = 0;
+       struct sk_buff *p;
+       u8 *buf;
+
+       buf = bus->dataptr;
+
+       /* copy the data */
+       skb_queue_walk(&bus->glom, p) {
+               n = min_t(uint, p->len, len);
+               memcpy(p->data, buf, n);
+               buf += n;
+               len -= n;
+               ret += n;
+               if (!len)
+                       break;
+       }
+
+       return ret;
+}
+
 static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
 {
        u16 dlen, totlen;
@@ -1240,7 +1263,8 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
        /* If packets, issue read(s) and send up packet chain */
        /* Return sequence numbers consumed? */
 
-       brcmf_dbg(TRACE, "start: glomd %p glom %p\n", bus->glomd, bus->glom);
+       brcmf_dbg(TRACE, "start: glomd %p glom %p\n",
+                 bus->glomd, skb_peek(&bus->glom));
 
        /* If there's a descriptor, generate the packet chain */
        if (bus->glomd) {
@@ -1287,12 +1311,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                          num, sublen);
                                break;
                        }
-                       if (!pfirst) {
-                               pfirst = plast = pnext;
-                       } else {
-                               plast->next = pnext;
-                               plast = pnext;
-                       }
+                       skb_queue_tail(&bus->glom, pnext);
 
                        /* Adhere to start alignment requirements */
                        pkt_align(pnext, sublen, BRCMF_SDALIGN);
@@ -1308,12 +1327,13 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                brcmf_dbg(GLOM, "glomdesc mismatch: nextlen %d glomdesc %d rxseq %d\n",
                                          bus->nextlen, totlen, rxseq);
                        }
-                       bus->glom = pfirst;
                        pfirst = pnext = NULL;
                } else {
-                       if (pfirst)
-                               brcmu_pkt_buf_free_skb(pfirst);
-                       bus->glom = NULL;
+                       if (!skb_queue_empty(&bus->glom))
+                               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
+                                       skb_unlink(pfirst, &bus->glom);
+                                       brcmu_pkt_buf_free_skb(pfirst);
+                               }
                        num = 0;
                }
 
@@ -1325,17 +1345,17 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
 
        /* Ok -- either we just generated a packet chain,
                 or had one from before */
-       if (bus->glom) {
+       if (!skb_queue_empty(&bus->glom)) {
                if (BRCMF_GLOM_ON()) {
                        brcmf_dbg(GLOM, "try superframe read, packet chain:\n");
-                       for (pnext = bus->glom; pnext; pnext = pnext->next) {
+                       skb_queue_walk(&bus->glom, pnext) {
                                brcmf_dbg(GLOM, "    %p: %p len 0x%04x (%d)\n",
                                          pnext, (u8 *) (pnext->data),
                                          pnext->len, pnext->len);
                        }
                }
 
-               pfirst = bus->glom;
+               pfirst = skb_peek(&bus->glom);
                dlen = (u16) brcmu_pkttotlen(pfirst);
 
                /* Do an SDIO read for the superframe.  Configurable iovar to
@@ -1354,8 +1374,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                                        SDIO_FUNC_2,
                                        F2SYNC, bus->dataptr, dlen,
                                        NULL);
-                       sublen = (u16) brcmu_pktfrombuf(pfirst, 0, dlen,
-                                               bus->dataptr);
+                       sublen = (u16) brcmf_sdbrcm_glom_from_buf(bus, dlen);
                        if (sublen != dlen) {
                                brcmf_dbg(ERROR, "FAILED TO COPY, dlen %d sublen %d\n",
                                          dlen, sublen);
@@ -1380,9 +1399,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                        } else {
                                bus->glomerr = 0;
                                brcmf_sdbrcm_rxfail(bus, true, false);
-                               brcmu_pkt_buf_free_skb(bus->glom);
                                bus->rxglomfail++;
-                               bus->glom = NULL;
+                               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
+                                       skb_unlink(pfirst, &bus->glom);
+                                       brcmu_pkt_buf_free_skb(pfirst);
+                               }
                        }
                        return 0;
                }
@@ -1503,9 +1524,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
                        } else {
                                bus->glomerr = 0;
                                brcmf_sdbrcm_rxfail(bus, true, false);
-                               brcmu_pkt_buf_free_skb(bus->glom);
                                bus->rxglomfail++;
-                               bus->glom = NULL;
+                               skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
+                                       skb_unlink(pfirst, &bus->glom);
+                                       brcmu_pkt_buf_free_skb(pfirst);
+                               }
                        }
                        bus->nextlen = 0;
                        return 0;
@@ -1513,7 +1536,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_bus *bus, u8 rxseq)
 
                /* Basic SD framing looks ok - process each packet (header) */
                save_pfirst = pfirst;
-               bus->glom = NULL;
                plast = NULL;
 
                for (num = 0; pfirst; rxseq++, pfirst = pnext) {
@@ -1850,10 +1872,10 @@ brcmf_sdbrcm_readframes(struct brcmf_bus *bus, uint maxframes, bool *finished)
             rxseq++, rxleft--) {
 
                /* Handle glomming separately */
-               if (bus->glom || bus->glomd) {
+               if (bus->glomd || !skb_queue_empty(&bus->glom)) {
                        u8 cnt;
                        brcmf_dbg(GLOM, "calling rxglom: glomd %p, glom %p\n",
-                                 bus->glomd, bus->glom);
+                                 bus->glomd, skb_peek(&bus->glom));
                        cnt = brcmf_sdbrcm_rxglom(bus, rxseq);
                        brcmf_dbg(GLOM, "rxglom returned %d\n", cnt);
                        rxseq += cnt - 1;
@@ -3602,6 +3624,8 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
        u8 saveclk;
        uint retries;
        int err;
+       struct sk_buff *cur;
+       struct sk_buff *next;
 
        brcmf_dbg(TRACE, "Enter\n");
 
@@ -3661,11 +3685,11 @@ void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus)
        /* Clear any held glomming stuff */
        if (bus->glomd)
                brcmu_pkt_buf_free_skb(bus->glomd);
-
-       if (bus->glom)
-               brcmu_pkt_buf_free_skb(bus->glom);
-
-       bus->glom = bus->glomd = NULL;
+       if (!skb_queue_empty(&bus->glom))
+               skb_queue_walk_safe(&bus->glom, cur, next) {
+                       skb_unlink(cur, &bus->glom);
+                       brcmu_pkt_buf_free_skb(cur);
+               }
 
        /* Clear rx control and wake any waiters */
        bus->rxlen = 0;
@@ -4440,6 +4464,7 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
 
        bus->sdiodev = sdiodev;
        sdiodev->bus = bus;
+       skb_queue_head_init(&bus->glom);
        bus->txbound = BRCMF_TXBOUND;
        bus->rxbound = BRCMF_RXBOUND;
        bus->txminmax = BRCMF_TXMINMAX;
@@ -4521,9 +4546,10 @@ void *brcmf_sdbrcm_probe(u16 bus_no, u16 slot, u16 func, uint bustype,
                        goto fail;
                }
        }
-       /* Ok, have the per-port tell the stack we're open for business */
-       if (brcmf_net_attach(bus->drvr, 0) != 0) {
-               brcmf_dbg(ERROR, "Net attach failed!!\n");
+
+       /* add interface and open for business */
+       if (brcmf_add_if((struct brcmf_info *)bus->drvr, 0, "wlan%d", NULL)) {
+               brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
                goto fail;
        }
 
@@ -4554,10 +4580,6 @@ struct device *brcmf_bus_get_device(struct brcmf_bus *bus)
 void
 brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
 {
-       /* don't start the wd until fw is loaded */
-       if (bus->drvr->busstate == BRCMF_BUS_DOWN)
-               return;
-
        /* Totally stop the timer */
        if (!wdtick && bus->wd_timer_valid == true) {
                del_timer_sync(&bus->timer);
@@ -4566,6 +4588,10 @@ brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick)
                return;
        }
 
+       /* don't start the wd until fw is loaded */
+       if (bus->drvr->busstate == BRCMF_BUS_DOWN)
+               return;
+
        if (wdtick) {
                if (bus->save_ms != BRCMF_WD_POLL_MS) {
                        if (bus->wd_timer_valid == true)
index 5eddabe..73be2c8 100644 (file)
@@ -1997,7 +1997,7 @@ done:
 }
 
 static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
-                                  struct brcmf_bss_info *bi)
+                                  struct brcmf_bss_info_le *bi)
 {
        struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
        struct ieee80211_channel *notify_channel;
@@ -2057,10 +2057,19 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
        return err;
 }
 
+static struct brcmf_bss_info_le *
+next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss)
+{
+       if (bss == NULL)
+               return list->bss_info_le;
+       return (struct brcmf_bss_info_le *)((unsigned long)bss +
+                                           le32_to_cpu(bss->length));
+}
+
 static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
 {
        struct brcmf_scan_results *bss_list;
-       struct brcmf_bss_info *bi = NULL;       /* must be initialized */
+       struct brcmf_bss_info_le *bi = NULL;    /* must be initialized */
        s32 err = 0;
        int i;
 
@@ -2072,7 +2081,7 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv)
        }
        WL_SCAN("scanned AP count (%d)\n", bss_list->count);
        for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) {
-               bi = next_bss(bss_list, bi);
+               bi = next_bss_le(bss_list, bi);
                err = brcmf_inform_single_bss(cfg_priv, bi);
                if (err)
                        break;
@@ -2085,7 +2094,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
 {
        struct wiphy *wiphy = cfg_to_wiphy(cfg_priv);
        struct ieee80211_channel *notify_channel;
-       struct brcmf_bss_info *bi = NULL;
+       struct brcmf_bss_info_le *bi = NULL;
        struct ieee80211_supported_band *band;
        u8 *buf = NULL;
        s32 err = 0;
@@ -2114,7 +2123,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
                goto CleanUp;
        }
 
-       bi = (struct brcmf_bss_info *)(buf + 4);
+       bi = (struct brcmf_bss_info_le *)(buf + 4);
 
        channel = bi->ctl_ch ? bi->ctl_ch :
                                CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
@@ -2188,7 +2197,7 @@ static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key)
 
 static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
 {
-       struct brcmf_bss_info *bi;
+       struct brcmf_bss_info_le *bi;
        struct brcmf_ssid *ssid;
        struct brcmf_tlv *tim;
        u16 beacon_interval;
@@ -2211,7 +2220,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv)
                goto update_bss_info_out;
        }
 
-       bi = (struct brcmf_bss_info *)(cfg_priv->extra_buf + 4);
+       bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4);
        err = brcmf_inform_single_bss(cfg_priv, bi);
        if (err)
                goto update_bss_info_out;
index 62dc461..a613b49 100644 (file)
@@ -352,15 +352,6 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg)
        return &cfg->conn_info;
 }
 
-static inline struct brcmf_bss_info *next_bss(struct brcmf_scan_results *list,
-                                          struct brcmf_bss_info *bss)
-{
-       return bss = bss ?
-               (struct brcmf_bss_info *)((unsigned long)bss +
-                                      le32_to_cpu(bss->length)) :
-               list->bss_info;
-}
-
 extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev,
                                                        struct device *busdev,
                                                        void *data);
index 106a742..b51d1e4 100644 (file)
 /* PCIE Client Mode sb2pcitranslation2 (2 ZettaBytes), high 32 bits */
 #define SI_PCIE_DMA_H32                0x80000000
 
-/* core codes */
-#define        NODEV_CORE_ID           0x700   /* Invalid coreid */
-#define        CC_CORE_ID              0x800   /* chipcommon core */
-#define        ILINE20_CORE_ID         0x801   /* iline20 core */
-#define        SRAM_CORE_ID            0x802   /* sram core */
-#define        SDRAM_CORE_ID           0x803   /* sdram core */
-#define        PCI_CORE_ID             0x804   /* pci core */
-#define        MIPS_CORE_ID            0x805   /* mips core */
-#define        ENET_CORE_ID            0x806   /* enet mac core */
-#define        CODEC_CORE_ID           0x807   /* v90 codec core */
-#define        USB_CORE_ID             0x808   /* usb 1.1 host/device core */
-#define        ADSL_CORE_ID            0x809   /* ADSL core */
-#define        ILINE100_CORE_ID        0x80a   /* iline100 core */
-#define        IPSEC_CORE_ID           0x80b   /* ipsec core */
-#define        UTOPIA_CORE_ID          0x80c   /* utopia core */
-#define        PCMCIA_CORE_ID          0x80d   /* pcmcia core */
-#define        SOCRAM_CORE_ID          0x80e   /* internal memory core */
-#define        MEMC_CORE_ID            0x80f   /* memc sdram core */
-#define        OFDM_CORE_ID            0x810   /* OFDM phy core */
-#define        EXTIF_CORE_ID           0x811   /* external interface core */
-#define        D11_CORE_ID             0x812   /* 802.11 MAC core */
-#define        APHY_CORE_ID            0x813   /* 802.11a phy core */
-#define        BPHY_CORE_ID            0x814   /* 802.11b phy core */
-#define        GPHY_CORE_ID            0x815   /* 802.11g phy core */
-#define        MIPS33_CORE_ID          0x816   /* mips3302 core */
-#define        USB11H_CORE_ID          0x817   /* usb 1.1 host core */
-#define        USB11D_CORE_ID          0x818   /* usb 1.1 device core */
-#define        USB20H_CORE_ID          0x819   /* usb 2.0 host core */
-#define        USB20D_CORE_ID          0x81a   /* usb 2.0 device core */
-#define        SDIOH_CORE_ID           0x81b   /* sdio host core */
-#define        ROBO_CORE_ID            0x81c   /* roboswitch core */
-#define        ATA100_CORE_ID          0x81d   /* parallel ATA core */
-#define        SATAXOR_CORE_ID         0x81e   /* serial ATA & XOR DMA core */
-#define        GIGETH_CORE_ID          0x81f   /* gigabit ethernet core */
-#define        PCIE_CORE_ID            0x820   /* pci express core */
-#define        NPHY_CORE_ID            0x821   /* 802.11n 2x2 phy core */
-#define        SRAMC_CORE_ID           0x822   /* SRAM controller core */
-#define        MINIMAC_CORE_ID         0x823   /* MINI MAC/phy core */
-#define        ARM11_CORE_ID           0x824   /* ARM 1176 core */
-#define        ARM7S_CORE_ID           0x825   /* ARM7tdmi-s core */
-#define        LPPHY_CORE_ID           0x826   /* 802.11a/b/g phy core */
-#define        PMU_CORE_ID             0x827   /* PMU core */
-#define        SSNPHY_CORE_ID          0x828   /* 802.11n single-stream phy core */
-#define        SDIOD_CORE_ID           0x829   /* SDIO device core */
-#define        ARMCM3_CORE_ID          0x82a   /* ARM Cortex M3 core */
-#define        HTPHY_CORE_ID           0x82b   /* 802.11n 4x4 phy core */
-#define        MIPS74K_CORE_ID         0x82c   /* mips 74k core */
-#define        GMAC_CORE_ID            0x82d   /* Gigabit MAC core */
-#define        DMEMC_CORE_ID           0x82e   /* DDR1/2 memory controller core */
-#define        PCIERC_CORE_ID          0x82f   /* PCIE Root Complex core */
-#define        OCP_CORE_ID             0x830   /* OCP2OCP bridge core */
-#define        SC_CORE_ID              0x831   /* shared common core */
-#define        AHB_CORE_ID             0x832   /* OCP2AHB bridge core */
-#define        SPIH_CORE_ID            0x833   /* SPI host core */
-#define        I2S_CORE_ID             0x834   /* I2S core */
-#define        DMEMS_CORE_ID           0x835   /* SDR/DDR1 memory controller core */
-#define        DEF_SHIM_COMP           0x837   /* SHIM component in ubus/6362 */
-#define OOB_ROUTER_CORE_ID     0x367   /* OOB router core ID */
-#define        DEF_AI_COMP             0xfff   /* Default component, in ai chips it
-                                        * maps all unused address ranges
-                                        */
-
 /* chipcommon being the first core: */
 #define        SI_CC_IDX               0
 
 /* SOC Interconnect types (aka chip types) */
 #define        SOCI_AI                 1
 
-/* Common core control flags */
-#define        SICF_BIST_EN            0x8000
-#define        SICF_PME_EN             0x4000
-#define        SICF_CORE_BITS          0x3ffc
-#define        SICF_FGC                0x0002
-#define        SICF_CLOCK_EN           0x0001
-
-/* Common core status flags */
-#define        SISF_BIST_DONE          0x8000
-#define        SISF_BIST_ERROR         0x4000
-#define        SISF_GATED_CLK          0x2000
-#define        SISF_DMA64              0x1000
-#define        SISF_CORE_BITS          0x0fff
-
 /* A register that is common to all cores to
  * communicate w/PMU regarding clock control.
  */
index 6ebec8f..e286fb4 100644 (file)
@@ -14,7 +14,6 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 #include <linux/slab.h>
-#include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
 
@@ -22,6 +21,7 @@
 #include <aiutils.h>
 #include "types.h"
 #include "dma.h"
+#include "soc.h"
 
 /*
  * DMA hardware requires each descriptor ring to be 8kB aligned, and fit within
@@ -901,7 +901,7 @@ static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
 
 /*
  * !! rx entry routine
- * returns a pointer to the next frame received, or NULL if there are no more
+ * returns the number packages in the next frame, or 0 if there are no more
  *   if DMA_CTRL_RXMULTI is defined, DMA scattering(multiple buffers) is
  *   supported with pkts chain
  *   otherwise, it's treated as giant pkt and will be tossed.
@@ -909,38 +909,40 @@ static struct sk_buff *_dma_getnextrxp(struct dma_info *di, bool forceall)
  *   buffer data. After it reaches the max size of buffer, the data continues
  *   in next DMA descriptor buffer WITHOUT DMA header
  */
-struct sk_buff *dma_rx(struct dma_pub *pub)
+int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list)
 {
        struct dma_info *di = (struct dma_info *)pub;
-       struct sk_buff *p, *head, *tail;
+       struct sk_buff_head dma_frames;
+       struct sk_buff *p, *next;
        uint len;
        uint pkt_len;
        int resid = 0;
+       int pktcnt = 1;
 
+       skb_queue_head_init(&dma_frames);
  next_frame:
-       head = _dma_getnextrxp(di, false);
-       if (head == NULL)
-               return NULL;
+       p = _dma_getnextrxp(di, false);
+       if (p == NULL)
+               return 0;
 
-       len = le16_to_cpu(*(__le16 *) (head->data));
+       len = le16_to_cpu(*(__le16 *) (p->data));
        DMA_TRACE(("%s: dma_rx len %d\n", di->name, len));
-       dma_spin_for_len(len, head);
+       dma_spin_for_len(len, p);
 
        /* set actual length */
        pkt_len = min((di->rxoffset + len), di->rxbufsize);
-       __skb_trim(head, pkt_len);
+       __skb_trim(p, pkt_len);
+       skb_queue_tail(&dma_frames, p);
        resid = len - (di->rxbufsize - di->rxoffset);
 
        /* check for single or multi-buffer rx */
        if (resid > 0) {
-               tail = head;
                while ((resid > 0) && (p = _dma_getnextrxp(di, false))) {
-                       tail->next = p;
                        pkt_len = min_t(uint, resid, di->rxbufsize);
                        __skb_trim(p, pkt_len);
-
-                       tail = p;
+                       skb_queue_tail(&dma_frames, p);
                        resid -= di->rxbufsize;
+                       pktcnt++;
                }
 
 #ifdef BCMDBG
@@ -959,13 +961,18 @@ struct sk_buff *dma_rx(struct dma_pub *pub)
                if ((di->dma.dmactrlflags & DMA_CTRL_RXMULTI) == 0) {
                        DMA_ERROR(("%s: dma_rx: bad frame length (%d)\n",
                                   di->name, len));
-                       brcmu_pkt_buf_free_skb(head);
+                       skb_queue_walk_safe(&dma_frames, p, next) {
+                               skb_unlink(p, &dma_frames);
+                               brcmu_pkt_buf_free_skb(p);
+                       }
                        di->dma.rxgiants++;
+                       pktcnt = 1;
                        goto next_frame;
                }
        }
 
-       return head;
+       skb_queue_splice_tail(&dma_frames, skb_list);
+       return pktcnt;
 }
 
 static bool dma64_rxidle(struct dma_info *di)
index ebc5bc5..d317c7c 100644 (file)
@@ -18,6 +18,7 @@
 #define        _BRCM_DMA_H_
 
 #include <linux/delay.h>
+#include <linux/skbuff.h>
 #include "types.h"             /* forward structure declarations */
 
 /* map/unmap direction */
@@ -80,7 +81,7 @@ extern struct dma_pub *dma_attach(char *name, struct si_pub *sih,
                            uint nrxpost, uint rxoffset, uint *msg_level);
 
 void dma_rxinit(struct dma_pub *pub);
-struct sk_buff *dma_rx(struct dma_pub *pub);
+int dma_rx(struct dma_pub *pub, struct sk_buff_head *skb_list);
 bool dma_rxfill(struct dma_pub *pub);
 bool dma_rxreset(struct dma_pub *pub);
 bool dma_txreset(struct dma_pub *pub);
index ac8d02b..8e35c62 100644 (file)
@@ -215,8 +215,7 @@ static const struct ieee80211_supported_band brcms_band_2GHz_nphy_template = {
        .ht_cap = {
                   /* from include/linux/ieee80211.h */
                   .cap = IEEE80211_HT_CAP_GRN_FLD |
-                  IEEE80211_HT_CAP_SGI_20 |
-                  IEEE80211_HT_CAP_SGI_40 | IEEE80211_HT_CAP_40MHZ_INTOLERANT,
+                         IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40,
                   .ht_supported = true,
                   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
                   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
@@ -237,8 +236,7 @@ static const struct ieee80211_supported_band brcms_band_5GHz_nphy_template = {
                        BRCMS_LEGACY_5G_RATE_OFFSET,
        .ht_cap = {
                   .cap = IEEE80211_HT_CAP_GRN_FLD | IEEE80211_HT_CAP_SGI_20 |
-                         IEEE80211_HT_CAP_SGI_40 |
-                         IEEE80211_HT_CAP_40MHZ_INTOLERANT, /* No 40 mhz yet */
+                         IEEE80211_HT_CAP_SGI_40,
                   .ht_supported = true,
                   .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K,
                   .ampdu_density = AMPDU_DEF_MPDU_DENSITY,
@@ -286,6 +284,7 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
 {
        struct brcms_info *wl = hw->priv;
        bool blocked;
+       int err;
 
        ieee80211_wake_queues(hw);
        spin_lock_bh(&wl->lock);
@@ -294,57 +293,69 @@ static int brcms_ops_start(struct ieee80211_hw *hw)
        if (!blocked)
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
 
-       return 0;
+       spin_lock_bh(&wl->lock);
+       /* avoid acknowledging frames before a non-monitor device is added */
+       wl->mute_tx = true;
+
+       if (!wl->pub->up)
+               err = brcms_up(wl);
+       else
+               err = -ENODEV;
+       spin_unlock_bh(&wl->lock);
+
+       if (err != 0)
+               wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
+                         err);
+       return err;
 }
 
 static void brcms_ops_stop(struct ieee80211_hw *hw)
 {
+       struct brcms_info *wl = hw->priv;
+       int status;
+
        ieee80211_stop_queues(hw);
+
+       if (wl->wlc == NULL)
+               return;
+
+       spin_lock_bh(&wl->lock);
+       status = brcms_c_chipmatch(wl->wlc->hw->vendorid,
+                                  wl->wlc->hw->deviceid);
+       spin_unlock_bh(&wl->lock);
+       if (!status) {
+               wiphy_err(wl->wiphy,
+                         "wl: brcms_ops_stop: chipmatch failed\n");
+               return;
+       }
+
+       /* put driver in down state */
+       spin_lock_bh(&wl->lock);
+       brcms_down(wl);
+       spin_unlock_bh(&wl->lock);
 }
 
 static int
 brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
-       struct brcms_info *wl;
-       int err;
+       struct brcms_info *wl = hw->priv;
 
        /* Just STA for now */
-       if (vif->type != NL80211_IFTYPE_AP &&
-           vif->type != NL80211_IFTYPE_MESH_POINT &&
-           vif->type != NL80211_IFTYPE_STATION &&
-           vif->type != NL80211_IFTYPE_WDS &&
-           vif->type != NL80211_IFTYPE_ADHOC) {
+       if (vif->type != NL80211_IFTYPE_STATION) {
                wiphy_err(hw->wiphy, "%s: Attempt to add type %d, only"
                          " STA for now\n", __func__, vif->type);
                return -EOPNOTSUPP;
        }
 
-       wl = hw->priv;
-       spin_lock_bh(&wl->lock);
-       if (!wl->pub->up)
-               err = brcms_up(wl);
-       else
-               err = -ENODEV;
-       spin_unlock_bh(&wl->lock);
-
-       if (err != 0)
-               wiphy_err(hw->wiphy, "%s: brcms_up() returned %d\n", __func__,
-                         err);
+       wl->mute_tx = false;
+       brcms_c_mute(wl->wlc, false);
 
-       return err;
+       return 0;
 }
 
 static void
 brcms_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
-       struct brcms_info *wl;
-
-       wl = hw->priv;
-
-       /* put driver in down state */
-       spin_lock_bh(&wl->lock);
-       brcms_down(wl);
-       spin_unlock_bh(&wl->lock);
 }
 
 static int brcms_ops_config(struct ieee80211_hw *hw, u32 changed)
@@ -876,37 +887,18 @@ static void brcms_free(struct brcms_info *wl)
 }
 
 /*
-* called from both kernel as from this kernel module.
+* called from both kernel as from this kernel module (error flow on attach)
 * precondition: perimeter lock is not acquired.
 */
 static void brcms_remove(struct pci_dev *pdev)
 {
-       struct brcms_info *wl;
-       struct ieee80211_hw *hw;
-       int status;
-
-       hw = pci_get_drvdata(pdev);
-       wl = hw->priv;
-       if (!wl) {
-               pr_err("wl: brcms_remove: pci_get_drvdata failed\n");
-               return;
-       }
+       struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+       struct brcms_info *wl = hw->priv;
 
-       spin_lock_bh(&wl->lock);
-       status = brcms_c_chipmatch(pdev->vendor, pdev->device);
-       spin_unlock_bh(&wl->lock);
-       if (!status) {
-               wiphy_err(wl->wiphy, "wl: brcms_remove: chipmatch "
-                                    "failed\n");
-               return;
-       }
        if (wl->wlc) {
                wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
                wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
                ieee80211_unregister_hw(hw);
-               spin_lock_bh(&wl->lock);
-               brcms_down(wl);
-               spin_unlock_bh(&wl->lock);
        }
        pci_disable_device(pdev);
 
@@ -1080,9 +1072,6 @@ static struct brcms_info *brcms_attach(u16 vendor, u16 device,
 
        wl->pub->ieee_hw = hw;
 
-       /* disable mpc */
-       brcms_c_set_radio_mpc(wl->wlc, false);
-
        /* register our interrupt handler */
        if (request_irq(irq, brcms_isr, IRQF_SHARED, KBUILD_MODNAME, wl)) {
                wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit);
@@ -1318,8 +1307,7 @@ void brcms_init(struct brcms_info *wl)
 {
        BCMMSG(wl->pub->ieee_hw->wiphy, "wl%d\n", wl->pub->unit);
        brcms_reset(wl);
-
-       brcms_c_init(wl->wlc);
+       brcms_c_init(wl->wlc, wl->mute_tx);
 }
 
 /*
@@ -1336,6 +1324,14 @@ uint brcms_reset(struct brcms_info *wl)
        return 0;
 }
 
+void brcms_fatal_error(struct brcms_info *wl)
+{
+       wiphy_err(wl->wlc->wiphy, "wl%d: fatal error, reinitializing\n",
+                 wl->wlc->pub->unit);
+       brcms_reset(wl);
+       ieee80211_restart_hw(wl->pub->ieee_hw);
+}
+
 /*
  * These are interrupt on/off entry points. Disable interrupts
  * during interrupt state transition.
index 177f0e4..6242f18 100644 (file)
@@ -80,6 +80,7 @@ struct brcms_info {
        struct brcms_firmware fw;
        struct wiphy *wiphy;
        struct brcms_ucode ucode;
+       bool mute_tx;
 };
 
 /* misc callbacks */
@@ -104,5 +105,6 @@ extern bool brcms_del_timer(struct brcms_timer *timer);
 extern void brcms_msleep(struct brcms_info *wl, uint ms);
 extern void brcms_dpc(unsigned long data);
 extern void brcms_timer(struct brcms_timer *t);
+extern void brcms_fatal_error(struct brcms_info *wl);
 
 #endif                         /* _BRCM_MAC80211_IF_H_ */
index 510e9bb..f193fab 100644 (file)
 #include "mac80211_if.h"
 #include "ucode_loader.h"
 #include "main.h"
+#include "soc.h"
 
 /*
  * Indication for txflowcontrol that all priority bits in
  * TXQ_STOP_FOR_PRIOFC_MASK are to be considered.
  */
-#define ALLPRIO                -1
-
-/*
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN       ((4 * IEEE80211_MAX_SSID_LEN) + 1)
+#define ALLPRIO                                -1
 
 /* watchdog timer, in unit of ms */
-#define        TIMER_INTERVAL_WATCHDOG 1000
+#define TIMER_INTERVAL_WATCHDOG                1000
 /* radio monitor timer, in unit of ms */
-#define        TIMER_INTERVAL_RADIOCHK 800
-
-/* Max MPC timeout, in unit of watchdog */
-#ifndef BRCMS_MPC_MAX_DELAYCNT
-#define        BRCMS_MPC_MAX_DELAYCNT  10
-#endif
+#define TIMER_INTERVAL_RADIOCHK                800
 
-/* Min MPC timeout, in unit of watchdog */
-#define        BRCMS_MPC_MIN_DELAYCNT  1
-#define        BRCMS_MPC_THRESHOLD     3       /* MPC count threshold level */
-
-/* beacon interval, in unit of 1024TU */
-#define        BEACON_INTERVAL_DEFAULT 100
-/* DTIM interval, in unit of beacon interval */
-#define        DTIM_INTERVAL_DEFAULT   3
-
-/* Scale down delays to accommodate QT slow speed */
 /* beacon interval, in unit of 1024TU */
-#define        BEACON_INTERVAL_DEF_QT  20
-/* DTIM interval, in unit of beacon interval */
-#define        DTIM_INTERVAL_DEF_QT    1
-
-#define        TBTT_ALIGN_LEEWAY_US    100     /* min leeway before first TBTT in us */
+#define BEACON_INTERVAL_DEFAULT                100
 
 /* n-mode support capability */
 /* 2x2 includes both 1x1 & 2x2 devices
 #define WL_11N_3x3                     3
 #define WL_11N_4x4                     4
 
-/* define 11n feature disable flags */
-#define WLFEATURE_DISABLE_11N          0x00000001
-#define WLFEATURE_DISABLE_11N_STBC_TX  0x00000002
-#define WLFEATURE_DISABLE_11N_STBC_RX  0x00000004
-#define WLFEATURE_DISABLE_11N_SGI_TX   0x00000008
-#define WLFEATURE_DISABLE_11N_SGI_RX   0x00000010
-#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020
-#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040
-#define WLFEATURE_DISABLE_11N_GF       0x00000080
-
-#define EDCF_ACI_MASK                0x60
-#define EDCF_ACI_SHIFT               5
-#define EDCF_ECWMIN_MASK             0x0f
-#define EDCF_ECWMAX_SHIFT            4
-#define EDCF_AIFSN_MASK              0x0f
-#define EDCF_AIFSN_MAX               15
-#define EDCF_ECWMAX_MASK             0xf0
-
-#define EDCF_AC_BE_TXOP_STA          0x0000
-#define EDCF_AC_BK_TXOP_STA          0x0000
-#define EDCF_AC_VO_ACI_STA           0x62
-#define EDCF_AC_VO_ECW_STA           0x32
-#define EDCF_AC_VI_ACI_STA           0x42
-#define EDCF_AC_VI_ECW_STA           0x43
-#define EDCF_AC_BK_ECW_STA           0xA4
-#define EDCF_AC_VI_TXOP_STA          0x005e
-#define EDCF_AC_VO_TXOP_STA          0x002f
-#define EDCF_AC_BE_ACI_STA           0x03
-#define EDCF_AC_BE_ECW_STA           0xA4
-#define EDCF_AC_BK_ACI_STA           0x27
-#define EDCF_AC_VO_TXOP_AP           0x002f
-
-#define EDCF_TXOP2USEC(txop)         ((txop) << 5)
-#define EDCF_ECW2CW(exp)             ((1 << (exp)) - 1)
-
-#define APHY_SYMBOL_TIME       4
-#define APHY_PREAMBLE_TIME     16
-#define APHY_SIGNAL_TIME       4
-#define APHY_SIFS_TIME         16
-#define APHY_SERVICE_NBITS     16
-#define APHY_TAIL_NBITS                6
-#define BPHY_SIFS_TIME         10
-#define BPHY_PLCP_SHORT_TIME   96
-
-#define PREN_PREAMBLE          24
-#define PREN_MM_EXT            12
-#define PREN_PREAMBLE_EXT      4
+#define EDCF_ACI_MASK                  0x60
+#define EDCF_ACI_SHIFT                 5
+#define EDCF_ECWMIN_MASK               0x0f
+#define EDCF_ECWMAX_SHIFT              4
+#define EDCF_AIFSN_MASK                        0x0f
+#define EDCF_AIFSN_MAX                 15
+#define EDCF_ECWMAX_MASK               0xf0
+
+#define EDCF_AC_BE_TXOP_STA            0x0000
+#define EDCF_AC_BK_TXOP_STA            0x0000
+#define EDCF_AC_VO_ACI_STA             0x62
+#define EDCF_AC_VO_ECW_STA             0x32
+#define EDCF_AC_VI_ACI_STA             0x42
+#define EDCF_AC_VI_ECW_STA             0x43
+#define EDCF_AC_BK_ECW_STA             0xA4
+#define EDCF_AC_VI_TXOP_STA            0x005e
+#define EDCF_AC_VO_TXOP_STA            0x002f
+#define EDCF_AC_BE_ACI_STA             0x03
+#define EDCF_AC_BE_ECW_STA             0xA4
+#define EDCF_AC_BK_ACI_STA             0x27
+#define EDCF_AC_VO_TXOP_AP             0x002f
+
+#define EDCF_TXOP2USEC(txop)           ((txop) << 5)
+#define EDCF_ECW2CW(exp)               ((1 << (exp)) - 1)
+
+#define APHY_SYMBOL_TIME               4
+#define APHY_PREAMBLE_TIME             16
+#define APHY_SIGNAL_TIME               4
+#define APHY_SIFS_TIME                 16
+#define APHY_SERVICE_NBITS             16
+#define APHY_TAIL_NBITS                        6
+#define BPHY_SIFS_TIME                 10
+#define BPHY_PLCP_SHORT_TIME           96
+
+#define PREN_PREAMBLE                  24
+#define PREN_MM_EXT                    12
+#define PREN_PREAMBLE_EXT              4
 
 #define DOT11_MAC_HDR_LEN              24
-#define        DOT11_ACK_LEN           10
-#define DOT11_BA_LEN           4
+#define DOT11_ACK_LEN                  10
+#define DOT11_BA_LEN                   4
 #define DOT11_OFDM_SIGNAL_EXTENSION    6
 #define DOT11_MIN_FRAG_LEN             256
-#define        DOT11_RTS_LEN           16
-#define        DOT11_CTS_LEN           10
+#define DOT11_RTS_LEN                  16
+#define DOT11_CTS_LEN                  10
 #define DOT11_BA_BITMAP_LEN            128
 #define DOT11_MIN_BEACON_PERIOD                1
 #define DOT11_MAX_BEACON_PERIOD                0xFFFF
-#define        DOT11_MAXNUMFRAGS       16
+#define DOT11_MAXNUMFRAGS              16
 #define DOT11_MAX_FRAG_LEN             2346
 
-#define BPHY_PLCP_TIME         192
-#define RIFS_11N_TIME          2
+#define BPHY_PLCP_TIME                 192
+#define RIFS_11N_TIME                  2
 
-#define WME_VER                        1
-#define WME_SUBTYPE_PARAM_IE   1
-#define WME_TYPE               2
-#define WME_OUI                        "\x00\x50\xf2"
+#define AC_BE                          0
+#define AC_BK                          1
+#define AC_VI                          2
+#define AC_VO                          3
 
-#define AC_BE                  0
-#define AC_BK                  1
-#define AC_VI                  2
-#define AC_VO                  3
-
-#define        BCN_TMPL_LEN            512     /* length of the BCN template area */
+/* length of the BCN template area */
+#define BCN_TMPL_LEN                   512
 
 /* brcms_bss_info flag bit values */
-#define BRCMS_BSS_HT           0x0020  /* BSS is HT (MIMO) capable */
-
-/* Flags used in brcms_c_txq_info.stopped */
-/* per prio flow control bits */
-#define TXQ_STOP_FOR_PRIOFC_MASK       0x000000FF
-/* stop txq enqueue for packet drain */
-#define TXQ_STOP_FOR_PKT_DRAIN         0x00000100
-/* stop txq enqueue for ampdu flow control */
-#define TXQ_STOP_FOR_AMPDU_FLOW_CNTRL  0x00000200
-
-#define        BRCMS_HWRXOFF           38      /* chip rx buffer offset */
-
-/* Find basic rate for a given rate */
-static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
-{
-       if (is_mcs_rate(rspec))
-               return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK]
-                      .leg_ofdm];
-       return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK];
-}
+#define BRCMS_BSS_HT                   0x0020  /* BSS is HT (MIMO) capable */
 
-static u16 frametype(u32 rspec, u8 mimoframe)
-{
-       if (is_mcs_rate(rspec))
-               return mimoframe;
-       return is_cck_rate(rspec) ? FT_CCK : FT_OFDM;
-}
+/* chip rx buffer offset */
+#define BRCMS_HWRXOFF                  38
 
 /* rfdisable delay timer 500 ms, runs of ALP clock */
-#define RFDISABLE_DEFAULT      10000000
+#define RFDISABLE_DEFAULT              10000000
 
 #define BRCMS_TEMPSENSE_PERIOD         10      /* 10 second timeout */
 
@@ -194,87 +134,83 @@ static u16 frametype(u32 rspec, u8 mimoframe)
  * These constants are used ONLY by wlc_prio2prec_map.  Do not use them
  * elsewhere.
  */
-#define        _BRCMS_PREC_NONE                0       /* None = - */
-#define        _BRCMS_PREC_BK          2       /* BK - Background */
-#define        _BRCMS_PREC_BE          4       /* BE - Best-effort */
-#define        _BRCMS_PREC_EE          6       /* EE - Excellent-effort */
-#define        _BRCMS_PREC_CL          8       /* CL - Controlled Load */
-#define        _BRCMS_PREC_VI          10      /* Vi - Video */
-#define        _BRCMS_PREC_VO          12      /* Vo - Voice */
-#define        _BRCMS_PREC_NC          14      /* NC - Network Control */
-
-/* The BSS is generating beacons in HW */
-#define BRCMS_BSSCFG_HW_BCN    0x20
-
-#define        SYNTHPU_DLY_APHY_US     3700    /* a phy synthpu_dly time in us */
-#define        SYNTHPU_DLY_BPHY_US     1050    /* b/g phy synthpu_dly time in us */
-#define        SYNTHPU_DLY_NPHY_US     2048    /* n phy REV3 synthpu_dly time in us */
-#define        SYNTHPU_DLY_LPPHY_US    300     /* lpphy synthpu_dly time in us */
-
-#define        SYNTHPU_DLY_PHY_US_QT   100     /* QT synthpu_dly time in us */
-
-#define        ANTCNT                  10      /* vanilla M_MAX_ANTCNT value */
+#define _BRCMS_PREC_NONE               0       /* None = - */
+#define _BRCMS_PREC_BK                 2       /* BK - Background */
+#define _BRCMS_PREC_BE                 4       /* BE - Best-effort */
+#define _BRCMS_PREC_EE                 6       /* EE - Excellent-effort */
+#define _BRCMS_PREC_CL                 8       /* CL - Controlled Load */
+#define _BRCMS_PREC_VI                 10      /* Vi - Video */
+#define _BRCMS_PREC_VO                 12      /* Vo - Voice */
+#define _BRCMS_PREC_NC                 14      /* NC - Network Control */
+
+/* synthpu_dly times in us */
+#define SYNTHPU_DLY_APHY_US            3700
+#define SYNTHPU_DLY_BPHY_US            1050
+#define SYNTHPU_DLY_NPHY_US            2048
+#define SYNTHPU_DLY_LPPHY_US           300
+
+#define ANTCNT                         10      /* vanilla M_MAX_ANTCNT val */
 
 /* Per-AC retry limit register definitions; uses defs.h bitfield macros */
-#define EDCF_SHORT_S            0
-#define EDCF_SFB_S              4
-#define EDCF_LONG_S             8
-#define EDCF_LFB_S              12
-#define EDCF_SHORT_M            BITFIELD_MASK(4)
-#define EDCF_SFB_M              BITFIELD_MASK(4)
-#define EDCF_LONG_M             BITFIELD_MASK(4)
-#define EDCF_LFB_M              BITFIELD_MASK(4)
+#define EDCF_SHORT_S                   0
+#define EDCF_SFB_S                     4
+#define EDCF_LONG_S                    8
+#define EDCF_LFB_S                     12
+#define EDCF_SHORT_M                   BITFIELD_MASK(4)
+#define EDCF_SFB_M                     BITFIELD_MASK(4)
+#define EDCF_LONG_M                    BITFIELD_MASK(4)
+#define EDCF_LFB_M                     BITFIELD_MASK(4)
 
-#define        RETRY_SHORT_DEF                 7       /* Default Short retry Limit */
-#define        RETRY_SHORT_MAX                 255     /* Maximum Short retry Limit */
-#define        RETRY_LONG_DEF                  4       /* Default Long retry count */
-#define        RETRY_SHORT_FB                  3 /* Short count for fallback rate */
-#define        RETRY_LONG_FB                   2 /* Long count for fallback rate */
+#define RETRY_SHORT_DEF                        7       /* Default Short retry Limit */
+#define RETRY_SHORT_MAX                        255     /* Maximum Short retry Limit */
+#define RETRY_LONG_DEF                 4       /* Default Long retry count */
+#define RETRY_SHORT_FB                 3       /* Short count for fb rate */
+#define RETRY_LONG_FB                  2       /* Long count for fb rate */
 
-#define        APHY_CWMIN              15
-#define PHY_CWMAX              1023
+#define APHY_CWMIN                     15
+#define PHY_CWMAX                      1023
 
-#define EDCF_AIFSN_MIN               1
+#define EDCF_AIFSN_MIN                 1
 
-#define FRAGNUM_MASK           0xF
+#define FRAGNUM_MASK                   0xF
 
-#define APHY_SLOT_TIME         9
-#define BPHY_SLOT_TIME         20
+#define APHY_SLOT_TIME                 9
+#define BPHY_SLOT_TIME                 20
 
-#define        WL_SPURAVOID_OFF        0
-#define        WL_SPURAVOID_ON1        1
-#define        WL_SPURAVOID_ON2        2
+#define WL_SPURAVOID_OFF               0
+#define WL_SPURAVOID_ON1               1
+#define WL_SPURAVOID_ON2               2
 
 /* invalid core flags, use the saved coreflags */
-#define BRCMS_USE_COREFLAGS    0xffffffff
+#define BRCMS_USE_COREFLAGS            0xffffffff
 
 /* values for PLCPHdr_override */
-#define BRCMS_PLCP_AUTO        -1
-#define BRCMS_PLCP_SHORT       0
-#define BRCMS_PLCP_LONG        1
+#define BRCMS_PLCP_AUTO                        -1
+#define BRCMS_PLCP_SHORT               0
+#define BRCMS_PLCP_LONG                        1
 
 /* values for g_protection_override and n_protection_override */
 #define BRCMS_PROTECTION_AUTO          -1
 #define BRCMS_PROTECTION_OFF           0
 #define BRCMS_PROTECTION_ON            1
 #define BRCMS_PROTECTION_MMHDR_ONLY    2
-#define BRCMS_PROTECTION_CTS_ONLY              3
+#define BRCMS_PROTECTION_CTS_ONLY      3
 
 /* values for g_protection_control and n_protection_control */
-#define BRCMS_PROTECTION_CTL_OFF               0
+#define BRCMS_PROTECTION_CTL_OFF       0
 #define BRCMS_PROTECTION_CTL_LOCAL     1
 #define BRCMS_PROTECTION_CTL_OVERLAP   2
 
 /* values for n_protection */
 #define BRCMS_N_PROTECTION_OFF         0
 #define BRCMS_N_PROTECTION_OPTIONAL    1
-#define BRCMS_N_PROTECTION_20IN40              2
+#define BRCMS_N_PROTECTION_20IN40      2
 #define BRCMS_N_PROTECTION_MIXEDMODE   3
 
 /* values for band specific 40MHz capabilities */
-#define BRCMS_N_BW_20ALL                       0
-#define BRCMS_N_BW_40ALL                       1
-#define BRCMS_N_BW_20IN2G_40IN5G               2
+#define BRCMS_N_BW_20ALL               0
+#define BRCMS_N_BW_40ALL               1
+#define BRCMS_N_BW_20IN2G_40IN5G       2
 
 /* bitflags for SGI support (sgi_rx iovar) */
 #define BRCMS_N_SGI_20                 0x01
@@ -282,48 +218,42 @@ static u16 frametype(u32 rspec, u8 mimoframe)
 
 /* defines used by the nrate iovar */
 /* MSC in use,indicates b0-6 holds an mcs */
-#define NRATE_MCS_INUSE        0x00000080
+#define NRATE_MCS_INUSE                        0x00000080
 /* rate/mcs value */
-#define NRATE_RATE_MASK 0x0000007f
+#define NRATE_RATE_MASK                        0x0000007f
 /* stf mode mask: siso, cdd, stbc, sdm */
-#define NRATE_STF_MASK 0x0000ff00
+#define NRATE_STF_MASK                 0x0000ff00
 /* stf mode shift */
-#define NRATE_STF_SHIFT        8
-/* bit indicates override both rate & mode */
-#define NRATE_OVERRIDE 0x80000000
+#define NRATE_STF_SHIFT                        8
 /* bit indicate to override mcs only */
-#define NRATE_OVERRIDE_MCS_ONLY 0x40000000
-#define NRATE_SGI_MASK  0x00800000     /* sgi mode */
-#define NRATE_SGI_SHIFT 23     /* sgi mode */
-#define NRATE_LDPC_CODING 0x00400000   /* bit indicates adv coding in use */
-#define NRATE_LDPC_SHIFT 22    /* ldpc shift */
+#define NRATE_OVERRIDE_MCS_ONLY                0x40000000
+#define NRATE_SGI_MASK                 0x00800000      /* sgi mode */
+#define NRATE_SGI_SHIFT                        23              /* sgi mode */
+#define NRATE_LDPC_CODING              0x00400000      /* adv coding in use */
+#define NRATE_LDPC_SHIFT               22              /* ldpc shift */
 
-#define NRATE_STF_SISO 0       /* stf mode SISO */
-#define NRATE_STF_CDD  1       /* stf mode CDD */
-#define NRATE_STF_STBC 2       /* stf mode STBC */
-#define NRATE_STF_SDM  3       /* stf mode SDM */
+#define NRATE_STF_SISO                 0               /* stf mode SISO */
+#define NRATE_STF_CDD                  1               /* stf mode CDD */
+#define NRATE_STF_STBC                 2               /* stf mode STBC */
+#define NRATE_STF_SDM                  3               /* stf mode SDM */
 
-#define MAX_DMA_SEGS 4
+#define MAX_DMA_SEGS                   4
 
 /* Max # of entries in Tx FIFO based on 4kb page size */
-#define NTXD           256
+#define NTXD                           256
 /* Max # of entries in Rx FIFO based on 4kb page size */
-#define NRXD           256
+#define NRXD                           256
 
 /* try to keep this # rbufs posted to the chip */
-#define        NRXBUFPOST      32
+#define NRXBUFPOST                     32
 
 /* data msg txq hiwat mark */
-#define BRCMS_DATAHIWAT                50
-
-/* bounded rx loops */
-#define RXBND          8 /* max # frames to process in brcms_c_recv() */
-#define TXSBND         8 /* max # tx status to process in wlc_txstatus() */
+#define BRCMS_DATAHIWAT                        50
 
-/*
- * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL.
- */
-#define SSID_FMT_BUF_LEN       ((4 * IEEE80211_MAX_SSID_LEN) + 1)
+/* max # frames to process in brcms_c_recv() */
+#define RXBND                          8
+/* max # tx status to process in wlc_txstatus() */
+#define TXSBND                         8
 
 /* brcmu_format_flags() bit description structure */
 struct brcms_c_bit_desc {
@@ -405,13 +335,6 @@ static const u16 xmtfifo_sz[][NFIFO] = {
        {9, 58, 22, 14, 14, 5},
 };
 
-static const u8 acbitmap2maxprio[] = {
-       PRIO_8021D_BE, PRIO_8021D_BE, PRIO_8021D_BK, PRIO_8021D_BK,
-       PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI, PRIO_8021D_VI,
-       PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO,
-       PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO, PRIO_8021D_VO
-};
-
 #ifdef BCMDBG
 static const char * const fifo_names[] = {
        "AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
@@ -424,6 +347,22 @@ static const char fifo_names[6][0];
 static struct brcms_c_info *wlc_info_dbg = (struct brcms_c_info *) (NULL);
 #endif
 
+/* Find basic rate for a given rate */
+static u8 brcms_basic_rate(struct brcms_c_info *wlc, u32 rspec)
+{
+       if (is_mcs_rate(rspec))
+               return wlc->band->basic_rate[mcs_table[rspec & RSPEC_RATE_MASK]
+                      .leg_ofdm];
+       return wlc->band->basic_rate[rspec & RSPEC_RATE_MASK];
+}
+
+static u16 frametype(u32 rspec, u8 mimoframe)
+{
+       if (is_mcs_rate(rspec))
+               return mimoframe;
+       return is_cck_rate(rspec) ? FT_CCK : FT_OFDM;
+}
+
 /* currently the best mechanism for determining SIFS is the band in use */
 static u16 get_sifs(struct brcms_band *band)
 {
@@ -470,20 +409,6 @@ static int brcms_chspec_bw(u16 chanspec)
        return BRCMS_10_MHZ;
 }
 
-/*
- * return true if Minimum Power Consumption should
- * be entered, false otherwise
- */
-static bool brcms_c_is_non_delay_mpc(struct brcms_c_info *wlc)
-{
-       return false;
-}
-
-static bool brcms_c_ismpc(struct brcms_c_info *wlc)
-{
-       return (wlc->mpc_delay_off == 0) && (brcms_c_is_non_delay_mpc(wlc));
-}
-
 static void brcms_c_bsscfg_mfree(struct brcms_bss_cfg *cfg)
 {
        if (cfg == NULL)
@@ -669,9 +594,8 @@ static void brcms_b_update_slot_timing(struct brcms_hardware *wlc_hw,
  * calculate frame duration of a given rate and length, return
  * time in usec unit
  */
-uint
-brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
-                       u8 preamble_type, uint mac_len)
+static uint brcms_c_calc_frame_time(struct brcms_c_info *wlc, u32 ratespec,
+                                   u8 preamble_type, uint mac_len)
 {
        uint nsyms, dur = 0, Ndps, kNdps;
        uint rate = rspec2rate(ratespec);
@@ -2352,13 +2276,6 @@ void brcms_b_antsel_type_set(struct brcms_hardware *wlc_hw, u8 antsel_type)
        wlc_phy_antsel_type_set(wlc_hw->band->pi, antsel_type);
 }
 
-static void brcms_c_fatal_error(struct brcms_c_info *wlc)
-{
-       wiphy_err(wlc->wiphy, "wl%d: fatal error, reinitializing\n",
-                 wlc->pub->unit);
-       brcms_init(wlc->wl);
-}
-
 static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
 {
        bool fatal = false;
@@ -2414,7 +2331,7 @@ static void brcms_b_fifoerrors(struct brcms_hardware *wlc_hw)
                }
 
                if (fatal) {
-                       brcms_c_fatal_error(wlc_hw->wlc);       /* big hammer */
+                       brcms_fatal_error(wlc_hw->wlc->wl); /* big hammer */
                        break;
                } else
                        W_REG(&regs->intctrlregs[idx].intstatus,
@@ -2479,6 +2396,7 @@ void brcms_c_intrsrestore(struct brcms_c_info *wlc, u32 macintmask)
        W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
 }
 
+/* assumes that the d11 MAC is enabled */
 static void brcms_b_tx_fifo_suspend(struct brcms_hardware *wlc_hw,
                                    uint tx_fifo)
 {
@@ -2535,11 +2453,12 @@ static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
        }
 }
 
-static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags)
+/* precondition: requires the mac core to be enabled */
+static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx)
 {
        static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
 
-       if (on) {
+       if (mute_tx) {
                /* suspend tx fifos */
                brcms_b_tx_fifo_suspend(wlc_hw, TX_DATA_FIFO);
                brcms_b_tx_fifo_suspend(wlc_hw, TX_CTL_FIFO);
@@ -2561,14 +2480,20 @@ static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool on, u32 flags)
                                       wlc_hw->etheraddr);
        }
 
-       wlc_phy_mute_upd(wlc_hw->band->pi, on, flags);
+       wlc_phy_mute_upd(wlc_hw->band->pi, mute_tx, 0);
 
-       if (on)
+       if (mute_tx)
                brcms_c_ucode_mute_override_set(wlc_hw);
        else
                brcms_c_ucode_mute_override_clear(wlc_hw);
 }
 
+void
+brcms_c_mute(struct brcms_c_info *wlc, bool mute_tx)
+{
+       brcms_b_mute(wlc->hw, mute_tx);
+}
+
 /*
  * Read and clear macintmask and macintstatus and intstatus registers.
  * This routine should be called with interrupts off
@@ -3437,8 +3362,7 @@ static void brcms_b_coreinit(struct brcms_c_info *wlc)
 }
 
 void
-static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec,
-                         bool mute) {
+static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) {
        u32 macintmask;
        bool fastclk;
        struct brcms_c_info *wlc = wlc_hw->wlc;
@@ -3463,10 +3387,6 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec,
        /* core-specific initialization */
        brcms_b_coreinit(wlc);
 
-       /* suspend the tx fifos and mute the phy for preism cac time */
-       if (mute)
-               brcms_b_mute(wlc_hw, ON, PHY_MUTE_FOR_PREISM);
-
        /* band-specific inits */
        brcms_b_bsinit(wlc, chanspec);
 
@@ -3979,7 +3899,7 @@ static void brcms_c_set_home_chanspec(struct brcms_c_info *wlc, u16 chanspec)
 
 void
 brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
-                     bool mute, struct txpwr_limits *txpwr)
+                     bool mute_tx, struct txpwr_limits *txpwr)
 {
        uint bandunit;
 
@@ -4005,7 +3925,7 @@ brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
                }
        }
 
-       wlc_phy_initcal_enable(wlc_hw->band->pi, !mute);
+       wlc_phy_initcal_enable(wlc_hw->band->pi, !mute_tx);
 
        if (!wlc_hw->up) {
                if (wlc_hw->clk)
@@ -4017,7 +3937,7 @@ brcms_b_set_chanspec(struct brcms_hardware *wlc_hw, u16 chanspec,
                wlc_phy_txpower_limit_set(wlc_hw->band->pi, txpwr, chanspec);
 
                /* Update muting of the channel */
-               brcms_b_mute(wlc_hw, mute, 0);
+               brcms_b_mute(wlc_hw, mute_tx);
        }
 }
 
@@ -4242,7 +4162,7 @@ void brcms_c_wme_setparams(struct brcms_c_info *wlc, u16 aci,
        }
 }
 
-void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
+static void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
 {
        u16 aci;
        int i_ac;
@@ -4277,17 +4197,6 @@ void brcms_c_edcf_setparams(struct brcms_c_info *wlc, bool suspend)
        }
 }
 
-/* maintain LED behavior in down state */
-static void brcms_c_down_led_upd(struct brcms_c_info *wlc)
-{
-       /*
-        * maintain LEDs while in down state, turn on sbclk if
-        * not available yet. Turn on sbclk if necessary
-        */
-       brcms_b_pllreq(wlc->hw, true, BRCMS_PLLREQ_FLIP);
-       brcms_b_pllreq(wlc->hw, false, BRCMS_PLLREQ_FLIP);
-}
-
 static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
 {
        /* Don't start the timer if HWRADIO feature is disabled */
@@ -4299,28 +4208,6 @@ static void brcms_c_radio_monitor_start(struct brcms_c_info *wlc)
        brcms_add_timer(wlc->radio_timer, TIMER_INTERVAL_RADIOCHK, true);
 }
 
-static void brcms_c_radio_disable(struct brcms_c_info *wlc)
-{
-       if (!wlc->pub->up) {
-               brcms_c_down_led_upd(wlc);
-               return;
-       }
-
-       brcms_c_radio_monitor_start(wlc);
-       brcms_down(wlc->wl);
-}
-
-static void brcms_c_radio_enable(struct brcms_c_info *wlc)
-{
-       if (wlc->pub->up)
-               return;
-
-       if (brcms_deviceremoved(wlc))
-               return;
-
-       brcms_up(wlc->wl);
-}
-
 static bool brcms_c_radio_monitor_stop(struct brcms_c_info *wlc)
 {
        if (!wlc->radio_monitor)
@@ -4343,18 +4230,6 @@ static void brcms_c_radio_hwdisable_upd(struct brcms_c_info *wlc)
                mboolclr(wlc->pub->radio_disabled, WL_RADIO_HW_DISABLE);
 }
 
-/*
- * centralized radio disable/enable function,
- * invoke radio enable/disable after updating hwradio status
- */
-static void brcms_c_radio_upd(struct brcms_c_info *wlc)
-{
-       if (wlc->pub->radio_disabled)
-               brcms_c_radio_disable(wlc);
-       else
-               brcms_c_radio_enable(wlc);
-}
-
 /* update hwradio status and return it */
 bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc)
 {
@@ -4376,12 +4251,7 @@ static void brcms_c_radio_timer(void *arg)
                return;
        }
 
-       /* cap mpc off count */
-       if (wlc->mpc_offcnt < BRCMS_MPC_MAX_DELAYCNT)
-               wlc->mpc_offcnt++;
-
        brcms_c_radio_hwdisable_upd(wlc);
-       brcms_c_radio_upd(wlc);
 }
 
 /* common low-level watchdog code */
@@ -4407,60 +4277,6 @@ static void brcms_b_watchdog(void *arg)
        wlc_phy_watchdog(wlc_hw->band->pi);
 }
 
-static void brcms_c_radio_mpc_upd(struct brcms_c_info *wlc)
-{
-       bool mpc_radio, radio_state;
-
-       /*
-        * Clear the WL_RADIO_MPC_DISABLE bit when mpc feature is disabled
-        * in case the WL_RADIO_MPC_DISABLE bit was set. Stop the radio
-        * monitor also when WL_RADIO_MPC_DISABLE is the only reason that
-        * the radio is going down.
-        */
-       if (!wlc->mpc) {
-               if (!wlc->pub->radio_disabled)
-                       return;
-               mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-               brcms_c_radio_upd(wlc);
-               if (!wlc->pub->radio_disabled)
-                       brcms_c_radio_monitor_stop(wlc);
-               return;
-       }
-
-       /*
-        * sync ismpc logic with WL_RADIO_MPC_DISABLE bit in
-        * wlc->pub->radio_disabled to go ON, always call radio_upd
-        * synchronously to go OFF, postpone radio_upd to later when
-        * context is safe(e.g. watchdog)
-        */
-       radio_state =
-           (mboolisset(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE) ? OFF :
-            ON);
-       mpc_radio = (brcms_c_ismpc(wlc) == true) ? OFF : ON;
-
-       if (radio_state == ON && mpc_radio == OFF)
-               wlc->mpc_delay_off = wlc->mpc_dlycnt;
-       else if (radio_state == OFF && mpc_radio == ON) {
-               mboolclr(wlc->pub->radio_disabled, WL_RADIO_MPC_DISABLE);
-               brcms_c_radio_upd(wlc);
-               if (wlc->mpc_offcnt < BRCMS_MPC_THRESHOLD)
-                       wlc->mpc_dlycnt = BRCMS_MPC_MAX_DELAYCNT;
-               else
-                       wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
-       }
-       /*
-        * Below logic is meant to capture the transition from mpc off
-        * to mpc on for reasons other than wlc->mpc_delay_off keeping
-        * the mpc off. In that case reset wlc->mpc_delay_off to
-        * wlc->mpc_dlycnt, so that we restart the countdown of mpc_delay_off
-        */
-       if ((wlc->prev_non_delay_mpc == false) &&
-           (brcms_c_is_non_delay_mpc(wlc) == true) && wlc->mpc_delay_off)
-               wlc->mpc_delay_off = wlc->mpc_dlycnt;
-
-       wlc->prev_non_delay_mpc = brcms_c_is_non_delay_mpc(wlc);
-}
-
 /* common watchdog code */
 static void brcms_c_watchdog(void *arg)
 {
@@ -4481,21 +4297,7 @@ static void brcms_c_watchdog(void *arg)
        /* increment second count */
        wlc->pub->now++;
 
-       /* delay radio disable */
-       if (wlc->mpc_delay_off) {
-               if (--wlc->mpc_delay_off == 0) {
-                       mboolset(wlc->pub->radio_disabled,
-                                WL_RADIO_MPC_DISABLE);
-                       if (wlc->mpc && brcms_c_ismpc(wlc))
-                               wlc->mpc_offcnt = 0;
-               }
-       }
-
-       /* mpc sync */
-       brcms_c_radio_mpc_upd(wlc);
-       /* radio sync: sw/hw/mpc --> radio_disable/radio_enable */
        brcms_c_radio_hwdisable_upd(wlc);
-       brcms_c_radio_upd(wlc);
        /* if radio is disable, driver may be down, quit here */
        if (wlc->pub->radio_disabled)
                return;
@@ -4599,9 +4401,6 @@ static void brcms_c_info_init(struct brcms_c_info *wlc, int unit)
        /* WME QoS mode is Auto by default */
        wlc->pub->_ampdu = AMPDU_AGG_HOST;
        wlc->pub->bcmerror = 0;
-
-       /* initialize mpc delay */
-       wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
 }
 
 static uint brcms_c_attach_module(struct brcms_c_info *wlc)
@@ -5259,9 +5058,6 @@ static void brcms_c_ap_upd(struct brcms_c_info *wlc)
 {
        /* STA-BSS; short capable */
        wlc->PLCPHdr_override = BRCMS_PLCP_SHORT;
-
-       /* fixup mpc */
-       wlc->mpc = true;
 }
 
 /* Initialize just the hardware when coming out of POR or S3/S5 system states */
@@ -5575,7 +5371,6 @@ uint brcms_c_down(struct brcms_c_info *wlc)
        if (!wlc->pub->up)
                return callbacks;
 
-       /* in between, mpc could try to bring down again.. */
        wlc->going_down = true;
 
        callbacks += brcms_b_bmac_down_prep(wlc->hw);
@@ -6103,7 +5898,6 @@ void brcms_c_print_txdesc(struct d11txh *txh)
 
        u8 *rtsph = txh->RTSPhyHeader;
        struct ieee80211_rts rts = txh->rts_frame;
-       char hexbuf[256];
 
        /* add plcp header along with txh descriptor */
        printk(KERN_DEBUG "Raw TxDesc + plcp header:\n");
@@ -6124,17 +5918,16 @@ void brcms_c_print_txdesc(struct d11txh *txh)
        printk(KERN_DEBUG "XtraFrameTypes: %04x ", xtraft);
        printk(KERN_DEBUG "\n");
 
-       brcmu_format_hex(hexbuf, iv, sizeof(txh->IV));
-       printk(KERN_DEBUG "SecIV:       %s\n", hexbuf);
-       brcmu_format_hex(hexbuf, ra, sizeof(txh->TxFrameRA));
-       printk(KERN_DEBUG "RA:          %s\n", hexbuf);
+       print_hex_dump_bytes("SecIV:", DUMP_PREFIX_OFFSET, iv, sizeof(txh->IV));
+       print_hex_dump_bytes("RA:", DUMP_PREFIX_OFFSET,
+                            ra, sizeof(txh->TxFrameRA));
 
        printk(KERN_DEBUG "Fb FES Time: %04x ", tfestfb);
-       brcmu_format_hex(hexbuf, rtspfb, sizeof(txh->RTSPLCPFallback));
-       printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
+       print_hex_dump_bytes("Fb RTS PLCP:", DUMP_PREFIX_OFFSET,
+                            rtspfb, sizeof(txh->RTSPLCPFallback));
        printk(KERN_DEBUG "RTS DUR: %04x ", rtsdfb);
-       brcmu_format_hex(hexbuf, fragpfb, sizeof(txh->FragPLCPFallback));
-       printk(KERN_DEBUG "PLCP: %s ", hexbuf);
+       print_hex_dump_bytes("PLCP:", DUMP_PREFIX_OFFSET,
+                            fragpfb, sizeof(txh->FragPLCPFallback));
        printk(KERN_DEBUG "DUR: %04x", fragdfb);
        printk(KERN_DEBUG "\n");
 
@@ -6149,18 +5942,18 @@ void brcms_c_print_txdesc(struct d11txh *txh)
        printk(KERN_DEBUG "MaxAggbyte_fb:  %04x\n", mabyte_f);
        printk(KERN_DEBUG "MinByte:     %04x\n", mmbyte);
 
-       brcmu_format_hex(hexbuf, rtsph, sizeof(txh->RTSPhyHeader));
-       printk(KERN_DEBUG "RTS PLCP: %s ", hexbuf);
-       brcmu_format_hex(hexbuf, (u8 *) &rts, sizeof(txh->rts_frame));
-       printk(KERN_DEBUG "RTS Frame: %s", hexbuf);
+       print_hex_dump_bytes("RTS PLCP:", DUMP_PREFIX_OFFSET,
+                            rtsph, sizeof(txh->RTSPhyHeader));
+       print_hex_dump_bytes("RTS Frame:", DUMP_PREFIX_OFFSET,
+                            (u8 *)&rts, sizeof(txh->rts_frame));
        printk(KERN_DEBUG "\n");
 }
 #endif                         /* defined(BCMDBG) */
 
 #if defined(BCMDBG)
-int
+static int
 brcms_c_format_flags(const struct brcms_c_bit_desc *bd, u32 flags, char *buf,
-                  int len)
+                    int len)
 {
        int i;
        char *p = buf;
@@ -8253,12 +8046,6 @@ int brcms_c_get_tx_power(struct brcms_c_info *wlc)
        return (int)(qdbm / BRCMS_TXPWR_DB_FACTOR);
 }
 
-void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc)
-{
-       wlc->mpc = mpc;
-       brcms_c_radio_mpc_upd(wlc);
-}
-
 /* Process received frames */
 /*
  * Return true if more frames need to be processed. false otherwise.
@@ -8328,21 +8115,17 @@ static bool
 brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
 {
        struct sk_buff *p;
-       struct sk_buff *head = NULL;
-       struct sk_buff *tail = NULL;
+       struct sk_buff *next = NULL;
+       struct sk_buff_head recv_frames;
+
        uint n = 0;
        uint bound_limit = bound ? RXBND : -1;
 
        BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit);
-       /* gather received frames */
-       while ((p = dma_rx(wlc_hw->di[fifo]))) {
+       skb_queue_head_init(&recv_frames);
 
-               if (!tail)
-                       head = tail = p;
-               else {
-                       tail->prev = p;
-                       tail = p;
-               }
+       /* gather received frames */
+       while (dma_rx(wlc_hw->di[fifo], &recv_frames)) {
 
                /* !give others some time to run! */
                if (++n >= bound_limit)
@@ -8353,12 +8136,11 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
        dma_rxfill(wlc_hw->di[fifo]);
 
        /* process each frame */
-       while ((p = head) != NULL) {
+       skb_queue_walk_safe(&recv_frames, p, next) {
                struct d11rxhdr_le *rxh_le;
                struct d11rxhdr *rxh;
-               head = head->prev;
-               p->prev = NULL;
 
+               skb_unlink(p, &recv_frames);
                rxh_le = (struct d11rxhdr_le *)p->data;
                rxh = (struct d11rxhdr *)p->data;
 
@@ -8448,8 +8230,7 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
                printk_once("%s : PSM Watchdog, chipid 0x%x, chiprev 0x%x\n",
                                        __func__, wlc_hw->sih->chip,
                                        wlc_hw->sih->chiprev);
-               /* big hammer */
-               brcms_init(wlc->wl);
+               brcms_fatal_error(wlc_hw->wlc->wl);
        }
 
        /* gptimer timeout */
@@ -8470,15 +8251,14 @@ bool brcms_c_dpc(struct brcms_c_info *wlc, bool bounded)
        return wlc->macintstatus != 0;
 
  fatal:
-       brcms_init(wlc->wl);
+       brcms_fatal_error(wlc_hw->wlc->wl);
        return wlc->macintstatus != 0;
 }
 
-void brcms_c_init(struct brcms_c_info *wlc)
+void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx)
 {
        struct d11regs __iomem *regs;
        u16 chanspec;
-       bool mute = false;
 
        BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit);
 
@@ -8494,7 +8274,7 @@ void brcms_c_init(struct brcms_c_info *wlc)
        else
                chanspec = brcms_c_init_chanspec(wlc);
 
-       brcms_b_init(wlc->hw, chanspec, mute);
+       brcms_b_init(wlc->hw, chanspec);
 
        /* update beacon listen interval */
        brcms_c_bcn_li_upd(wlc);
@@ -8560,15 +8340,16 @@ void brcms_c_init(struct brcms_c_info *wlc)
        /* ..now really unleash hell (allow the MAC out of suspend) */
        brcms_c_enable_mac(wlc);
 
+       /* suspend the tx fifos and mute the phy for preism cac time */
+       if (mute_tx)
+               brcms_b_mute(wlc->hw, true);
+
        /* clear tx flow control */
        brcms_c_txflowcontrol_reset(wlc);
 
        /* enable the RF Disable Delay timer */
        W_REG(&wlc->regs->rfdisabledly, RFDISABLE_DEFAULT);
 
-       /* initialize mpc delay */
-       wlc->mpc_delay_off = wlc->mpc_dlycnt = BRCMS_MPC_MIN_DELAYCNT;
-
        /*
         * Initialize WME parameters; if they haven't been set by some other
         * mechanism (IOVar, etc) then read them from the hardware.
@@ -8754,8 +8535,6 @@ brcms_c_attach(struct brcms_info *wl, u16 vendor, u16 device, uint unit,
                brcms_c_ht_update_sgi_rx(wlc, 0);
        }
 
-       /* initialize radio_mpc_disable according to wlc->mpc */
-       brcms_c_radio_mpc_upd(wlc);
        brcms_b_antsel_set(wlc->hw, wlc->asi->antsel_avail);
 
        if (perr)
index c0e0fcf..9a7535d 100644 (file)
@@ -427,11 +427,6 @@ struct brcms_txq_info {
  * bandinit_pending: track band init in auto band.
  * radio_monitor: radio timer is running.
  * going_down: down path intermediate variable.
- * mpc: enable minimum power consumption.
- * mpc_dlycnt: # of watchdog cnt before turn disable radio.
- * mpc_offcnt: # of watchdog cnt that radio is disabled.
- * mpc_delay_off: delay radio disable by # of watchdog cnt.
- * prev_non_delay_mpc: prev state brcms_c_is_non_delay_mpc.
  * wdtimer: timer for watchdog routine.
  * radio_timer: timer for hw radio button monitor routine.
  * monitor: monitor (MPDU sniffing) mode.
@@ -522,12 +517,6 @@ struct brcms_c_info {
        bool radio_monitor;
        bool going_down;
 
-       bool mpc;
-       u8 mpc_dlycnt;
-       u8 mpc_offcnt;
-       u8 mpc_delay_off;
-       u8 prev_non_delay_mpc;
-
        struct brcms_timer *wdtimer;
        struct brcms_timer *radio_timer;
 
index a314925..2faea50 100644 (file)
@@ -112,7 +112,7 @@ static const struct chan_info_basic chan_info_all[] = {
        {216, 50800}
 };
 
-const u8 ofdm_rate_lookup[] = {
+static const u8 ofdm_rate_lookup[] = {
 
        BRCM_RATE_48M,
        BRCM_RATE_24M,
index bea8524..5f9478b 100644 (file)
@@ -774,11 +774,6 @@ struct brcms_phy {
        s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
        u8 nphy_noise_index;
 
-       u8 nphy_txpid2g[PHY_CORE_NUM_2];
-       u8 nphy_txpid5g[PHY_CORE_NUM_2];
-       u8 nphy_txpid5gl[PHY_CORE_NUM_2];
-       u8 nphy_txpid5gh[PHY_CORE_NUM_2];
-
        bool nphy_gain_boost;
        bool nphy_elna_gain_config;
        u16 old_bphy_test;
index cd19c2f..ec9b566 100644 (file)
@@ -29,6 +29,7 @@
 #include "phy_radio.h"
 #include "phyreg_n.h"
 #include "phytbl_n.h"
+#include "soc.h"
 
 #define READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name)        \
        read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
@@ -14417,12 +14418,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
                switch (band_num) {
                case 0:
 
-                       pi->nphy_txpid2g[PHY_CORE_0] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID2GA0);
-                       pi->nphy_txpid2g[PHY_CORE_1] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID2GA1);
                        pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g =
                                (s8) wlapi_getintvar(shim,
                                                     BRCMS_SROM_MAXP2GA0);
@@ -14486,12 +14481,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
                        break;
                case 1:
 
-                       pi->nphy_txpid5g[PHY_CORE_0] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID5GA0);
-                       pi->nphy_txpid5g[PHY_CORE_1] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID5GA1);
                        pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm =
                                (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0);
                        pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm =
@@ -14551,12 +14540,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
                        break;
                case 2:
 
-                       pi->nphy_txpid5gl[0] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID5GLA0);
-                       pi->nphy_txpid5gl[1] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID5GLA1);
                        pi->nphy_pwrctrl_info[0].max_pwr_5gl =
                                (s8) wlapi_getintvar(shim,
                                                     BRCMS_SROM_MAXP5GLA0);
@@ -14615,12 +14598,6 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi)
                        break;
                case 3:
 
-                       pi->nphy_txpid5gh[0] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID5GHA0);
-                       pi->nphy_txpid5gh[1] =
-                               (u8) wlapi_getintvar(shim,
-                                                    BRCMS_SROM_TXPID5GHA1);
                        pi->nphy_pwrctrl_info[0].max_pwr_5gh =
                                (s8) wlapi_getintvar(shim,
                                                     BRCMS_SROM_MAXP5GHA0);
@@ -27994,20 +27971,11 @@ void wlc_phy_txpwr_fixpower_nphy(struct brcms_phy *pi)
                chan_freq_range = wlc_phy_get_chan_freq_range_nphy(pi, 0);
                switch (chan_freq_range) {
                case WL_CHAN_FREQ_RANGE_2G:
-                       txpi[0] = pi->nphy_txpid2g[0];
-                       txpi[1] = pi->nphy_txpid2g[1];
-                       break;
                case WL_CHAN_FREQ_RANGE_5GL:
-                       txpi[0] = pi->nphy_txpid5gl[0];
-                       txpi[1] = pi->nphy_txpid5gl[1];
-                       break;
                case WL_CHAN_FREQ_RANGE_5GM:
-                       txpi[0] = pi->nphy_txpid5g[0];
-                       txpi[1] = pi->nphy_txpid5g[1];
-                       break;
                case WL_CHAN_FREQ_RANGE_5GH:
-                       txpi[0] = pi->nphy_txpid5gh[0];
-                       txpi[1] = pi->nphy_txpid5gh[1];
+                       txpi[0] = 0;
+                       txpi[1] = 0;
                        break;
                default:
                        txpi[0] = txpi[1] = 91;
index 3b36e3a..12ba575 100644 (file)
@@ -23,6 +23,7 @@
 #include "pub.h"
 #include "aiutils.h"
 #include "pmu.h"
+#include "soc.h"
 
 /*
  * external LPO crystal frequency
index 37bb2dc..022523a 100644 (file)
@@ -170,22 +170,6 @@ enum brcms_srom_id {
        BRCMS_SROM_TSSIPOS2G,
        BRCMS_SROM_TSSIPOS5G,
        BRCMS_SROM_TXCHAIN,
-       BRCMS_SROM_TXPID2GA0,
-       BRCMS_SROM_TXPID2GA1,
-       BRCMS_SROM_TXPID2GA2,
-       BRCMS_SROM_TXPID2GA3,
-       BRCMS_SROM_TXPID5GA0,
-       BRCMS_SROM_TXPID5GA1,
-       BRCMS_SROM_TXPID5GA2,
-       BRCMS_SROM_TXPID5GA3,
-       BRCMS_SROM_TXPID5GHA0,
-       BRCMS_SROM_TXPID5GHA1,
-       BRCMS_SROM_TXPID5GHA2,
-       BRCMS_SROM_TXPID5GHA3,
-       BRCMS_SROM_TXPID5GLA0,
-       BRCMS_SROM_TXPID5GLA1,
-       BRCMS_SROM_TXPID5GLA2,
-       BRCMS_SROM_TXPID5GLA3,
        /*
         * per-path identifiers (see srom.c)
         */
@@ -225,10 +209,6 @@ enum brcms_srom_id {
        BRCMS_SROM_PA2GW2A1,
        BRCMS_SROM_PA2GW2A2,
        BRCMS_SROM_PA2GW2A3,
-       BRCMS_SROM_PA2GW3A0,
-       BRCMS_SROM_PA2GW3A1,
-       BRCMS_SROM_PA2GW3A2,
-       BRCMS_SROM_PA2GW3A3,
        BRCMS_SROM_PA5GHW0A0,
        BRCMS_SROM_PA5GHW0A1,
        BRCMS_SROM_PA5GHW0A2,
@@ -241,10 +221,6 @@ enum brcms_srom_id {
        BRCMS_SROM_PA5GHW2A1,
        BRCMS_SROM_PA5GHW2A2,
        BRCMS_SROM_PA5GHW2A3,
-       BRCMS_SROM_PA5GHW3A0,
-       BRCMS_SROM_PA5GHW3A1,
-       BRCMS_SROM_PA5GHW3A2,
-       BRCMS_SROM_PA5GHW3A3,
        BRCMS_SROM_PA5GLW0A0,
        BRCMS_SROM_PA5GLW0A1,
        BRCMS_SROM_PA5GLW0A2,
@@ -257,10 +233,6 @@ enum brcms_srom_id {
        BRCMS_SROM_PA5GLW2A1,
        BRCMS_SROM_PA5GLW2A2,
        BRCMS_SROM_PA5GLW2A3,
-       BRCMS_SROM_PA5GLW3A0,
-       BRCMS_SROM_PA5GLW3A1,
-       BRCMS_SROM_PA5GLW3A2,
-       BRCMS_SROM_PA5GLW3A3,
        BRCMS_SROM_PA5GW0A0,
        BRCMS_SROM_PA5GW0A1,
        BRCMS_SROM_PA5GW0A2,
@@ -273,10 +245,6 @@ enum brcms_srom_id {
        BRCMS_SROM_PA5GW2A1,
        BRCMS_SROM_PA5GW2A2,
        BRCMS_SROM_PA5GW2A3,
-       BRCMS_SROM_PA5GW3A0,
-       BRCMS_SROM_PA5GW3A1,
-       BRCMS_SROM_PA5GW3A2,
-       BRCMS_SROM_PA5GW3A3,
 };
 
 #define        BRCMS_NUMRATES  16      /* max # of rates in a rateset */
@@ -572,7 +540,7 @@ extern int brcms_c_up(struct brcms_c_info *wlc);
 extern uint brcms_c_down(struct brcms_c_info *wlc);
 
 extern bool brcms_c_chipmatch(u16 vendor, u16 device);
-extern void brcms_c_init(struct brcms_c_info *wlc);
+extern void brcms_c_init(struct brcms_c_info *wlc, bool mute_tx);
 extern void brcms_c_reset(struct brcms_c_info *wlc);
 
 extern void brcms_c_intrson(struct brcms_c_info *wlc);
@@ -628,7 +596,7 @@ extern void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc,
                                        u8 interval);
 extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr);
 extern int brcms_c_get_tx_power(struct brcms_c_info *wlc);
-extern void brcms_c_set_radio_mpc(struct brcms_c_info *wlc, bool mpc);
 extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc);
+extern void brcms_c_mute(struct brcms_c_info *wlc, bool on);
 
 #endif                         /* _BRCM_PUB_H_ */
index e7b9dc2..980d578 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "types.h"
 #include "d11.h"
+#include "phy_hal.h"
 
 extern const u8 rate_info[];
 extern const struct brcms_c_rateset cck_ofdm_mimo_rates;
@@ -198,11 +199,9 @@ static inline u8 cck_rspec(u8 cck)
 
 /* Convert encoded rate value in plcp header to numerical rates in 500 KHz
  * increments */
-extern const u8 ofdm_rate_lookup[];
-
 static inline u8 ofdm_phy2mac_rate(u8 rlpt)
 {
-       return ofdm_rate_lookup[rlpt & 0x7];
+       return wlc_phy_get_ofdm_rate_lookup()[rlpt & 0x7];
 }
 
 static inline u8 cck_phy2mac_rate(u8 signal)
index 99f7910..0539a6a 100644 (file)
@@ -28,6 +28,7 @@
 #include "aiutils.h"
 #include "otp.h"
 #include "srom.h"
+#include "soc.h"
 
 /*
  * SROM CRC8 polynomial value:
@@ -62,9 +63,6 @@
 #define        SROM_MACHI_ET1          42
 #define        SROM_MACMID_ET1         43
 #define        SROM_MACLO_ET1          44
-#define        SROM3_MACHI             37
-#define        SROM3_MACMID            38
-#define        SROM3_MACLO             39
 
 #define        SROM_BXARSSI2G          40
 #define        SROM_BXARSSI5G          41
 
 #define        SROM_BFL                57
 #define        SROM_BFL2               28
-#define        SROM3_BFL2              61
 
 #define        SROM_AG10               58
 
 
 #define        SROM_OPO                60
 
-#define        SROM3_LEDDC             62
-
 #define        SROM_CRCREV             63
 
-/* SROM Rev 4: Reallocate the software part of the srom to accommodate
- * MIMO features. It assumes up to two PCIE functions and 440 bytes
- * of usable srom i.e. the usable storage in chips with OTP that
- * implements hardware redundancy.
- */
-
 #define        SROM4_WORDS             220
 
-#define        SROM4_SIGN              32
-#define        SROM4_SIGNATURE         0x5372
-
-#define        SROM4_BREV              33
-
-#define        SROM4_BFL0              34
-#define        SROM4_BFL1              35
-#define        SROM4_BFL2              36
-#define        SROM4_BFL3              37
-#define        SROM5_BFL0              37
-#define        SROM5_BFL1              38
-#define        SROM5_BFL2              39
-#define        SROM5_BFL3              40
-
-#define        SROM4_MACHI             38
-#define        SROM4_MACMID            39
-#define        SROM4_MACLO             40
-#define        SROM5_MACHI             41
-#define        SROM5_MACMID            42
-#define        SROM5_MACLO             43
-
-#define        SROM4_CCODE             41
-#define        SROM4_REGREV            42
-#define        SROM5_CCODE             34
-#define        SROM5_REGREV            35
-
-#define        SROM4_LEDBH10           43
-#define        SROM4_LEDBH32           44
-#define        SROM5_LEDBH10           59
-#define        SROM5_LEDBH32           60
-
-#define        SROM4_LEDDC             45
-#define        SROM5_LEDDC             45
-
-#define        SROM4_AA                46
-
-#define        SROM4_AG10              47
-#define        SROM4_AG32              48
-
-#define        SROM4_TXPID2G           49
-#define        SROM4_TXPID5G           51
-#define        SROM4_TXPID5GL          53
-#define        SROM4_TXPID5GH          55
-
-#define SROM4_TXRXC            61
 #define SROM4_TXCHAIN_MASK     0x000f
-#define SROM4_TXCHAIN_SHIFT    0
 #define SROM4_RXCHAIN_MASK     0x00f0
-#define SROM4_RXCHAIN_SHIFT    4
 #define SROM4_SWITCH_MASK      0xff00
-#define SROM4_SWITCH_SHIFT     8
 
 /* Per-path fields */
 #define        MAX_PATH_SROM           4
-#define        SROM4_PATH0             64
-#define        SROM4_PATH1             87
-#define        SROM4_PATH2             110
-#define        SROM4_PATH3             133
-
-#define        SROM4_2G_ITT_MAXP       0
-#define        SROM4_2G_PA             1
-#define        SROM4_5G_ITT_MAXP       5
-#define        SROM4_5GLH_MAXP         6
-#define        SROM4_5G_PA             7
-#define        SROM4_5GL_PA            11
-#define        SROM4_5GH_PA            15
-
-/* All the miriad power offsets */
-#define        SROM4_2G_CCKPO          156
-#define        SROM4_2G_OFDMPO         157
-#define        SROM4_5G_OFDMPO         159
-#define        SROM4_5GL_OFDMPO        161
-#define        SROM4_5GH_OFDMPO        163
-#define        SROM4_2G_MCSPO          165
-#define        SROM4_5G_MCSPO          173
-#define        SROM4_5GL_MCSPO         181
-#define        SROM4_5GH_MCSPO         189
-#define        SROM4_CDDPO             197
-#define        SROM4_STBCPO            198
-#define        SROM4_BW40PO            199
-#define        SROM4_BWDUPPO           200
 
 #define        SROM4_CRCREV            219
 
@@ -424,103 +338,32 @@ struct brcms_varbuf {
 static const struct brcms_sromvar pci_sromvars[] = {
        {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID,
         0xffff},
-       {BRCMS_SROM_BOARDREV, 0x0000000e, SRFL_PRHEX, SROM_AABREV,
-        SROM_BR_MASK},
-       {BRCMS_SROM_BOARDREV, 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff},
        {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS, 0x00000002, SRFL_PRHEX, SROM_BFL, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS, 0x00000004, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM_BFL2, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS, 0x00000008, SRFL_PRHEX | SRFL_MORE, SROM_BFL,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM3_BFL2, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL0,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM4_BFL1, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL0,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM5_BFL1, 0xffff},
        {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0,
         0xffff},
        {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS2, 0x00000010, SRFL_PRHEX | SRFL_MORE, SROM4_BFL2,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM4_BFL3, 0xffff},
-       {BRCMS_SROM_BOARDFLAGS2, 0x000000e0, SRFL_PRHEX | SRFL_MORE, SROM5_BFL2,
-        0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM5_BFL3, 0xffff},
        {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2,
         0xffff},
        {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff},
        {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff},
-       {BRCMS_SROM_BOARDNUM, 0x00000006, 0, SROM_MACLO_IL0, 0xffff},
-       {BRCMS_SROM_BOARDNUM, 0x00000008, 0, SROM3_MACLO, 0xffff},
-       {BRCMS_SROM_BOARDNUM, 0x00000010, 0, SROM4_MACLO, 0xffff},
-       {BRCMS_SROM_BOARDNUM, 0x000000e0, 0, SROM5_MACLO, 0xffff},
        {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff},
-       {BRCMS_SROM_CC, 0x00000002, 0, SROM_AABREV, SROM_CC_MASK},
-       {BRCMS_SROM_REGREV, 0x00000008, 0, SROM_OPO, 0xff00},
-       {BRCMS_SROM_REGREV, 0x00000010, 0, SROM4_REGREV, 0x00ff},
-       {BRCMS_SROM_REGREV, 0x000000e0, 0, SROM5_REGREV, 0x00ff},
        {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff},
-       {BRCMS_SROM_LEDBH0, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0x00ff},
-       {BRCMS_SROM_LEDBH1, 0x0000000e, SRFL_NOFFS, SROM_LEDBH10, 0xff00},
-       {BRCMS_SROM_LEDBH2, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0x00ff},
-       {BRCMS_SROM_LEDBH3, 0x0000000e, SRFL_NOFFS, SROM_LEDBH32, 0xff00},
-       {BRCMS_SROM_LEDBH0, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0x00ff},
-       {BRCMS_SROM_LEDBH1, 0x00000010, SRFL_NOFFS, SROM4_LEDBH10, 0xff00},
-       {BRCMS_SROM_LEDBH2, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0x00ff},
-       {BRCMS_SROM_LEDBH3, 0x00000010, SRFL_NOFFS, SROM4_LEDBH32, 0xff00},
-       {BRCMS_SROM_LEDBH0, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0x00ff},
-       {BRCMS_SROM_LEDBH1, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH10, 0xff00},
-       {BRCMS_SROM_LEDBH2, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0x00ff},
-       {BRCMS_SROM_LEDBH3, 0x000000e0, SRFL_NOFFS, SROM5_LEDBH32, 0xff00},
        {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff},
        {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00},
        {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff},
        {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00},
-       {BRCMS_SROM_PA0B0, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB0, 0xffff},
-       {BRCMS_SROM_PA0B1, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB1, 0xffff},
-       {BRCMS_SROM_PA0B2, 0x0000000e, SRFL_PRHEX, SROM_WL0PAB2, 0xffff},
-       {BRCMS_SROM_PA0ITSSIT, 0x0000000e, 0, SROM_ITT, 0x00ff},
-       {BRCMS_SROM_PA0MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0x00ff},
        {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff},
        {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff},
        {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff},
        {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00},
        {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff},
-       {BRCMS_SROM_OPO, 0x0000000c, 0, SROM_OPO, 0x00ff},
        {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff},
-       {BRCMS_SROM_AA2G, 0x0000000e, 0, SROM_AABREV, SROM_AA0_MASK},
-       {BRCMS_SROM_AA2G, 0x000000f0, 0, SROM4_AA, 0x00ff},
        {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff},
-       {BRCMS_SROM_AA5G, 0x0000000e, 0, SROM_AABREV, SROM_AA1_MASK},
-       {BRCMS_SROM_AA5G, 0x000000f0, 0, SROM4_AA, 0xff00},
        {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00},
-       {BRCMS_SROM_AG0, 0x0000000e, 0, SROM_AG10, 0x00ff},
-       {BRCMS_SROM_AG1, 0x0000000e, 0, SROM_AG10, 0xff00},
-       {BRCMS_SROM_AG0, 0x000000f0, 0, SROM4_AG10, 0x00ff},
-       {BRCMS_SROM_AG1, 0x000000f0, 0, SROM4_AG10, 0xff00},
-       {BRCMS_SROM_AG2, 0x000000f0, 0, SROM4_AG32, 0x00ff},
-       {BRCMS_SROM_AG3, 0x000000f0, 0, SROM4_AG32, 0xff00},
        {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff},
        {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00},
        {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff},
        {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00},
-       {BRCMS_SROM_PA1B0, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB0, 0xffff},
-       {BRCMS_SROM_PA1B1, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB1, 0xffff},
-       {BRCMS_SROM_PA1B2, 0x0000000e, SRFL_PRHEX, SROM_WL1PAB2, 0xffff},
-       {BRCMS_SROM_PA1LOB0, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB0, 0xffff},
-       {BRCMS_SROM_PA1LOB1, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB1, 0xffff},
-       {BRCMS_SROM_PA1LOB2, 0x0000000c, SRFL_PRHEX, SROM_WL1LPAB2, 0xffff},
-       {BRCMS_SROM_PA1HIB0, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB0, 0xffff},
-       {BRCMS_SROM_PA1HIB1, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB1, 0xffff},
-       {BRCMS_SROM_PA1HIB2, 0x0000000c, SRFL_PRHEX, SROM_WL1HPAB2, 0xffff},
-       {BRCMS_SROM_PA1ITSSIT, 0x0000000e, 0, SROM_ITT, 0xff00},
-       {BRCMS_SROM_PA1MAXPWR, 0x0000000e, 0, SROM_WL10MAXP, 0xff00},
-       {BRCMS_SROM_PA1LOMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0xff00},
-       {BRCMS_SROM_PA1HIMAXPWR, 0x0000000c, 0, SROM_WL1LHMAXP, 0x00ff},
        {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff},
        {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff},
        {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff},
@@ -534,40 +377,20 @@ static const struct brcms_sromvar pci_sromvars[] = {
        {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff},
        {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00},
        {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff},
-       {BRCMS_SROM_BXA2G, 0x00000008, 0, SROM_BXARSSI2G, 0x1800},
-       {BRCMS_SROM_RSSISAV2G, 0x00000008, 0, SROM_BXARSSI2G, 0x0700},
-       {BRCMS_SROM_RSSISMC2G, 0x00000008, 0, SROM_BXARSSI2G, 0x00f0},
-       {BRCMS_SROM_RSSISMF2G, 0x00000008, 0, SROM_BXARSSI2G, 0x000f},
        {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800},
        {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700},
        {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0},
        {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f},
-       {BRCMS_SROM_BXA5G, 0x00000008, 0, SROM_BXARSSI5G, 0x1800},
-       {BRCMS_SROM_RSSISAV5G, 0x00000008, 0, SROM_BXARSSI5G, 0x0700},
-       {BRCMS_SROM_RSSISMC5G, 0x00000008, 0, SROM_BXARSSI5G, 0x00f0},
-       {BRCMS_SROM_RSSISMF5G, 0x00000008, 0, SROM_BXARSSI5G, 0x000f},
        {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800},
        {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700},
        {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0},
        {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f},
-       {BRCMS_SROM_TRI2G, 0x00000008, 0, SROM_TRI52G, 0x00ff},
-       {BRCMS_SROM_TRI5G, 0x00000008, 0, SROM_TRI52G, 0xff00},
-       {BRCMS_SROM_TRI5GL, 0x00000008, 0, SROM_TRI5GHL, 0x00ff},
-       {BRCMS_SROM_TRI5GH, 0x00000008, 0, SROM_TRI5GHL, 0xff00},
        {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff},
        {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00},
        {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff},
        {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00},
-       {BRCMS_SROM_RXPO2G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0x00ff},
-       {BRCMS_SROM_RXPO5G, 0x00000008, SRFL_PRSIGN, SROM_RXPO52G, 0xff00},
        {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff},
        {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00},
-       {BRCMS_SROM_TXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
-        SROM4_TXCHAIN_MASK},
-       {BRCMS_SROM_RXCHAIN, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
-        SROM4_RXCHAIN_MASK},
-       {BRCMS_SROM_ANTSWITCH, 0x000000f0, SRFL_NOFFS, SROM4_TXRXC,
-        SROM4_SWITCH_MASK},
        {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
         SROM4_TXCHAIN_MASK},
        {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC,
@@ -594,43 +417,11 @@ static const struct brcms_sromvar pci_sromvars[] = {
         SROM8_FEM_ANTSWLUT_MASK},
        {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00},
        {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff},
-       {BRCMS_SROM_TXPID2GA0, 0x000000f0, 0, SROM4_TXPID2G, 0x00ff},
-       {BRCMS_SROM_TXPID2GA1, 0x000000f0, 0, SROM4_TXPID2G, 0xff00},
-       {BRCMS_SROM_TXPID2GA2, 0x000000f0, 0, SROM4_TXPID2G + 1, 0x00ff},
-       {BRCMS_SROM_TXPID2GA3, 0x000000f0, 0, SROM4_TXPID2G + 1, 0xff00},
-       {BRCMS_SROM_TXPID5GA0, 0x000000f0, 0, SROM4_TXPID5G, 0x00ff},
-       {BRCMS_SROM_TXPID5GA1, 0x000000f0, 0, SROM4_TXPID5G, 0xff00},
-       {BRCMS_SROM_TXPID5GA2, 0x000000f0, 0, SROM4_TXPID5G + 1, 0x00ff},
-       {BRCMS_SROM_TXPID5GA3, 0x000000f0, 0, SROM4_TXPID5G + 1, 0xff00},
-       {BRCMS_SROM_TXPID5GLA0, 0x000000f0, 0, SROM4_TXPID5GL, 0x00ff},
-       {BRCMS_SROM_TXPID5GLA1, 0x000000f0, 0, SROM4_TXPID5GL, 0xff00},
-       {BRCMS_SROM_TXPID5GLA2, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0x00ff},
-       {BRCMS_SROM_TXPID5GLA3, 0x000000f0, 0, SROM4_TXPID5GL + 1, 0xff00},
-       {BRCMS_SROM_TXPID5GHA0, 0x000000f0, 0, SROM4_TXPID5GH, 0x00ff},
-       {BRCMS_SROM_TXPID5GHA1, 0x000000f0, 0, SROM4_TXPID5GH, 0xff00},
-       {BRCMS_SROM_TXPID5GHA2, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0x00ff},
-       {BRCMS_SROM_TXPID5GHA3, 0x000000f0, 0, SROM4_TXPID5GH + 1, 0xff00},
-
-       {BRCMS_SROM_CCODE, 0x0000000f, SRFL_CCODE, SROM_CCODE, 0xffff},
-       {BRCMS_SROM_CCODE, 0x00000010, SRFL_CCODE, SROM4_CCODE, 0xffff},
-       {BRCMS_SROM_CCODE, 0x000000e0, SRFL_CCODE, SROM5_CCODE, 0xffff},
+
        {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff},
        {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff},
-       {BRCMS_SROM_MACADDR, 0x000000e0, SRFL_ETHADDR, SROM5_MACHI, 0xffff},
-       {BRCMS_SROM_MACADDR, 0x00000010, SRFL_ETHADDR, SROM4_MACHI, 0xffff},
-       {BRCMS_SROM_MACADDR, 0x00000008, SRFL_ETHADDR, SROM3_MACHI, 0xffff},
-       {BRCMS_SROM_IL0MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_IL0,
-        0xffff},
-       {BRCMS_SROM_ET1MACADDR, 0x00000007, SRFL_ETHADDR, SROM_MACHI_ET1,
-        0xffff},
        {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC,
         0xffff},
-       {BRCMS_SROM_LEDDC, 0x000000e0, SRFL_NOFFS | SRFL_LEDDC, SROM5_LEDDC,
-        0xffff},
-       {BRCMS_SROM_LEDDC, 0x00000010, SRFL_NOFFS | SRFL_LEDDC, SROM4_LEDDC,
-        0xffff},
-       {BRCMS_SROM_LEDDC, 0x00000008, SRFL_NOFFS | SRFL_LEDDC, SROM3_LEDDC,
-        0xffff},
        {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
         0x01ff},
        {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS,
@@ -650,16 +441,7 @@ static const struct brcms_sromvar pci_sromvars[] = {
        {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA,
         0x00ff},
 
-       {BRCMS_SROM_CCK2GPO, 0x000000f0, 0, SROM4_2G_CCKPO, 0xffff},
        {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff},
-       {BRCMS_SROM_OFDM2GPO, 0x000000f0, SRFL_MORE, SROM4_2G_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM4_2G_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_OFDM5GPO, 0x000000f0, SRFL_MORE, SROM4_5G_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM4_5G_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_OFDM5GLPO, 0x000000f0, SRFL_MORE, SROM4_5GL_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM4_5GL_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_OFDM5GHPO, 0x000000f0, SRFL_MORE, SROM4_5GH_OFDMPO, 0xffff},
-       {BRCMS_SROM_CONT, 0, 0, SROM4_5GH_OFDMPO + 1, 0xffff},
        {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff},
        {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff},
        {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff},
@@ -668,38 +450,6 @@ static const struct brcms_sromvar pci_sromvars[] = {
        {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff},
        {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff},
        {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff},
-       {BRCMS_SROM_MCS2GPO0, 0x000000f0, 0, SROM4_2G_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS2GPO1, 0x000000f0, 0, SROM4_2G_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS2GPO2, 0x000000f0, 0, SROM4_2G_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS2GPO3, 0x000000f0, 0, SROM4_2G_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS2GPO4, 0x000000f0, 0, SROM4_2G_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS2GPO5, 0x000000f0, 0, SROM4_2G_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS2GPO6, 0x000000f0, 0, SROM4_2G_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS2GPO7, 0x000000f0, 0, SROM4_2G_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_MCS5GPO0, 0x000000f0, 0, SROM4_5G_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS5GPO1, 0x000000f0, 0, SROM4_5G_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS5GPO2, 0x000000f0, 0, SROM4_5G_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS5GPO3, 0x000000f0, 0, SROM4_5G_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS5GPO4, 0x000000f0, 0, SROM4_5G_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS5GPO5, 0x000000f0, 0, SROM4_5G_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS5GPO6, 0x000000f0, 0, SROM4_5G_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS5GPO7, 0x000000f0, 0, SROM4_5G_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_MCS5GLPO0, 0x000000f0, 0, SROM4_5GL_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS5GLPO1, 0x000000f0, 0, SROM4_5GL_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS5GLPO2, 0x000000f0, 0, SROM4_5GL_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS5GLPO3, 0x000000f0, 0, SROM4_5GL_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS5GLPO4, 0x000000f0, 0, SROM4_5GL_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS5GLPO5, 0x000000f0, 0, SROM4_5GL_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS5GLPO6, 0x000000f0, 0, SROM4_5GL_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS5GLPO7, 0x000000f0, 0, SROM4_5GL_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_MCS5GHPO0, 0x000000f0, 0, SROM4_5GH_MCSPO, 0xffff},
-       {BRCMS_SROM_MCS5GHPO1, 0x000000f0, 0, SROM4_5GH_MCSPO + 1, 0xffff},
-       {BRCMS_SROM_MCS5GHPO2, 0x000000f0, 0, SROM4_5GH_MCSPO + 2, 0xffff},
-       {BRCMS_SROM_MCS5GHPO3, 0x000000f0, 0, SROM4_5GH_MCSPO + 3, 0xffff},
-       {BRCMS_SROM_MCS5GHPO4, 0x000000f0, 0, SROM4_5GH_MCSPO + 4, 0xffff},
-       {BRCMS_SROM_MCS5GHPO5, 0x000000f0, 0, SROM4_5GH_MCSPO + 5, 0xffff},
-       {BRCMS_SROM_MCS5GHPO6, 0x000000f0, 0, SROM4_5GH_MCSPO + 6, 0xffff},
-       {BRCMS_SROM_MCS5GHPO7, 0x000000f0, 0, SROM4_5GH_MCSPO + 7, 0xffff},
        {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff},
        {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff},
        {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff},
@@ -732,10 +482,6 @@ static const struct brcms_sromvar pci_sromvars[] = {
        {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff},
        {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff},
        {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff},
-       {BRCMS_SROM_CDDPO, 0x000000f0, 0, SROM4_CDDPO, 0xffff},
-       {BRCMS_SROM_STBCPO, 0x000000f0, 0, SROM4_STBCPO, 0xffff},
-       {BRCMS_SROM_BW40PO, 0x000000f0, 0, SROM4_BW40PO, 0xffff},
-       {BRCMS_SROM_BWDUPPO, 0x000000f0, 0, SROM4_BWDUPPO, 0xffff},
        {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff},
        {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff},
        {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff},
@@ -811,34 +557,6 @@ static const struct brcms_sromvar pci_sromvars[] = {
 };
 
 static const struct brcms_sromvar perpath_pci_sromvars[] = {
-       {BRCMS_SROM_MAXP2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0x00ff},
-       {BRCMS_SROM_ITT2GA0, 0x000000f0, 0, SROM4_2G_ITT_MAXP, 0xff00},
-       {BRCMS_SROM_ITT5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0xff00},
-       {BRCMS_SROM_PA2GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA, 0xffff},
-       {BRCMS_SROM_PA2GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 1, 0xffff},
-       {BRCMS_SROM_PA2GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 2, 0xffff},
-       {BRCMS_SROM_PA2GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_2G_PA + 3, 0xffff},
-       {BRCMS_SROM_MAXP5GA0, 0x000000f0, 0, SROM4_5G_ITT_MAXP, 0x00ff},
-       {BRCMS_SROM_MAXP5GHA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0x00ff},
-       {BRCMS_SROM_MAXP5GLA0, 0x000000f0, 0, SROM4_5GLH_MAXP, 0xff00},
-       {BRCMS_SROM_PA5GW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA, 0xffff},
-       {BRCMS_SROM_PA5GW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 1, 0xffff},
-       {BRCMS_SROM_PA5GW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 2, 0xffff},
-       {BRCMS_SROM_PA5GW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5G_PA + 3, 0xffff},
-       {BRCMS_SROM_PA5GLW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA, 0xffff},
-       {BRCMS_SROM_PA5GLW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 1,
-        0xffff},
-       {BRCMS_SROM_PA5GLW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 2,
-        0xffff},
-       {BRCMS_SROM_PA5GLW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GL_PA + 3,
-        0xffff},
-       {BRCMS_SROM_PA5GHW0A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA, 0xffff},
-       {BRCMS_SROM_PA5GHW1A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 1,
-        0xffff},
-       {BRCMS_SROM_PA5GHW2A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 2,
-        0xffff},
-       {BRCMS_SROM_PA5GHW3A0, 0x000000f0, SRFL_PRHEX, SROM4_5GH_PA + 3,
-        0xffff},
        {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff},
        {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00},
        {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00},
@@ -868,24 +586,17 @@ static const struct brcms_sromvar perpath_pci_sromvars[] = {
  * shared between devices. */
 static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE];
 
-static u16 __iomem *
+static u8 __iomem *
 srom_window_address(struct si_pub *sih, u8 __iomem *curmap)
 {
        if (sih->ccrev < 32)
-               return (u16 __iomem *)(curmap + PCI_BAR0_SPROM_OFFSET);
+               return curmap + PCI_BAR0_SPROM_OFFSET;
        if (sih->cccaps & CC_CAP_SROM)
-               return (u16 __iomem *)
-                      (curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP);
+               return curmap + PCI_16KB0_CCREGS_OFFSET + CC_SROM_OTP;
 
        return NULL;
 }
 
-/* Parse SROM and create name=value pairs. 'srom' points to
- * the SROM word array. 'off' specifies the offset of the
- * first word 'srom' points to, which should be either 0 or
- * SROM3_SWRG_OFF (full SROM or software region).
- */
-
 static uint mask_shift(u16 mask)
 {
        uint i;
@@ -906,18 +617,16 @@ static uint mask_width(u16 mask)
        return 0;
 }
 
-static inline void ltoh16_buf(u16 *buf, unsigned int size)
+static inline void le16_to_cpu_buf(u16 *buf, uint nwords)
 {
-       size /= 2;
-       while (size--)
-               *(buf + size) = le16_to_cpu(*(__le16 *)(buf + size));
+       while (nwords--)
+               *(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords));
 }
 
-static inline void htol16_buf(u16 *buf, unsigned int size)
+static inline void cpu_to_le16_buf(u16 *buf, uint nwords)
 {
-       size /= 2;
-       while (size--)
-               *(__le16 *)(buf + size) = cpu_to_le16(*(buf + size));
+       while (nwords--)
+               *(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords));
 }
 
 /*
@@ -934,6 +643,9 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
        uint width;
        uint flags;
        u32 sr = (1 << sromrev);
+       uint p;
+       uint pb =  SROM8_PATH0;
+       const uint psz = SROM8_PATH1 - SROM8_PATH0;
 
        /* first store the srom revision */
        entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
@@ -1031,47 +743,34 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
                list_add(&entry->var_list, var_list);
        }
 
-       if (sromrev >= 4) {
-               /* Do per-path variables */
-               uint p, pb, psz;
-
-               if (sromrev >= 8) {
-                       pb = SROM8_PATH0;
-                       psz = SROM8_PATH1 - SROM8_PATH0;
-               } else {
-                       pb = SROM4_PATH0;
-                       psz = SROM4_PATH1 - SROM4_PATH0;
-               }
-
-               for (p = 0; p < MAX_PATH_SROM; p++) {
-                       for (srv = perpath_pci_sromvars;
-                            srv->varid != BRCMS_SROM_NULL; srv++) {
-                               if ((srv->revmask & sr) == 0)
-                                       continue;
+       for (p = 0; p < MAX_PATH_SROM; p++) {
+               for (srv = perpath_pci_sromvars;
+                    srv->varid != BRCMS_SROM_NULL; srv++) {
+                       if ((srv->revmask & sr) == 0)
+                               continue;
 
-                               if (srv->flags & SRFL_NOVAR)
-                                       continue;
+                       if (srv->flags & SRFL_NOVAR)
+                               continue;
 
-                               w = srom[pb + srv->off];
-                               val = (w & srv->mask) >> mask_shift(srv->mask);
-                               width = mask_width(srv->mask);
+                       w = srom[pb + srv->off];
+                       val = (w & srv->mask) >> mask_shift(srv->mask);
+                       width = mask_width(srv->mask);
 
-                               /* Cheating: no per-path var is more than
-                                * 1 word */
-                               if ((srv->flags & SRFL_NOFFS)
-                                   && ((int)val == (1 << width) - 1))
-                                       continue;
+                       /* Cheating: no per-path var is more than
+                        * 1 word */
+                       if ((srv->flags & SRFL_NOFFS)
+                           && ((int)val == (1 << width) - 1))
+                               continue;
 
-                               entry =
-                                   kzalloc(sizeof(struct brcms_srom_list_head),
-                                           GFP_KERNEL);
-                               entry->varid = srv->varid+p;
-                               entry->var_type = BRCMS_SROM_UNUMBER;
-                               entry->uval = val;
-                               list_add(&entry->var_list, var_list);
-                       }
-                       pb += psz;
+                       entry =
+                           kzalloc(sizeof(struct brcms_srom_list_head),
+                                   GFP_KERNEL);
+                       entry->varid = srv->varid+p;
+                       entry->var_type = BRCMS_SROM_UNUMBER;
+                       entry->uval = val;
+                       list_add(&entry->var_list, var_list);
                }
+               pb += psz;
        }
 }
 
@@ -1080,41 +779,38 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
  * Return 0 on success, nonzero on error.
  */
 static int
-sprom_read_pci(struct si_pub *sih, u16 __iomem *sprom, uint wordoff,
+sprom_read_pci(struct si_pub *sih, u8 __iomem *sprom, uint wordoff,
               u16 *buf, uint nwords, bool check_crc)
 {
        int err = 0;
        uint i;
+       u8 *bbuf = (u8 *)buf; /* byte buffer */
+       uint nbytes = nwords << 1;
 
-       /* read the sprom */
-       for (i = 0; i < nwords; i++)
-               buf[i] = R_REG(&sprom[wordoff + i]);
-
-       if (check_crc) {
+       /* read the sprom in bytes */
+       for (i = 0; i < nbytes; i++)
+               bbuf[i] = readb(sprom+i);
 
-               if (buf[0] == 0xffff)
-                       /*
-                        * The hardware thinks that an srom that starts with
-                        * 0xffff is blank, regardless of the rest of the
-                        * content, so declare it bad.
-                        */
-                       return -ENODATA;
-
-               /* fixup the endianness so crc8 will pass */
-               htol16_buf(buf, nwords * 2);
-               if (crc8(brcms_srom_crc8_table, (u8 *) buf, nwords * 2,
-                        CRC8_INIT_VALUE) !=
-                        CRC8_GOOD_VALUE(brcms_srom_crc8_table))
-                       /* DBG only pci always read srom4 first, then srom8/9 */
-                       err = -EIO;
+       if (buf[0] == 0xffff)
+               /*
+                * The hardware thinks that an srom that starts with
+                * 0xffff is blank, regardless of the rest of the
+                * content, so declare it bad.
+                */
+               return -ENODATA;
 
+       if (check_crc &&
+           crc8(brcms_srom_crc8_table, bbuf, nbytes, CRC8_INIT_VALUE) !=
+                CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+               err = -EIO;
+       else
                /* now correct the endianness of the byte array */
-               ltoh16_buf(buf, nwords * 2);
-       }
+               le16_to_cpu_buf(buf, nwords);
+
        return err;
 }
 
-static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
+static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords)
 {
        u8 *otp;
        uint sz = OTP_SZ_MAX / 2;       /* size in words */
@@ -1126,7 +822,8 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
 
        err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz);
 
-       memcpy(buf, otp, bufsz);
+       sz = min_t(uint, sz, nwords);
+       memcpy(buf, otp, sz * 2);
 
        kfree(otp);
 
@@ -1138,14 +835,12 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
                 */
                return -ENODATA;
 
-       /* fixup the endianness so crc8 will pass */
-       htol16_buf(buf, bufsz);
-       if (crc8(brcms_srom_crc8_table, (u8 *) buf, SROM4_WORDS * 2,
+       if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2,
                 CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table))
                err = -EIO;
-
-       /* now correct the endianness of the byte array */
-       ltoh16_buf(buf, bufsz);
+       else
+               /* now correct the endianness of the byte array */
+               le16_to_cpu_buf(buf, sz);
 
        return err;
 }
@@ -1157,7 +852,7 @@ static int otp_read_pci(struct si_pub *sih, u16 *buf, uint bufsz)
 static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
 {
        u16 *srom;
-       u16 __iomem *sromwindow;
+       u8 __iomem *sromwindow;
        u8 sromrev = 0;
        u32 sr;
        int err = 0;
@@ -1173,29 +868,16 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
 
        crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY);
        if (ai_is_sprom_available(sih)) {
-               err = sprom_read_pci(sih, sromwindow, 0, srom, SROM_WORDS,
-                                    true);
-
-               if ((srom[SROM4_SIGN] == SROM4_SIGNATURE) ||
-                   (((sih->buscoretype == PCIE_CORE_ID)
-                     && (sih->buscorerev >= 6))
-                    || ((sih->buscoretype == PCI_CORE_ID)
-                        && (sih->buscorerev >= 0xe)))) {
-                       /* sromrev >= 4, read more */
-                       err = sprom_read_pci(sih, sromwindow, 0, srom,
-                                            SROM4_WORDS, true);
-                       sromrev = srom[SROM4_CRCREV] & 0xff;
-               } else if (err == 0) {
-                       /* srom is good and is rev < 4 */
+               err = sprom_read_pci(sih, sromwindow, 0, srom,
+                                    SROM4_WORDS, true);
+
+               if (err == 0)
+                       /* srom read and passed crc */
                        /* top word of sprom contains version and crc8 */
-                       sromrev = srom[SROM_CRCREV] & 0xff;
-                       /* bcm4401 sroms misprogrammed */
-                       if (sromrev == 0x10)
-                               sromrev = 1;
-               }
+                       sromrev = srom[SROM4_CRCREV] & 0xff;
        } else {
                /* Use OTP if SPROM not available */
-               err = otp_read_pci(sih, srom, SROM_MAX);
+               err = otp_read_pci(sih, srom, SROM4_WORDS);
                if (err == 0)
                        /* OTP only contain SROM rev8/rev9 for now */
                        sromrev = srom[SROM4_CRCREV] & 0xff;
@@ -1208,10 +890,9 @@ static int initvars_srom_pci(struct si_pub *sih, void __iomem *curmap)
                sr = 1 << sromrev;
 
                /*
-                * srom version check: Current valid versions: 1, 2, 3, 4, 5, 8,
-                * 9
+                * srom version check: Current valid versions: 8, 9
                 */
-               if ((sr & 0x33e) == 0) {
+               if ((sr & 0x300) == 0) {
                        err = -EINVAL;
                        goto errout;
                }
index 708c43f..c81df97 100644 (file)
@@ -26,9 +26,4 @@ extern void srom_free_vars(struct si_pub *sih);
 extern int srom_read(struct si_pub *sih, uint bus, void *curmap,
                     uint byteoff, uint nbytes, u16 *buf, bool check_crc);
 
-/* parse standard PCMCIA cis, normally used by SB/PCMCIA/SDIO/SPI/OTP
- *   and extract from it into name=value pairs
- */
-extern int srom_parsecis(u8 **pcis, uint ciscnt,
-                        char **vars, uint *count);
 #endif                         /* _BRCM_SROM_H_ */
index f27c489..12b795f 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/netdevice.h>
 #include <linux/module.h>
+
 #include <brcmu_utils.h>
 
 MODULE_AUTHOR("Broadcom Corporation");
@@ -66,36 +67,6 @@ void brcmu_pkt_buf_free_skb(struct sk_buff *skb)
 EXPORT_SYMBOL(brcmu_pkt_buf_free_skb);
 
 
-/* copy a buffer into a pkt buffer chain */
-uint brcmu_pktfrombuf(struct sk_buff *p, uint offset, int len,
-               unsigned char *buf)
-{
-       uint n, ret = 0;
-
-       /* skip 'offset' bytes */
-       for (; p && offset; p = p->next) {
-               if (offset < (uint) (p->len))
-                       break;
-               offset -= p->len;
-       }
-
-       if (!p)
-               return 0;
-
-       /* copy the data */
-       for (; p && len; p = p->next) {
-               n = min((uint) (p->len) - offset, (uint) len);
-               memcpy(p->data + offset, buf, n);
-               buf += n;
-               len -= n;
-               ret += n;
-               offset = 0;
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(brcmu_pktfrombuf);
-
 /* return total length of buffer chain */
 uint brcmu_pkttotlen(struct sk_buff *p)
 {
@@ -364,23 +335,3 @@ void brcmu_prpkt(const char *msg, struct sk_buff *p0)
 }
 EXPORT_SYMBOL(brcmu_prpkt);
 #endif                         /* defined(BCMDBG) */
-
-#if defined(BCMDBG)
-/*
- * print bytes formatted as hex to a string. return the resulting
- * string length
- */
-int brcmu_format_hex(char *str, const void *bytes, int len)
-{
-       int i;
-       char *p = str;
-       const u8 *src = (const u8 *)bytes;
-
-       for (i = 0; i < len; i++) {
-               p += snprintf(p, 3, "%02X", *src);
-               src++;
-       }
-       return (int)(p - str);
-}
-EXPORT_SYMBOL(brcmu_format_hex);
-#endif                         /* defined(BCMDBG) */
index 7d0f46e..ccf6015 100644 (file)
@@ -173,23 +173,18 @@ extern void brcmu_pktq_flush(struct pktq *pq, bool dir,
 
 /* externs */
 /* packet */
-extern uint brcmu_pktfrombuf(struct sk_buff *p,
-       uint offset, int len, unsigned char *buf);
 extern uint brcmu_pkttotlen(struct sk_buff *p);
 
 /* ip address */
 struct ipv4_addr;
 
+
+/* externs */
+/* format/print */
 #ifdef BCMDBG
 extern void brcmu_prpkt(const char *msg, struct sk_buff *p0);
 #else
 #define brcmu_prpkt(a, b)
 #endif                         /* BCMDBG */
 
-/* externs */
-/* format/print */
-#if defined(BCMDBG)
-extern int brcmu_format_hex(char *str, const void *bytes, int len);
-#endif
-
 #endif                         /* _BRCMU_UTILS_H_ */
index 1e5f310..f0d8c04 100644 (file)
@@ -62,7 +62,6 @@
 
 #define WL_RADIO_SW_DISABLE            (1<<0)
 #define WL_RADIO_HW_DISABLE            (1<<1)
-#define WL_RADIO_MPC_DISABLE           (1<<2)
 /* some countries don't support any channel */
 #define WL_RADIO_COUNTRY_DISABLE       (1<<3)
 
index 4fcb956..4e9b7e4 100644 (file)
@@ -77,8 +77,9 @@
 #define        DMEMS_CORE_ID           0x835   /* SDR/DDR1 memory controller core */
 #define        DEF_SHIM_COMP           0x837   /* SHIM component in ubus/6362 */
 #define OOB_ROUTER_CORE_ID     0x367   /* OOB router core ID */
-/* Default component, in ai chips it maps all unused address ranges */
-#define        DEF_AI_COMP             0xfff
+#define        DEF_AI_COMP             0xfff   /* Default component, in ai chips it
+                                        * maps all unused address ranges
+                                        */
 
 /* Common core control flags */
 #define        SICF_BIST_EN            0x8000
 #define        SICF_FGC                0x0002
 #define        SICF_CLOCK_EN           0x0001
 
+/* Common core status flags */
+#define        SISF_BIST_DONE          0x8000
+#define        SISF_BIST_ERROR         0x4000
+#define        SISF_GATED_CLK          0x2000
+#define        SISF_DMA64              0x1000
+#define        SISF_CORE_BITS          0x0fff
+
 #endif                         /* _BRCM_SOC_H */
index ccba69b..9d463cf 100644 (file)
@@ -2028,6 +2028,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
                .tkip = &tkip_cmd,
                .use_tkip = false,
        };
+       struct iwlagn_d3_config_cmd d3_cfg_cmd = {};
        int ret, i;
        u16 seq;
 
@@ -2085,13 +2086,14 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
        if (wowlan->four_way_handshake)
                wakeup_filter_cmd.enabled |=
                        cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
-       if (wowlan->rfkill_release)
-               wakeup_filter_cmd.enabled |=
-                       cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_RFKILL);
        if (wowlan->n_patterns)
                wakeup_filter_cmd.enabled |=
                        cpu_to_le32(IWLAGN_WOWLAN_WAKEUP_PATTERN_MATCH);
 
+       if (wowlan->rfkill_release)
+               d3_cfg_cmd.wakeup_flags |=
+                       cpu_to_le32(IWLAGN_D3_WAKEUP_RFKILL);
+
        iwl_scan_cancel_timeout(priv, 200);
 
        memcpy(&rxon, &ctx->active, sizeof(rxon));
@@ -2179,6 +2181,11 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
                }
        }
 
+       ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC,
+                                    sizeof(d3_cfg_cmd), &d3_cfg_cmd);
+       if (ret)
+               goto error;
+
        ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER,
                                 CMD_SYNC, sizeof(wakeup_filter_cmd),
                                 &wakeup_filter_cmd);
@@ -3171,7 +3178,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
 }
 
 /* This function both allocates and initializes hw and priv. */
-static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
+static struct ieee80211_hw *iwl_alloc_all(void)
 {
        struct iwl_priv *priv;
        /* mac80211 allocates memory for this device instance, including
@@ -3179,11 +3186,8 @@ static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
        struct ieee80211_hw *hw;
 
        hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwlagn_hw_ops);
-       if (hw == NULL) {
-               pr_err("%s: Can not allocate network device\n",
-                      cfg->name);
+       if (!hw)
                goto out;
-       }
 
        priv = hw->priv;
        priv->hw = hw;
@@ -3204,8 +3208,9 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
        /************************
         * 1. Allocating HW data
         ************************/
-       hw = iwl_alloc_all(cfg);
+       hw = iwl_alloc_all();
        if (!hw) {
+               pr_err("%s: Cannot allocate network device\n", cfg->name);
                err = -ENOMEM;
                goto out;
        }
index 69d5f85..f4eccf5 100644 (file)
@@ -198,6 +198,7 @@ enum {
        REPLY_WOWLAN_TKIP_PARAMS = 0xe3,
        REPLY_WOWLAN_KEK_KCK_MATERIAL = 0xe4,
        REPLY_WOWLAN_GET_STATUS = 0xe5,
+       REPLY_D3_CONFIG = 0xd3,
 
        REPLY_MAX = 0xff
 };
@@ -3800,6 +3801,19 @@ struct iwl_bt_coex_prot_env_cmd {
        u8 reserved[2];
 } __attribute__((packed));
 
+/*
+ * REPLY_D3_CONFIG
+ */
+enum iwlagn_d3_wakeup_filters {
+       IWLAGN_D3_WAKEUP_RFKILL         = BIT(0),
+       IWLAGN_D3_WAKEUP_SYSASSERT      = BIT(1),
+};
+
+struct iwlagn_d3_config_cmd {
+       __le32 min_sleep_time;
+       __le32 wakeup_flags;
+} __packed;
+
 /*
  * REPLY_WOWLAN_PATTERNS
  */
@@ -3830,19 +3844,16 @@ enum iwlagn_wowlan_wakeup_filters {
        IWLAGN_WOWLAN_WAKEUP_BEACON_MISS        = BIT(2),
        IWLAGN_WOWLAN_WAKEUP_LINK_CHANGE        = BIT(3),
        IWLAGN_WOWLAN_WAKEUP_GTK_REKEY_FAIL     = BIT(4),
-       IWLAGN_WOWLAN_WAKEUP_RFKILL             = BIT(5),
-       IWLAGN_WOWLAN_WAKEUP_UCODE_ERROR        = BIT(6),
-       IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ      = BIT(7),
-       IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE     = BIT(8),
-       IWLAGN_WOWLAN_WAKEUP_ALWAYS             = BIT(9),
-       IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT  = BIT(10),
+       IWLAGN_WOWLAN_WAKEUP_EAP_IDENT_REQ      = BIT(5),
+       IWLAGN_WOWLAN_WAKEUP_4WAY_HANDSHAKE     = BIT(6),
+       IWLAGN_WOWLAN_WAKEUP_ALWAYS             = BIT(7),
+       IWLAGN_WOWLAN_WAKEUP_ENABLE_NET_DETECT  = BIT(8),
 };
 
 struct iwlagn_wowlan_wakeup_filter_cmd {
        __le32 enabled;
        __le16 non_qos_seq;
-       u8 min_sleep_seconds;
-       u8 reserved;
+       __le16 reserved;
        __le16 qos_seq[8];
 };
 
index b9f3267..fbc3095 100644 (file)
 #define CSR_HW_REV_TYPE_6x35          CSR_HW_REV_TYPE_6x05
 #define CSR_HW_REV_TYPE_2x30          (0x00000C0)
 #define CSR_HW_REV_TYPE_2x00          (0x0000100)
-#define CSR_HW_REV_TYPE_200           (0x0000110)
-#define CSR_HW_REV_TYPE_230           (0x0000120)
+#define CSR_HW_REV_TYPE_105           (0x0000110)
+#define CSR_HW_REV_TYPE_135           (0x0000120)
 #define CSR_HW_REV_TYPE_NONE           (0x00001F0)
 
 /* EEPROM REG */
index a635a7e..2a2c8de 100644 (file)
@@ -28,7 +28,7 @@
 
 /* sparse doesn't like tracepoint macros */
 #ifndef __CHECKER__
-#include "iwl-dev.h"
+#include "iwl-trans.h"
 
 #define CREATE_TRACE_POINTS
 #include "iwl-devtrace.h"
index 8a51c5c..f9d3319 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <linux/tracepoint.h>
 
-struct iwl_priv;
 
 #if !defined(CONFIG_IWLWIFI_DEVICE_TRACING) || defined(__CHECKER__)
 #undef TRACE_EVENT
@@ -37,14 +36,14 @@ struct iwl_priv;
 static inline void trace_ ## name(proto) {}
 #endif
 
-#define PRIV_ENTRY     __field(struct iwl_priv *, priv)
+#define PRIV_ENTRY     __field(void *, priv)
 #define PRIV_ASSIGN    __entry->priv = priv
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi_io
 
 TRACE_EVENT(iwlwifi_dev_ioread32,
-       TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
+       TP_PROTO(void *priv, u32 offs, u32 val),
        TP_ARGS(priv, offs, val),
        TP_STRUCT__entry(
                PRIV_ENTRY
@@ -60,7 +59,7 @@ TRACE_EVENT(iwlwifi_dev_ioread32,
 );
 
 TRACE_EVENT(iwlwifi_dev_iowrite8,
-       TP_PROTO(struct iwl_priv *priv, u32 offs, u8 val),
+       TP_PROTO(void *priv, u32 offs, u8 val),
        TP_ARGS(priv, offs, val),
        TP_STRUCT__entry(
                PRIV_ENTRY
@@ -76,7 +75,7 @@ TRACE_EVENT(iwlwifi_dev_iowrite8,
 );
 
 TRACE_EVENT(iwlwifi_dev_iowrite32,
-       TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
+       TP_PROTO(void *priv, u32 offs, u32 val),
        TP_ARGS(priv, offs, val),
        TP_STRUCT__entry(
                PRIV_ENTRY
@@ -95,7 +94,7 @@ TRACE_EVENT(iwlwifi_dev_iowrite32,
 #define TRACE_SYSTEM iwlwifi_ucode
 
 TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
-       TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
+       TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
        TP_ARGS(priv, time, data, ev),
        TP_STRUCT__entry(
                PRIV_ENTRY
@@ -115,7 +114,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
-       TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
+       TP_PROTO(void *priv, u32 wraps, u32 n_entry, u32 p_entry),
        TP_ARGS(priv, wraps, n_entry, p_entry),
        TP_STRUCT__entry(
                PRIV_ENTRY
@@ -139,7 +138,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
 #define TRACE_SYSTEM iwlwifi
 
 TRACE_EVENT(iwlwifi_dev_hcmd,
-       TP_PROTO(struct iwl_priv *priv, u32 flags,
+       TP_PROTO(void *priv, u32 flags,
                 const void *hcmd0, size_t len0,
                 const void *hcmd1, size_t len1,
                 const void *hcmd2, size_t len2),
@@ -164,7 +163,7 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
 );
 
 TRACE_EVENT(iwlwifi_dev_rx,
-       TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len),
+       TP_PROTO(void *priv, void *rxbuf, size_t len),
        TP_ARGS(priv, rxbuf, len),
        TP_STRUCT__entry(
                PRIV_ENTRY
@@ -179,7 +178,7 @@ TRACE_EVENT(iwlwifi_dev_rx,
 );
 
 TRACE_EVENT(iwlwifi_dev_tx,
-       TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen,
+       TP_PROTO(void *priv, void *tfd, size_t tfdlen,
                 void *buf0, size_t buf0_len,
                 void *buf1, size_t buf1_len),
        TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
@@ -211,7 +210,7 @@ TRACE_EVENT(iwlwifi_dev_tx,
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_error,
-       TP_PROTO(struct iwl_priv *priv, u32 desc, u32 tsf_low,
+       TP_PROTO(void *priv, u32 desc, u32 tsf_low,
                 u32 data1, u32 data2, u32 line, u32 blink1,
                 u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
                 u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
@@ -271,7 +270,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
 );
 
 TRACE_EVENT(iwlwifi_dev_ucode_event,
-       TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
+       TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
        TP_ARGS(priv, time, data, ev),
        TP_STRUCT__entry(
                PRIV_ENTRY
index e5d727f..a26fbd3 100644 (file)
@@ -678,7 +678,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
                        priv->contexts[IWL_RXON_CTX_BSS].active.flags &
                                                RXON_FLG_CHANNEL_MODE_MSK)
                                       >> RXON_FLG_CHANNEL_MODE_POS;
-               if (chan_mod == CHANNEL_MODE_PURE_40) {
+               if ((priv->scan_request && priv->scan_request->no_cck) ||
+                   chan_mod == CHANNEL_MODE_PURE_40) {
                        rate = IWL_RATE_6M_PLCP;
                } else {
                        rate = IWL_RATE_1M_PLCP;
index c42be81..48e8218 100644 (file)
@@ -165,11 +165,15 @@ static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
                                struct key_params *params)
 {
        struct iwm_priv *iwm = ndev_to_iwm(ndev);
-       struct iwm_key *key = &iwm->keys[key_index];
+       struct iwm_key *key;
        int ret;
 
        IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr);
 
+       if (key_index >= IWM_NUM_KEYS)
+               return -ENOENT;
+
+       key = &iwm->keys[key_index];
        memset(key, 0, sizeof(struct iwm_key));
        ret = iwm_key_init(key, key_index, mac_addr, params);
        if (ret < 0) {
@@ -214,8 +218,12 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
                                u8 key_index, bool pairwise, const u8 *mac_addr)
 {
        struct iwm_priv *iwm = ndev_to_iwm(ndev);
-       struct iwm_key *key = &iwm->keys[key_index];
+       struct iwm_key *key;
 
+       if (key_index >= IWM_NUM_KEYS)
+               return -ENOENT;
+
+       key = &iwm->keys[key_index];
        if (!iwm->keys[key_index].key_len) {
                IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index);
                return 0;
@@ -236,6 +244,9 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
 
        IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index);
 
+       if (key_index >= IWM_NUM_KEYS)
+               return -ENOENT;
+
        if (!iwm->keys[key_index].key_len) {
                IWM_ERR(iwm, "Key %d not used\n", key_index);
                return -EINVAL;
index 68455a2..477100d 100644 (file)
@@ -1747,6 +1747,8 @@ static int __init init_mac80211_hwsim(void)
                            IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                            IEEE80211_HW_AMPDU_AGGREGATION;
 
+               hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
+
                /* ask mac80211 to reserve space for magic */
                hw->vif_data_size = sizeof(struct hwsim_vif_priv);
                hw->sta_data_size = sizeof(struct hwsim_sta_priv);
index 0c13840..83f3e52 100644 (file)
@@ -414,6 +414,7 @@ struct ndis_80211_pmkid {
 #define RNDIS_WLAN_ALG_TKIP    (1<<1)
 #define RNDIS_WLAN_ALG_CCMP    (1<<2)
 
+#define RNDIS_WLAN_NUM_KEYS            4
 #define RNDIS_WLAN_KEY_MGMT_NONE       0
 #define RNDIS_WLAN_KEY_MGMT_802_1X     (1<<0)
 #define RNDIS_WLAN_KEY_MGMT_PSK                (1<<1)
@@ -516,7 +517,7 @@ struct rndis_wlan_private {
 
        /* encryption stuff */
        int  encr_tx_key_index;
-       struct rndis_wlan_encr_key encr_keys[4];
+       struct rndis_wlan_encr_key encr_keys[RNDIS_WLAN_NUM_KEYS];
        int  wpa_version;
 
        u8 command_buffer[COMMAND_BUFFER_SIZE];
@@ -1535,6 +1536,9 @@ static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid)
        bool is_wpa;
        int ret;
 
+       if (index >= RNDIS_WLAN_NUM_KEYS)
+               return -ENOENT;
+
        if (priv->encr_keys[index].len == 0)
                return 0;
 
@@ -2451,6 +2455,9 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 
        netdev_dbg(usbdev->net, "%s(%i)\n", __func__, key_index);
 
+       if (key_index >= RNDIS_WLAN_NUM_KEYS)
+               return -ENOENT;
+
        priv->encr_tx_key_index = key_index;
 
        if (is_wpa_key(priv, key_index))
index feed1ed..b9a158e 100644 (file)
@@ -274,6 +274,8 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)},
 
        /****** 8188CU ********/
+       /* RTL8188CTV */
+       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x018a, rtl92cu_hal_cfg)},
        /* 8188CE-VAU USB minCard */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)},
        /* 8188cu 1*1 dongle */
@@ -290,14 +292,14 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)},
        /* 8188RU in Alfa AWUS036NHR */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
+       /* RTL8188CUS-VL */
+       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)},
        /* 8188 Combo for BC4 */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
 
        /****** 8192CU ********/
-       /* 8191cu 1*2 */
-       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)},
        /* 8192cu 2*2 */
-       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)},
+       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8178, rtl92cu_hal_cfg)},
        /* 8192CE-VAU USB minCard */
        {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)},
 
@@ -308,13 +310,17 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
        {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
-       {RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+       {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+       {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
        {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
        /* HP - Lite-On ,8188CUS Slim Combo */
        {RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
        {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */
        {RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/
+       {RTL_USB_DEVICE(0x2019, 0x4902, rtl92cu_hal_cfg)}, /*Planex - Etop*/
        {RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/
+       /*SW-WF02-AD15 -Abocom*/
+       {RTL_USB_DEVICE(0x2019, 0xab2e, rtl92cu_hal_cfg)},
        {RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/
        {RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/
        {RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/
@@ -325,14 +331,36 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x4855, 0x0091, rtl92cu_hal_cfg)}, /* NetweeN-Feixun */
        {RTL_USB_DEVICE(0x9846, 0x9041, rtl92cu_hal_cfg)}, /* Netgear Cameo */
 
+       /****** 8188 RU ********/
+       /* Netcore */
+       {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x317f, rtl92cu_hal_cfg)},
+
+       /****** 8188CUS Slim Solo********/
+       {RTL_USB_DEVICE(0x04f2, 0xaff7, rtl92cu_hal_cfg)}, /*Xavi*/
+       {RTL_USB_DEVICE(0x04f2, 0xaff9, rtl92cu_hal_cfg)}, /*Xavi*/
+       {RTL_USB_DEVICE(0x04f2, 0xaffa, rtl92cu_hal_cfg)}, /*Xavi*/
+
+       /****** 8188CUS Slim Combo ********/
+       {RTL_USB_DEVICE(0x04f2, 0xaff8, rtl92cu_hal_cfg)}, /*Xavi*/
+       {RTL_USB_DEVICE(0x04f2, 0xaffb, rtl92cu_hal_cfg)}, /*Xavi*/
+       {RTL_USB_DEVICE(0x04f2, 0xaffc, rtl92cu_hal_cfg)}, /*Xavi*/
+       {RTL_USB_DEVICE(0x2019, 0x1201, rtl92cu_hal_cfg)}, /*Planex-Vencer*/
+
        /****** 8192CU ********/
+       {RTL_USB_DEVICE(0x050d, 0x2102, rtl92cu_hal_cfg)}, /*Belcom-Sercomm*/
+       {RTL_USB_DEVICE(0x050d, 0x2103, rtl92cu_hal_cfg)}, /*Belcom-Edimax*/
        {RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/
        {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
        {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
+       {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/
+       {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/
+       {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/
+       {RTL_USB_DEVICE(0x0e66, 0x0019, rtl92cu_hal_cfg)}, /*Hawking-Edimax*/
        {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
        {RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
        {RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
+       {RTL_USB_DEVICE(0x20f4, 0x624d, rtl92cu_hal_cfg)}, /*TRENDNet*/
        {RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/
        {}
 };
index 72eddd1..eddf492 100644 (file)
@@ -901,6 +901,10 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
  * @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
  *     CCMP key if it requires CCMP encryption of management frames (MFP) to
  *     be done in software.
+ * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver
+ *     for a CCMP key if space should be prepared for the IV, but the IV
+ *     itself should not be generated. Do not set together with
+ *     @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
  */
 enum ieee80211_key_flags {
        IEEE80211_KEY_FLAG_WMM_STA      = 1<<0,
@@ -908,6 +912,7 @@ enum ieee80211_key_flags {
        IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
        IEEE80211_KEY_FLAG_PAIRWISE     = 1<<3,
        IEEE80211_KEY_FLAG_SW_MGMT      = 1<<4,
+       IEEE80211_KEY_FLAG_PUT_IV_SPACE = 1<<5,
 };
 
 /**
index 97f3358..f9ec0d9 100644 (file)
@@ -176,7 +176,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
        memcpy(mgmt->da, da, ETH_ALEN);
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+           sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+           sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
                memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
index 2ac0339..fefc7e5 100644 (file)
@@ -77,7 +77,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
        memcpy(mgmt->da, da, ETH_ALEN);
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+           sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+           sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
                memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
@@ -371,13 +372,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
               pubsta->addr, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
-       /*
-        * The aggregation code is not prepared to handle
-        * anything but STA/AP due to the BSSID handling.
-        * IBSS could work in the code but isn't supported
-        * by drivers or the standard.
-        */
        if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+           sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
            sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
            sdata->vif.type != NL80211_IFTYPE_AP)
                return -EINVAL;
index d06c65f..65b72ae 100644 (file)
@@ -1394,7 +1394,7 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
            (old_oper_type != local->_oper_channel_type))
                ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
-       if ((sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR) &&
+       if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR &&
            old_vif_oper_type != sdata->vif.bss_conf.channel_type)
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
 
index f80a35c..988c7ec 100644 (file)
@@ -195,7 +195,8 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
        memcpy(mgmt->da, da, ETH_ALEN);
        memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
        if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+           sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
+           sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
                memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
index ea10a51..e244709 100644 (file)
@@ -1334,6 +1334,12 @@ void ieee80211_recalc_smps(struct ieee80211_local *local);
 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
                          const u8 *ids, int n_ids, size_t offset);
 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+                             u16 cap);
+u8 *ieee80211_ie_build_ht_info(u8 *pos,
+                               struct ieee80211_sta_ht_cap *ht_cap,
+                               struct ieee80211_channel *channel,
+                               enum nl80211_channel_type channel_type);
 
 /* internal work items */
 void ieee80211_work_init(struct ieee80211_local *local);
@@ -1362,6 +1368,8 @@ ieee80211_get_channel_mode(struct ieee80211_local *local,
 bool ieee80211_set_channel_type(struct ieee80211_local *local,
                                struct ieee80211_sub_if_data *sdata,
                                enum nl80211_channel_type chantype);
+enum nl80211_channel_type
+ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info);
 
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
index 30d7355..33a9746 100644 (file)
@@ -286,6 +286,13 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
                        netif_carrier_off(dev);
                else
                        netif_carrier_on(dev);
+
+               /*
+                * set default queue parameters so drivers don't
+                * need to initialise the hardware if the hardware
+                * doesn't start up with sane defaults
+                */
+               ieee80211_set_wmm_default(sdata);
        }
 
        set_bit(SDATA_STATE_RUNNING, &sdata->state);
@@ -329,15 +336,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up)
        if (coming_up)
                local->open_count++;
 
-       if (hw_reconf_flags) {
+       if (hw_reconf_flags)
                ieee80211_hw_config(local, hw_reconf_flags);
-               /*
-                * set default queue parameters so drivers don't
-                * need to initialise the hardware if the hardware
-                * doesn't start up with sane defaults
-                */
-               ieee80211_set_wmm_default(sdata);
-       }
 
        ieee80211_recalc_ps(local, -1);
 
index 756b157..17a5220 100644 (file)
@@ -133,9 +133,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
                key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
 
                if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+                     (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
+                     (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
                        sdata->crypto_tx_tailroom_needed_cnt--;
 
+               WARN_ON((key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE) &&
+                       (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV));
+
                return 0;
        }
 
@@ -178,7 +182,8 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
        sdata = key->sdata;
 
        if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
-             (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)))
+             (key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) ||
+             (key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
                increment_tailroom_need_count(sdata);
 
        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
index a7078fd..b3a125f 100644 (file)
@@ -76,6 +76,7 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
 bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+       struct ieee80211_local *local = sdata->local;
 
        /*
         * As support for each feature is added, check for matching
@@ -87,15 +88,23 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
         *   - MDA enabled
         * - Power management control on fc
         */
-       if (ifmsh->mesh_id_len == ie->mesh_id_len &&
-               memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
-               (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
-               (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) &&
-               (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
-               (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
-               (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth))
-               return true;
-
+       if (!(ifmsh->mesh_id_len == ie->mesh_id_len &&
+            memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
+            (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
+            (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) &&
+            (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) &&
+            (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) &&
+            (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)))
+               goto mismatch;
+
+       /* disallow peering with mismatched channel types for now */
+       if (ie->ht_info_elem &&
+           (local->_oper_channel_type !=
+            ieee80211_ht_info_to_channel_type(ie->ht_info_elem)))
+               goto mismatch;
+
+       return true;
+mismatch:
        return false;
 }
 
@@ -341,6 +350,49 @@ int mesh_add_ds_params_ie(struct sk_buff *skb,
        return 0;
 }
 
+int mesh_add_ht_cap_ie(struct sk_buff *skb,
+                      struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_supported_band *sband;
+       u8 *pos;
+
+       sband = local->hw.wiphy->bands[local->oper_channel->band];
+       if (!sband->ht_cap.ht_supported ||
+           local->_oper_channel_type == NL80211_CHAN_NO_HT)
+               return 0;
+
+       if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap))
+               return -ENOMEM;
+
+       pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_cap));
+       ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
+
+       return 0;
+}
+
+int mesh_add_ht_info_ie(struct sk_buff *skb,
+                       struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_channel *channel = local->oper_channel;
+       enum nl80211_channel_type channel_type = local->_oper_channel_type;
+       struct ieee80211_supported_band *sband =
+                               local->hw.wiphy->bands[channel->band];
+       struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap;
+       u8 *pos;
+
+       if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
+               return 0;
+
+       if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_info))
+               return -ENOMEM;
+
+       pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_info));
+       ieee80211_ie_build_ht_info(pos, ht_cap, channel, channel_type);
+
+       return 0;
+}
 static void ieee80211_mesh_path_timer(unsigned long data)
 {
        struct ieee80211_sub_if_data *sdata =
index 8c00e2d..0f2c4e6 100644 (file)
@@ -212,6 +212,10 @@ int mesh_add_vendor_ies(struct sk_buff *skb,
                        struct ieee80211_sub_if_data *sdata);
 int mesh_add_ds_params_ie(struct sk_buff *skb,
                          struct ieee80211_sub_if_data *sdata);
+int mesh_add_ht_cap_ie(struct sk_buff *skb,
+                      struct ieee80211_sub_if_data *sdata);
+int mesh_add_ht_info_ie(struct sk_buff *skb,
+                       struct ieee80211_sub_if_data *sdata);
 void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
 int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
 void ieee80211s_init(void);
index 174040a..9a1f8bb 100644 (file)
@@ -113,20 +113,20 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,
                struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
-       struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+       struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
-       u8 *pos;
-       int ie_len;
+       u8 *pos, ie_len;
+       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
+                     sizeof(mgmt->u.action.u.mesh_action);
 
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+                           hdr_len +
+                           2 + 37); /* max HWMP IE */
        if (!skb)
                return -1;
        skb_reserve(skb, local->hw.extra_tx_headroom);
-       /* 25 is the size of the common mgmt part (24) plus the size of the
-        * common action part (1)
-        */
-       mgmt = (struct ieee80211_mgmt *)
-               skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
-       memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
+       memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
 
@@ -240,20 +240,20 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,
                       struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
-       struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
+       struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
-       u8 *pos;
-       int ie_len;
+       u8 *pos, ie_len;
+       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.mesh_action) +
+                     sizeof(mgmt->u.action.u.mesh_action);
 
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+                           hdr_len +
+                           2 + 15 /* PERR IE */);
        if (!skb)
                return -1;
        skb_reserve(skb, local->tx_headroom + local->hw.extra_tx_headroom);
-       /* 25 is the size of the common mgmt part (24) plus the size of the
-        * common action part (1)
-        */
-       mgmt = (struct ieee80211_mgmt *)
-               skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action));
-       memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action));
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
+       memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
 
index 7e57f5d..0140e88 100644 (file)
@@ -80,11 +80,15 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta)
  *       on it in the lifecycle management section!
  */
 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
-                                        u8 *hw_addr, u32 rates)
+                                        u8 *hw_addr, u32 rates,
+                                        struct ieee802_11_elems *elems)
 {
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_supported_band *sband;
        struct sta_info *sta;
 
+       sband = local->hw.wiphy->bands[local->oper_channel->band];
+
        if (local->num_sta >= MESH_MAX_PLINKS)
                return NULL;
 
@@ -96,6 +100,9 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
        set_sta_flag(sta, WLAN_STA_AUTHORIZED);
        set_sta_flag(sta, WLAN_STA_WME);
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
+       if (elems->ht_cap_elem)
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sband, elems->ht_cap_elem,
+                                                 &sta->sta.ht_cap);
        rate_control_rate_init(sta);
 
        return sta;
@@ -153,23 +160,31 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                enum ieee80211_self_protected_actioncode action,
                u8 *da, __le16 llid, __le16 plid, __le16 reason) {
        struct ieee80211_local *local = sdata->local;
-       struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
-                       sdata->u.mesh.ie_len);
+       struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
        bool include_plid = false;
-       int ie_len = 4;
        u16 peering_proto = 0;
-       u8 *pos;
-
+       u8 *pos, ie_len = 4;
+       int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
+                     sizeof(mgmt->u.action.u.self_prot);
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+                           hdr_len +
+                           2 + /* capability info */
+                           2 + /* AID */
+                           2 + 8 + /* supported rates */
+                           2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+                           2 + sdata->u.mesh.mesh_id_len +
+                           2 + sizeof(struct ieee80211_meshconf_ie) +
+                           2 + sizeof(struct ieee80211_ht_cap) +
+                           2 + sizeof(struct ieee80211_ht_info) +
+                           2 + 8 + /* peering IE */
+                           sdata->u.mesh.ie_len);
        if (!skb)
                return -1;
        skb_reserve(skb, local->hw.extra_tx_headroom);
-       /* 25 is the size of the common mgmt part (24) plus the size of the
-        * common action part (1)
-        */
-       mgmt = (struct ieee80211_mgmt *)
-               skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot));
-       memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot));
+       mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
+       memset(mgmt, 0, hdr_len);
        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
        memcpy(mgmt->da, da, ETH_ALEN);
@@ -235,6 +250,13 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
                memcpy(pos, &reason, 2);
                pos += 2;
        }
+
+       if (action != WLAN_SP_MESH_PEERING_CLOSE) {
+               if (mesh_add_ht_cap_ie(skb, sdata) ||
+                   mesh_add_ht_info_ie(skb, sdata))
+                       return -1;
+       }
+
        if (mesh_add_vendor_ies(skb, sdata))
                return -1;
 
@@ -261,7 +283,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
                                        elems->ie_start, elems->total_len,
                                        GFP_KERNEL);
                else
-                       sta = mesh_plink_alloc(sdata, hw_addr, rates);
+                       sta = mesh_plink_alloc(sdata, hw_addr, rates, elems);
                if (!sta)
                        return;
                if (sta_info_insert_rcu(sta)) {
@@ -552,7 +574,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
                }
 
                rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
-               sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
+               sta = mesh_plink_alloc(sdata, mgmt->sa, rates, &elems);
                if (!sta) {
                        mpl_dbg("Mesh plink error: plink table full\n");
                        return;
index b867bd5..3173dcf 100644 (file)
@@ -2203,13 +2203,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 
        switch (mgmt->u.action.category) {
        case WLAN_CATEGORY_BACK:
-               /*
-                * The aggregation code is not prepared to handle
-                * anything but STA/AP due to the BSSID handling;
-                * IBSS could work in the code but isn't supported
-                * by drivers or the standard.
-                */
                if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+                   sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
                    sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
                    sdata->vif.type != NL80211_IFTYPE_AP)
                        break;
@@ -2489,6 +2484,10 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                goto out_free_skb;
        rx->flags |= IEEE80211_RX_CMNTR;
 
+       /* If there are no cooked monitor interfaces, just free the SKB */
+       if (!local->cooked_mntrs)
+               goto out_free_skb;
+
        if (skb_headroom(skb) < sizeof(*rthdr) &&
            pskb_expand_head(skb, sizeof(*rthdr), 0, GFP_ATOMIC))
                goto out_free_skb;
index 48bbb96..a543d26 100644 (file)
@@ -2278,22 +2278,31 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
        } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
                struct ieee80211_mgmt *mgmt;
                u8 *pos;
+               int hdr_len = offsetof(struct ieee80211_mgmt, u.beacon) +
+                             sizeof(mgmt->u.beacon);
 
 #ifdef CONFIG_MAC80211_MESH
                if (!sdata->u.mesh.mesh_id_len)
                        goto out;
 #endif
 
-               /* headroom, head length, tail length and maximum TIM length */
-               skb = dev_alloc_skb(local->tx_headroom + 400 +
-                               sdata->u.mesh.ie_len);
+               skb = dev_alloc_skb(local->tx_headroom +
+                                   hdr_len +
+                                   2 + /* NULL SSID */
+                                   2 + 8 + /* supported rates */
+                                   2 + 3 + /* DS params */
+                                   2 + (IEEE80211_MAX_SUPP_RATES - 8) +
+                                   2 + sizeof(struct ieee80211_ht_cap) +
+                                   2 + sizeof(struct ieee80211_ht_info) +
+                                   2 + sdata->u.mesh.mesh_id_len +
+                                   2 + sizeof(struct ieee80211_meshconf_ie) +
+                                   sdata->u.mesh.ie_len);
                if (!skb)
                        goto out;
 
                skb_reserve(skb, local->hw.extra_tx_headroom);
-               mgmt = (struct ieee80211_mgmt *)
-                       skb_put(skb, 24 + sizeof(mgmt->u.beacon));
-               memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
+               mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
+               memset(mgmt, 0, hdr_len);
                mgmt->frame_control =
                    cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
                memset(mgmt->da, 0xff, ETH_ALEN);
@@ -2312,6 +2321,8 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
                    mesh_add_ds_params_ie(skb, sdata) ||
                    ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
                    mesh_add_rsn_ie(skb, sdata) ||
+                   mesh_add_ht_cap_ie(skb, sdata) ||
+                   mesh_add_ht_info_ie(skb, sdata) ||
                    mesh_add_meshid_ie(skb, sdata) ||
                    mesh_add_meshconf_ie(skb, sdata) ||
                    mesh_add_vendor_ies(skb, sdata)) {
index 7439d26..72b3a2e 100644 (file)
@@ -811,23 +811,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
                offset = noffset;
        }
 
-       if (sband->ht_cap.ht_supported) {
-               u16 cap = sband->ht_cap.cap;
-               __le16 tmp;
-
-               *pos++ = WLAN_EID_HT_CAPABILITY;
-               *pos++ = sizeof(struct ieee80211_ht_cap);
-               memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-               tmp = cpu_to_le16(cap);
-               memcpy(pos, &tmp, sizeof(u16));
-               pos += sizeof(u16);
-               *pos++ = sband->ht_cap.ampdu_factor |
-                        (sband->ht_cap.ampdu_density <<
-                               IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-               memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-               pos += sizeof(sband->ht_cap.mcs);
-               pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
-       }
+       if (sband->ht_cap.ht_supported)
+               pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
 
        /*
         * If adding more here, adjust code in main.c
@@ -1362,6 +1347,103 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
 }
 EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
 
+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
+                             u16 cap)
+{
+       __le16 tmp;
+
+       *pos++ = WLAN_EID_HT_CAPABILITY;
+       *pos++ = sizeof(struct ieee80211_ht_cap);
+       memset(pos, 0, sizeof(struct ieee80211_ht_cap));
+
+       /* capability flags */
+       tmp = cpu_to_le16(cap);
+       memcpy(pos, &tmp, sizeof(u16));
+       pos += sizeof(u16);
+
+       /* AMPDU parameters */
+       *pos++ = sband->ht_cap.ampdu_factor |
+                (sband->ht_cap.ampdu_density <<
+                       IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
+
+       /* MCS set */
+       memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
+       pos += sizeof(sband->ht_cap.mcs);
+
+       /* extended capabilities */
+       pos += sizeof(__le16);
+
+       /* BF capabilities */
+       pos += sizeof(__le32);
+
+       /* antenna selection */
+       pos += sizeof(u8);
+
+       return pos;
+}
+
+u8 *ieee80211_ie_build_ht_info(u8 *pos,
+                              struct ieee80211_sta_ht_cap *ht_cap,
+                              struct ieee80211_channel *channel,
+                              enum nl80211_channel_type channel_type)
+{
+       struct ieee80211_ht_info *ht_info;
+       /* Build HT Information */
+       *pos++ = WLAN_EID_HT_INFORMATION;
+       *pos++ = sizeof(struct ieee80211_ht_info);
+       ht_info = (struct ieee80211_ht_info *)pos;
+       ht_info->control_chan =
+                       ieee80211_frequency_to_channel(channel->center_freq);
+       switch (channel_type) {
+       case NL80211_CHAN_HT40MINUS:
+               ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+               break;
+       case NL80211_CHAN_HT40PLUS:
+               ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+               break;
+       case NL80211_CHAN_HT20:
+       default:
+               ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+               break;
+       }
+       if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+               ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
+       ht_info->operation_mode = 0x0000;
+       ht_info->stbc_param = 0x0000;
+
+       /* It seems that Basic MCS set and Supported MCS set
+          are identical for the first 10 bytes */
+       memset(&ht_info->basic_set, 0, 16);
+       memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);
+
+       return pos + sizeof(struct ieee80211_ht_info);
+}
+
+enum nl80211_channel_type
+ieee80211_ht_info_to_channel_type(struct ieee80211_ht_info *ht_info)
+{
+       enum nl80211_channel_type channel_type;
+
+       if (!ht_info)
+               return NL80211_CHAN_NO_HT;
+
+       switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+       case IEEE80211_HT_PARAM_CHA_SEC_NONE:
+               channel_type = NL80211_CHAN_HT20;
+               break;
+       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               channel_type = NL80211_CHAN_HT40PLUS;
+               break;
+       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+               channel_type = NL80211_CHAN_HT40MINUS;
+               break;
+       default:
+               channel_type = NL80211_CHAN_NO_HT;
+       }
+
+       return channel_type;
+}
+
 int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
index 6c53b6d..30da4e3 100644 (file)
@@ -103,7 +103,6 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        u8 *pos;
        u32 flags = channel->flags;
        u16 cap = sband->ht_cap.cap;
-       __le16 tmp;
 
        if (!sband->ht_cap.ht_supported)
                return;
@@ -154,34 +153,8 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        }
 
        /* reserve and fill IE */
-
        pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-       *pos++ = WLAN_EID_HT_CAPABILITY;
-       *pos++ = sizeof(struct ieee80211_ht_cap);
-       memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-
-       /* capability flags */
-       tmp = cpu_to_le16(cap);
-       memcpy(pos, &tmp, sizeof(u16));
-       pos += sizeof(u16);
-
-       /* AMPDU parameters */
-       *pos++ = sband->ht_cap.ampdu_factor |
-                (sband->ht_cap.ampdu_density <<
-                       IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-
-       /* MCS set */
-       memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-       pos += sizeof(sband->ht_cap.mcs);
-
-       /* extended capabilities */
-       pos += sizeof(__le16);
-
-       /* BF capabilities */
-       pos += sizeof(__le32);
-
-       /* antenna selection */
-       pos += sizeof(u8);
+       ieee80211_ie_build_ht_cap(pos, sband, cap);
 }
 
 static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
index f614ce7..13efab5 100644 (file)
@@ -390,7 +390,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        u8 scratch[6 * AES_BLOCK_SIZE];
 
        if (info->control.hw_key &&
-           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
+           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
+           !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) {
                /*
                 * hwaccel has no need for preallocated room for CCMP
                 * header or MIC fields
@@ -412,6 +413,11 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
 
        pos = skb_push(skb, CCMP_HDR_LEN);
        memmove(pos, pos + CCMP_HDR_LEN, hdrlen);
+
+       /* the HW only needs room for the IV, but not the actual IV */
+       if (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)
+               return 0;
+
        hdr = (struct ieee80211_hdr *) pos;
        pos += hdrlen;
 
index b3a476f..e97827b 100644 (file)
@@ -6639,10 +6639,7 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
        if (wiphy_idx_valid(request->wiphy_idx))
                NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        rcu_read_lock();
        genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
@@ -6678,10 +6675,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
        NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -6762,10 +6756,7 @@ static void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
        NLA_PUT_FLAG(msg, NL80211_ATTR_TIMED_OUT);
        NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -6821,10 +6812,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
        if (resp_ie)
                NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -6862,10 +6850,7 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
        if (resp_ie)
                NLA_PUT(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -6903,10 +6888,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
        if (ie)
                NLA_PUT(msg, NL80211_ATTR_IE, ie_len, ie);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, GFP_KERNEL);
@@ -6939,10 +6921,7 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
        NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -6977,10 +6956,7 @@ void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
        if (ie_len && ie)
                NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7019,10 +6995,7 @@ void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
        if (tsc)
                NLA_PUT(msg, NL80211_ATTR_KEY_SEQ, 6, tsc);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7073,10 +7046,7 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
                goto nla_put_failure;
        nla_nest_end(msg, nl_freq);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        rcu_read_lock();
        genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
@@ -7119,10 +7089,7 @@ static void nl80211_send_remain_on_chan_event(
        if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL)
                NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7193,10 +7160,7 @@ void nl80211_send_sta_del_event(struct cfg80211_registered_device *rdev,
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
        NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7213,7 +7177,6 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 {
        struct sk_buff *msg;
        void *hdr;
-       int err;
 
        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
        if (!msg)
@@ -7230,16 +7193,9 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
        NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
        NLA_PUT(msg, NL80211_ATTR_FRAME, len, buf);
 
-       err = genlmsg_end(msg, hdr);
-       if (err < 0) {
-               nlmsg_free(msg);
-               return err;
-       }
+       genlmsg_end(msg, hdr);
 
-       err = genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
-       if (err < 0)
-               return err;
-       return 0;
+       return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
 
  nla_put_failure:
        genlmsg_cancel(msg, hdr);
@@ -7272,10 +7228,7 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev,
        if (ack)
                NLA_PUT_FLAG(msg, NL80211_ATTR_ACK);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
        return;
@@ -7317,10 +7270,7 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
 
        nla_nest_end(msg, pinfoattr);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7362,10 +7312,7 @@ void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
 
        nla_nest_end(msg, rekey_attr);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7408,10 +7355,7 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
 
        nla_nest_end(msg, attr);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);
@@ -7453,10 +7397,7 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
 
        nla_nest_end(msg, pinfoattr);
 
-       if (genlmsg_end(msg, hdr) < 0) {
-               nlmsg_free(msg);
-               return;
-       }
+       genlmsg_end(msg, hdr);
 
        genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
                                nl80211_mlme_mcgrp.id, gfp);