Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Jun 2011 19:25:51 +0000 (15:25 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Jun 2011 19:25:51 +0000 (15:25 -0400)
Conflicts:
drivers/net/wireless/rtlwifi/pci.c
include/linux/netlink.h

185 files changed:
drivers/bcma/bcma_private.h
drivers/bcma/core.c
drivers/bcma/driver_chipcommon_pmu.c
drivers/bcma/driver_pci.c
drivers/bcma/host_pci.c
drivers/bcma/main.c
drivers/net/b44.c
drivers/net/wireless/ath/ath5k/ahb.c
drivers/net/wireless/ath/ath5k/ath5k.h
drivers/net/wireless/ath/ath5k/base.c
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath5k/reset.c
drivers/net/wireless/ath/ath9k/ahb.c
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_hw.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h [new file with mode: 0644]
drivers/net/wireless/ath/ath9k/ath9k.h
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/rc.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/reg.h
drivers/net/wireless/b43/Kconfig
drivers/net/wireless/b43/Makefile
drivers/net/wireless/b43/b43.h
drivers/net/wireless/b43/bus.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/phy_common.c
drivers/net/wireless/b43/phy_common.h
drivers/net/wireless/b43/phy_ht.c [new file with mode: 0644]
drivers/net/wireless/b43/phy_ht.h [new file with mode: 0644]
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/b43/radio_2055.h
drivers/net/wireless/b43/radio_2056.h
drivers/net/wireless/b43/radio_2059.c [new file with mode: 0644]
drivers/net/wireless/b43/radio_2059.h [new file with mode: 0644]
drivers/net/wireless/b43/sdio.c
drivers/net/wireless/b43/tables_nphy.h
drivers/net/wireless/iwlegacy/iwl-3945.c
drivers/net/wireless/iwlegacy/iwl-4965-lib.c
drivers/net/wireless/iwlegacy/iwl-4965-rx.c
drivers/net/wireless/iwlegacy/iwl-4965.c
drivers/net/wireless/iwlegacy/iwl-commands.h
drivers/net/wireless/iwlegacy/iwl-core.c
drivers/net/wireless/iwlegacy/iwl-core.h
drivers/net/wireless/iwlegacy/iwl-debugfs.c
drivers/net/wireless/iwlegacy/iwl-dev.h
drivers/net/wireless/iwlegacy/iwl-devtrace.c
drivers/net/wireless/iwlegacy/iwl-devtrace.h
drivers/net/wireless/iwlegacy/iwl-helpers.h
drivers/net/wireless/iwlegacy/iwl-rx.c
drivers/net/wireless/iwlegacy/iwl-scan.c
drivers/net/wireless/iwlegacy/iwl3945-base.c
drivers/net/wireless/iwlegacy/iwl4965-base.c
drivers/net/wireless/iwlwifi/Makefile
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-2000.c
drivers/net/wireless/iwlwifi/iwl-5000-hw.h
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
drivers/net/wireless/iwlwifi/iwl-agn-hw.h
drivers/net/wireless/iwlwifi/iwl-agn-ict.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-agn-tt.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-debug.h
drivers/net/wireless/iwlwifi/iwl-debugfs.c
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-eeprom.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/iwlwifi/iwl-hcmd.c
drivers/net/wireless/iwlwifi/iwl-helpers.h
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-pci.c [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-pci.h [new file with mode: 0644]
drivers/net/wireless/iwlwifi/iwl-power.c
drivers/net/wireless/iwlwifi/iwl-power.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-sv-open.c
drivers/net/wireless/iwlwifi/iwl-testmode.h
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/mwifiex/11n.c
drivers/net/wireless/mwifiex/11n.h
drivers/net/wireless/mwifiex/11n_rxreorder.c
drivers/net/wireless/mwifiex/11n_rxreorder.h
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/mwifiex/sta_cmd.c
drivers/net/wireless/mwifiex/sta_cmdresp.c
drivers/net/wireless/mwifiex/sta_rx.c
drivers/net/wireless/mwifiex/txrx.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00usb.c
drivers/net/wireless/rtlwifi/base.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/rtlwifi/core.h
drivers/net/wireless/rtlwifi/efuse.c
drivers/net/wireless/rtlwifi/pci.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/rtlwifi/ps.h
drivers/net/wireless/rtlwifi/rc.c
drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/led.c
drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/rtl8192cu/led.c
drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
drivers/net/wireless/rtlwifi/rtl8192se/dm.c
drivers/net/wireless/rtlwifi/rtl8192se/hw.c
drivers/net/wireless/rtlwifi/rtl8192se/led.c
drivers/net/wireless/rtlwifi/rtl8192se/phy.c
drivers/net/wireless/rtlwifi/rtl8192se/reg.h
drivers/net/wireless/rtlwifi/rtl8192se/rf.c
drivers/net/wireless/rtlwifi/rtl8192se/trx.c
drivers/net/wireless/rtlwifi/wifi.h
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_def.h
drivers/net/wireless/zd1211rw/zd_mac.c
drivers/net/wireless/zd1211rw/zd_mac.h
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/ssb/driver_chipcommon_pmu.c
drivers/ssb/driver_gige.c
drivers/ssb/driver_pcicore.c
drivers/ssb/main.c
drivers/ssb/pcihost_wrapper.c
include/linux/ath9k_platform.h
include/linux/bcma/bcma.h
include/linux/bcma/bcma_driver_pci.h
include/linux/netlink.h
include/net/bluetooth/bluetooth.h
include/net/bluetooth/hci.h
include/net/bluetooth/hci_core.h
include/net/bluetooth/l2cap.h
include/net/bluetooth/mgmt.h
include/net/bluetooth/rfcomm.h
include/net/bluetooth/smp.h
include/net/genetlink.h
include/net/mac80211.h
include/net/netlink.h
net/bluetooth/Kconfig
net/bluetooth/Makefile
net/bluetooth/cmtp/capi.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/smp.c [new file with mode: 0644]
net/mac80211/driver-ops.h
net/mac80211/driver-trace.h
net/mac80211/mlme.c
net/mac80211/pm.c
net/mac80211/scan.c
net/mac80211/util.c
net/netlink/af_netlink.c
net/wireless/mlme.c
net/wireless/nl80211.c

index 12a75ab..4228736 100644 (file)
@@ -13,8 +13,8 @@
 struct bcma_bus;
 
 /* main.c */
-extern int bcma_bus_register(struct bcma_bus *bus);
-extern void bcma_bus_unregister(struct bcma_bus *bus);
+int bcma_bus_register(struct bcma_bus *bus);
+void bcma_bus_unregister(struct bcma_bus *bus);
 
 /* scan.c */
 int bcma_bus_scan(struct bcma_bus *bus);
index ced379f..1ec7d45 100644 (file)
@@ -19,7 +19,7 @@ bool bcma_core_is_enabled(struct bcma_device *core)
 }
 EXPORT_SYMBOL_GPL(bcma_core_is_enabled);
 
-static void bcma_core_disable(struct bcma_device *core, u32 flags)
+void bcma_core_disable(struct bcma_device *core, u32 flags)
 {
        if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
                return;
@@ -31,6 +31,7 @@ static void bcma_core_disable(struct bcma_device *core, u32 flags)
        bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
        udelay(1);
 }
+EXPORT_SYMBOL_GPL(bcma_core_disable);
 
 int bcma_core_enable(struct bcma_device *core, u32 flags)
 {
index f44177a..dd5846b 100644 (file)
@@ -53,6 +53,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
                max_msk = 0xFFFF;
                break;
        case 43224:
+       case 43225:
                break;
        default:
                pr_err("PMU resource config unknown for device 0x%04X\n",
@@ -74,6 +75,7 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
        case 0x4313:
        case 0x4331:
        case 43224:
+       case 43225:
                break;
        default:
                pr_err("PMU switch/regulators init unknown for device "
@@ -96,11 +98,13 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
                if (bus->chipinfo.rev == 0) {
                        pr_err("Workarounds for 43224 rev 0 not fully "
                                "implemented\n");
-                       bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
+                       bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x00F000F0);
                } else {
                        bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0);
                }
                break;
+       case 43225:
+               break;
        default:
                pr_err("Workarounds unknown for device 0x%04X\n",
                        bus->chipinfo.id);
index 789d68b..b0c19ed 100644 (file)
@@ -184,3 +184,4 @@ int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
 out:
        return err;
 }
+EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl);
index 2a526bc..ac4bc62 100644 (file)
@@ -227,6 +227,7 @@ static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
        { 0, },
 };
index 11e96dc..ba15105 100644 (file)
@@ -160,13 +160,11 @@ int bcma_bus_register(struct bcma_bus *bus)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(bcma_bus_register);
 
 void bcma_bus_unregister(struct bcma_bus *bus)
 {
        bcma_unregister_cores(bus);
 }
-EXPORT_SYMBOL_GPL(bcma_bus_unregister);
 
 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 {
index 085560e..cced4fd 100644 (file)
@@ -2336,7 +2336,7 @@ static struct ssb_driver b44_ssb_driver = {
        .resume         = b44_resume,
 };
 
-static inline int b44_pci_init(void)
+static inline int __init b44_pci_init(void)
 {
        int err = 0;
 #ifdef CONFIG_B44_PCI
@@ -2345,7 +2345,7 @@ static inline int b44_pci_init(void)
        return err;
 }
 
-static inline void b44_pci_exit(void)
+static inline void __exit b44_pci_exit(void)
 {
 #ifdef CONFIG_B44_PCI
        ssb_pcihost_unregister(&b44_pci_driver);
index ea99827..c38e9e8 100644 (file)
@@ -219,6 +219,7 @@ static int ath_ahb_remove(struct platform_device *pdev)
 
        ath5k_deinit_softc(sc);
        platform_set_drvdata(pdev, NULL);
+       ieee80211_free_hw(hw);
 
        return 0;
 }
index bb50700..c4c02d5 100644 (file)
@@ -767,6 +767,7 @@ struct ath5k_athchan_2ghz {
  */
 
 #define AR5K_KEYCACHE_SIZE     8
+extern int ath5k_modparam_nohwcrypt;
 
 /***********************\
  HW RELATED DEFINITIONS
@@ -1180,8 +1181,8 @@ void ath5k_sysfs_unregister(struct ath5k_softc *sc);
 struct ath5k_buf;
 struct ath5k_txq;
 
-void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
+void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+bool ath5k_any_vif_assoc(struct ath5k_softc *sc);
 void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
                    struct ath5k_txq *txq);
 int ath5k_init_hw(struct ath5k_softc *sc);
@@ -1253,7 +1254,7 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
                int len, struct ieee80211_rate *rate, bool shortpre);
 unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah);
 unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah);
-extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
+int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode);
 void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class);
 /* RX filter control*/
 int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
index 779a1d2..fb05bf8 100644 (file)
@@ -88,8 +88,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 static int ath5k_init(struct ieee80211_hw *hw);
 static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
                                                                bool skip_pcu);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
 
 /* Known SREVs */
 static const struct ath5k_srev_name srev_names[] = {
@@ -2162,7 +2160,7 @@ ath5k_schedule_tx(struct ath5k_softc *sc)
        tasklet_schedule(&sc->txtq);
 }
 
-irqreturn_t
+static irqreturn_t
 ath5k_intr(int irq, void *dev_id)
 {
        struct ath5k_softc *sc = dev_id;
@@ -2616,7 +2614,7 @@ done:
        return ret;
 }
 
-static void stop_tasklets(struct ath5k_softc *sc)
+static void ath5k_stop_tasklets(struct ath5k_softc *sc)
 {
        sc->rx_pending = false;
        sc->tx_pending = false;
@@ -2670,7 +2668,7 @@ ath5k_stop_hw(struct ath5k_softc *sc)
        mmiowb();
        mutex_unlock(&sc->lock);
 
-       stop_tasklets(sc);
+       ath5k_stop_tasklets(sc);
 
        cancel_delayed_work_sync(&sc->tx_complete_work);
 
@@ -2698,7 +2696,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
 
        ath5k_hw_set_imr(ah, 0);
        synchronize_irq(sc->irq);
-       stop_tasklets(sc);
+       ath5k_stop_tasklets(sc);
 
        /* Save ani mode and disable ANI during
         * reset. If we don't we might get false
@@ -2963,11 +2961,12 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
         * state and potentially want to use them.
         */
        ath5k_hw_deinit(sc->ah);
+       kfree(sc->ah);
        free_irq(sc->irq, sc);
 }
 
 bool
-ath_any_vif_assoc(struct ath5k_softc *sc)
+ath5k_any_vif_assoc(struct ath5k_softc *sc)
 {
        struct ath5k_vif_iter_data iter_data;
        iter_data.hw_macaddr = NULL;
@@ -2981,7 +2980,7 @@ ath_any_vif_assoc(struct ath5k_softc *sc)
 }
 
 void
-set_beacon_filter(struct ieee80211_hw *hw, bool enable)
+ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable)
 {
        struct ath5k_softc *sc = hw->priv;
        struct ath5k_hw *ah = sc->ah;
index 807bd64..4939082 100644 (file)
@@ -46,8 +46,6 @@
 #include "base.h"
 #include "reg.h"
 
-extern int ath5k_modparam_nohwcrypt;
-
 /********************\
 * Mac80211 functions *
 \********************/
@@ -296,10 +294,10 @@ ath5k_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                if (bss_conf->assoc)
                        sc->assoc = bss_conf->assoc;
                else
-                       sc->assoc = ath_any_vif_assoc(sc);
+                       sc->assoc = ath5k_any_vif_assoc(sc);
 
                if (sc->opmode == NL80211_IFTYPE_STATION)
-                       set_beacon_filter(hw, sc->assoc);
+                       ath5k_set_beacon_filter(hw, sc->assoc);
                ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
                        AR5K_LED_ASSOC : AR5K_LED_INIT);
                if (bss_conf->assoc) {
index 126a4ea..1676a3e 100644 (file)
@@ -375,19 +375,19 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
 static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
 {
        u32 mask = flags ? flags : ~0U;
-       volatile u32 *reg;
+       volatile __iomem u32 *reg;
        u32 regval;
        u32 val = 0;
 
        /* ah->ah_mac_srev is not available at this point yet */
        if (ah->ah_sc->devid >= AR5K_SREV_AR2315_R6) {
-               reg = (u32 *) AR5K_AR2315_RESET;
+               reg = (u32 __iomem *) AR5K_AR2315_RESET;
                if (mask & AR5K_RESET_CTL_PCU)
                        val |= AR5K_AR2315_RESET_WMAC;
                if (mask & AR5K_RESET_CTL_BASEBAND)
                        val |= AR5K_AR2315_RESET_BB_WARM;
        } else {
-               reg = (u32 *) AR5K_AR5312_RESET;
+               reg = (u32 __iomem *) AR5K_AR5312_RESET;
                if (to_platform_device(ah->ah_sc->dev)->id == 0) {
                        if (mask & AR5K_RESET_CTL_PCU)
                                val |= AR5K_AR5312_RESET_WMAC0;
index 5b49cd0..0b36fcf 100644 (file)
@@ -26,6 +26,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
                .name = "ath9k",
                .driver_data = AR5416_AR9100_DEVID,
        },
+       {
+               .name = "ar933x_wmac",
+               .driver_data = AR9300_DEVID_AR9330,
+       },
        {
                .name = "ar934x_wmac",
                .driver_data = AR9300_DEVID_AR9340,
index ff8150e..1d09f22 100644 (file)
@@ -1461,7 +1461,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-               { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+               { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -2616,7 +2616,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 1) } },
 
-                { { CTL(60, 1), CTL(60, 0), CTL(0, 0), CTL(0, 0) } },
+                { { CTL(60, 1), CTL(60, 0), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
                 { { CTL(60, 0), CTL(60, 1), CTL(60, 0), CTL(60, 0) } },
 
@@ -3324,6 +3324,8 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
        read = ar9300_read_eeprom;
        if (AR_SREV_9485(ah))
                cptr = AR9300_BASE_ADDR_4K;
+       else if (AR_SREV_9330(ah))
+               cptr = AR9300_BASE_ADDR_512;
        else
                cptr = AR9300_BASE_ADDR;
        ath_dbg(common, ATH_DBG_EEPROM,
@@ -3442,7 +3444,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
 {
        int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
 
-       if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+       if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
                REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
        else {
                REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@@ -3523,7 +3525,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
                }
        }
 
-       if (AR_SREV_9485(ah)) {
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
                value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1);
                /*
                 * main_lnaconf, alt_lnaconf, main_tb, alt_tb
@@ -3710,7 +3712,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
 
        if (internal_regulator) {
-               if (AR_SREV_9485(ah)) {
+               if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
                        int reg_pmu_set;
 
                        reg_pmu_set = REG_READ(ah, AR_PHY_PMU2) & ~AR_PHY_PMU2_PGM;
@@ -3718,9 +3720,24 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                        if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
                                return;
 
-                       reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
-                                     (2 << 14) | (6 << 17) | (1 << 20) |
-                                     (3 << 24) | (1 << 28);
+                       if (AR_SREV_9330(ah)) {
+                               if (ah->is_clk_25mhz) {
+                                       reg_pmu_set = (3 << 1) | (8 << 4) |
+                                                     (3 << 8) | (1 << 14) |
+                                                     (6 << 17) | (1 << 20) |
+                                                     (3 << 24);
+                               } else {
+                                       reg_pmu_set = (4 << 1)  | (7 << 4) |
+                                                     (3 << 8)  | (1 << 14) |
+                                                     (6 << 17) | (1 << 20) |
+                                                     (3 << 24);
+                               }
+                       } else {
+                               reg_pmu_set = (5 << 1) | (7 << 4) |
+                                             (1 << 8) | (2 << 14) |
+                                             (6 << 17) | (1 << 20) |
+                                             (3 << 24) | (1 << 28);
+                       }
 
                        REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
                        if (!is_pmu_set(ah, AR_PHY_PMU1, reg_pmu_set))
@@ -3751,7 +3768,7 @@ static void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
                                           AR_RTC_REG_CONTROL1_SWREG_PROGRAM);
                }
        } else {
-               if (AR_SREV_9485(ah)) {
+               if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
                        REG_RMW_FIELD(ah, AR_PHY_PMU2, AR_PHY_PMU2_PGM, 0);
                        while (REG_READ_FIELD(ah, AR_PHY_PMU2,
                                              AR_PHY_PMU2_PGM))
@@ -3795,9 +3812,9 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
        ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
        ar9003_hw_drive_strength_apply(ah);
        ar9003_hw_atten_apply(ah, chan);
-       if (!AR_SREV_9340(ah))
+       if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah))
                ar9003_hw_internal_regulator_apply(ah);
-       if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+       if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
                ar9003_hw_apply_tuning_caps(ah);
 }
 
index 392bf0f..8efdec2 100644 (file)
@@ -19,6 +19,8 @@
 #include "ar9003_2p2_initvals.h"
 #include "ar9485_initvals.h"
 #include "ar9340_initvals.h"
+#include "ar9330_1p1_initvals.h"
+#include "ar9330_1p2_initvals.h"
 
 /* General hardware code for the AR9003 hadware family */
 
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-       if (AR_SREV_9340(ah)) {
+       if (AR_SREV_9330_11(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9331_1p1_mac_core,
+                               ARRAY_SIZE(ar9331_1p1_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9331_1p1_mac_postamble,
+                               ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9331_1p1_baseband_core,
+                               ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9331_1p1_baseband_postamble,
+                               ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9331_1p1_radio_core,
+                               ARRAY_SIZE(ar9331_1p1_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9331_1p1_soc_preamble,
+                               ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9331_1p1_soc_postamble,
+                               ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p1,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p1,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+                       5);
+
+               /* additional clock settings */
+               if (ah->is_clk_25mhz)
+                       INIT_INI_ARRAY(&ah->iniModesAdditional,
+                                       ar9331_1p1_xtal_25M,
+                                       ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesAdditional,
+                                       ar9331_1p1_xtal_40M,
+                                       ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
+       } else if (AR_SREV_9330_12(ah)) {
+               /* mac */
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+                               ar9331_1p2_mac_core,
+                               ARRAY_SIZE(ar9331_1p2_mac_core), 2);
+               INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+                               ar9331_1p2_mac_postamble,
+                               ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
+
+               /* bb */
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+                               ar9331_1p2_baseband_core,
+                               ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
+               INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+                               ar9331_1p2_baseband_postamble,
+                               ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
+
+               /* radio */
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+                               ar9331_1p2_radio_core,
+                               ARRAY_SIZE(ar9331_1p2_radio_core), 2);
+               INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
+
+               /* soc */
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+                               ar9331_1p2_soc_preamble,
+                               ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+               INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
+                               ar9331_1p2_soc_postamble,
+                               ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
+
+               /* rx/tx gain */
+               INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_rx_gain_1p2,
+                               ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
+               INIT_INI_ARRAY(&ah->iniModesTxGain,
+                       ar9331_modes_lowest_ob_db_tx_gain_1p2,
+                       ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+                       5);
+
+               /* additional clock settings */
+               if (ah->is_clk_25mhz)
+                       INIT_INI_ARRAY(&ah->iniModesAdditional,
+                                       ar9331_1p2_xtal_25M,
+                                       ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
+               else
+                       INIT_INI_ARRAY(&ah->iniModesAdditional,
+                                       ar9331_1p2_xtal_40M,
+                                       ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
+       } else if (AR_SREV_9340(ah)) {
                /* mac */
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
                INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -220,7 +328,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
        switch (ar9003_hw_get_tx_gain_idx(ah)) {
        case 0:
        default:
-               if (AR_SREV_9340(ah))
+               if (AR_SREV_9330_12(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_lowest_ob_db_tx_gain_1p2,
+                               ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
+                               5);
+               else if (AR_SREV_9330_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_lowest_ob_db_tx_gain_1p1,
+                               ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
+                               5);
+               else if (AR_SREV_9340(ah))
                        INIT_INI_ARRAY(&ah->iniModesTxGain,
                                        ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
                                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -237,7 +355,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
                                       5);
                break;
        case 1:
-               if (AR_SREV_9340(ah))
+               if (AR_SREV_9330_12(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_high_ob_db_tx_gain_1p2,
+                               ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
+                               5);
+               else if (AR_SREV_9330_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_high_ob_db_tx_gain_1p1,
+                               ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
+                               5);
+               else if (AR_SREV_9340(ah))
                        INIT_INI_ARRAY(&ah->iniModesTxGain,
                                        ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
                                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -254,7 +382,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
                                       5);
                break;
        case 2:
-               if (AR_SREV_9340(ah))
+               if (AR_SREV_9330_12(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_low_ob_db_tx_gain_1p2,
+                               ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
+                               5);
+               else if (AR_SREV_9330_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_low_ob_db_tx_gain_1p1,
+                               ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
+                               5);
+               else if (AR_SREV_9340(ah))
                        INIT_INI_ARRAY(&ah->iniModesTxGain,
                                        ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
                                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -271,7 +409,17 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
                                       5);
                break;
        case 3:
-               if (AR_SREV_9340(ah))
+               if (AR_SREV_9330_12(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_high_power_tx_gain_1p2,
+                               ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
+                               5);
+               else if (AR_SREV_9330_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesTxGain,
+                               ar9331_modes_high_power_tx_gain_1p1,
+                               ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
+                               5);
+               else if (AR_SREV_9340(ah))
                        INIT_INI_ARRAY(&ah->iniModesTxGain,
                                        ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
                                       ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
@@ -295,7 +443,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
        switch (ar9003_hw_get_rx_gain_idx(ah)) {
        case 0:
        default:
-               if (AR_SREV_9340(ah))
+               if (AR_SREV_9330_12(ah))
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                                       ar9331_common_rx_gain_1p2,
+                                       ARRAY_SIZE(ar9331_common_rx_gain_1p2),
+                                       2);
+               else if (AR_SREV_9330_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                                       ar9331_common_rx_gain_1p1,
+                                       ARRAY_SIZE(ar9331_common_rx_gain_1p1),
+                                       2);
+               else if (AR_SREV_9340(ah))
                        INIT_INI_ARRAY(&ah->iniModesRxGain,
                                       ar9340Common_rx_gain_table_1p0,
                                       ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
@@ -312,7 +470,17 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
                                       2);
                break;
        case 1:
-               if (AR_SREV_9340(ah))
+               if (AR_SREV_9330_12(ah))
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_wo_xlna_rx_gain_1p2,
+                               ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
+                               2);
+               else if (AR_SREV_9330_11(ah))
+                       INIT_INI_ARRAY(&ah->iniModesRxGain,
+                               ar9331_common_wo_xlna_rx_gain_1p1,
+                               ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
+                               2);
+               else if (AR_SREV_9340(ah))
                        INIT_INI_ARRAY(&ah->iniModesRxGain,
                                       ar9340Common_wo_xlna_rx_gain_table_1p0,
                                       ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
index 2e7f0f2..8f6d11d 100644 (file)
@@ -83,7 +83,23 @@ static int ar9003_get_training_power_5g(struct ath_hw *ah)
        if (delta > scale)
                return -1;
 
-       power += 2 * get_streams(common->tx_chainmask);
+       switch (get_streams(common->tx_chainmask)) {
+       case 1:
+               delta = 6;
+               break;
+       case 2:
+               delta = 4;
+               break;
+       case 3:
+               delta = 2;
+               break;
+       default:
+               delta = 0;
+               ath_dbg(common, ATH_DBG_CALIBRATE,
+               "Invalid tx-chainmask: %u\n", common->tx_chainmask);
+       }
+
+       power += delta;
        return power;
 }
 
@@ -785,7 +801,26 @@ EXPORT_SYMBOL(ar9003_paprd_init_table);
 
 bool ar9003_paprd_is_done(struct ath_hw *ah)
 {
-       return !!REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+       int paprd_done, agc2_pwr;
+       paprd_done = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
                                AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
+
+       if (paprd_done == 0x1) {
+               agc2_pwr = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_STAT1,
+                               AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_AGC2_PWR);
+
+               ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
+                       "AGC2_PWR = 0x%x training done = 0x%x\n",
+                       agc2_pwr, paprd_done);
+       /*
+        * agc2_pwr range should not be less than 'IDEAL_AGC2_PWR_CHANGE'
+        * when the training is completely done, otherwise retraining is
+        * done to make sure the value is in ideal range
+        */
+               if (agc2_pwr <= PAPRD_IDEAL_AGC2_PWR_RANGE)
+                       paprd_done = 0;
+       }
+
+       return !!paprd_done;
 }
 EXPORT_SYMBOL(ar9003_paprd_is_done);
index 892c48b..1baca8e 100644 (file)
@@ -75,7 +75,19 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
        freq = centers.synth_center;
 
        if (freq < 4800) {     /* 2 GHz, fractional mode */
-               if (AR_SREV_9485(ah)) {
+               if (AR_SREV_9330(ah)) {
+                       u32 chan_frac;
+                       u32 div;
+
+                       if (ah->is_clk_25mhz)
+                               div = 75;
+                       else
+                               div = 120;
+
+                       channelSel = (freq * 4) / div;
+                       chan_frac = (((freq * 4) % div) * 0x20000) / div;
+                       channelSel = (channelSel << 17) | chan_frac;
+               } else if (AR_SREV_9485(ah)) {
                        u32 chan_frac;
 
                        /*
@@ -104,7 +116,7 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
                        u32 chan_frac;
 
                        channelSel = (freq * 2) / 75;
-                       chan_frac = ((freq % 75) * 0x20000) / 75;
+                       chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
                        channelSel = (channelSel << 17) | chan_frac;
                } else {
                        channelSel = CHANSEL_5G(freq);
@@ -168,7 +180,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
         * is out-of-band and can be ignored.
         */
 
-       if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) {
+       if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah)) {
                spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah,
                                                         IS_CHAN_2GHZ(chan));
                if (spur_fbin_ptr[0] == 0) /* No spur */
@@ -193,7 +205,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
 
        for (i = 0; i < max_spur_cnts; i++) {
                negative = 0;
-               if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+               if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
                        cur_bb_spur = FBIN2FREQ(spur_fbin_ptr[i],
                                        IS_CHAN_2GHZ(chan)) - synth_freq;
                else
@@ -659,6 +671,9 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
                REG_WRITE_ARRAY(&ah->iniModesAdditional,
                                modesIndex, regWrites);
 
+       if (AR_SREV_9300(ah))
+               REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
+
        if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
                REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
 
@@ -1074,7 +1089,10 @@ static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
 {
        ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
        ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
-       ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
+       if (AR_SREV_9330(ah))
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9330_2GHZ;
+       else
+               ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
        ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
        ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
        ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
@@ -1196,8 +1214,17 @@ static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah,
                                 AR_PHY_9485_ANT_DIV_ALT_LNACONF_S;
        antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >>
                                  AR_PHY_9485_ANT_FAST_DIV_BIAS_S;
-       antconf->lna1_lna2_delta = -9;
-       antconf->div_group = 2;
+
+       if (AR_SREV_9330_11(ah)) {
+               antconf->lna1_lna2_delta = -9;
+               antconf->div_group = 1;
+       } else if (AR_SREV_9485(ah)) {
+               antconf->lna1_lna2_delta = -9;
+               antconf->div_group = 2;
+       } else {
+               antconf->lna1_lna2_delta = -3;
+               antconf->div_group = 0;
+       }
 }
 
 static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah,
index 443090d..9eb3aa2 100644 (file)
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ     -95
 #define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ     -100
 
+#define AR_PHY_CCA_NOM_VAL_9330_2GHZ          -118
+
 /*
  * AGC Field Definitions
  */
 #define AR_PHY_65NM_CH2_RXTX1       0x16900
 #define AR_PHY_65NM_CH2_RXTX2       0x16904
 
-#define AR_CH0_TOP2 (AR_SREV_9485(ah) ? 0x00016284 : 0x0001628c)
+#define AR_CH0_TOP2            (AR_SREV_9300(ah) ? 0x1628c : 0x16284)
 #define AR_CH0_TOP2_XPABIASLVL         0xf000
 #define AR_CH0_TOP2_XPABIASLVL_S       12
 
-#define AR_CH0_XTAL            (AR_SREV_9485(ah) ? 0x16290 : 0x16294)
+#define AR_CH0_XTAL            (AR_SREV_9300(ah) ? 0x16294 : 0x16290)
 #define AR_CH0_XTAL_CAPINDAC   0x7f000000
 #define AR_CH0_XTAL_CAPINDAC_S 24
 #define AR_CH0_XTAL_CAPOUTDAC  0x00fe0000
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p1_initvals.h
new file mode 100644 (file)
index 0000000..f11d9b2
--- /dev/null
@@ -0,0 +1,1147 @@
+/*
+ * Copyright (c) 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 INITVALS_9330_1P1_H
+#define INITVALS_9330_1P1_H
+
+static const u32 ar9331_1p1_baseband_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p1[][5] = {
+       /*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p1[][5] = {
+       /*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52, 0xffaa9a52},
+       {0x0000a2e0, 0xffb31c84, 0xffb31c84, 0xffb31c84, 0xffb31c84},
+       {0x0000a2e4, 0xff43e000, 0xff43e000, 0xff43e000, 0xff43e000},
+       {0x0000a2e8, 0xfffc0000, 0xfffc0000, 0xfffc0000, 0xfffc0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3d001620, 0x3d001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x3f001621, 0x3f001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x42001640, 0x42001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x44001641, 0x44001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x46001642, 0x46001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49001644, 0x49001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4c001a81, 0x4c001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4f001a83, 0x4f001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x52001c84, 0x52001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001ce3, 0x55001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x59001ce5, 0x59001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5d001ce9, 0x5d001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x64001eec, 0x64001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x64001eec, 0x64001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x64001eec, 0x64001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x0280ca03, 0x0280ca03, 0x0280ca03, 0x0280ca03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04015005, 0x04015005, 0x04015005, 0x04015005},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p1[][5] = {
+       /*   Addr     5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_baseband_core_txfir_coeff_japan_2484[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x6f7f0301},
+       {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p1_xtal_25M[][2] = {
+       /* Addr      allmodes  */
+       {0x00007038, 0x000002f8},
+       {0x00008244, 0x0010f3d7},
+       {0x0000824c, 0x0001e7ae},
+       {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p1_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73800000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x00016044, 0x03db62db},
+       {0x00016048, 0x6c924268},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x4db6db8c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f081c},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd411eb84},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160ac, 0x24651800},
+       {0x000160b0, 0x03284f3e},
+       {0x000160b4, 0x92480040},
+       {0x000160c0, 0x006db6db},
+       {0x000160c4, 0x0186db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6de6c300},
+       {0x000160d0, 0x14500820},
+       {0x00016100, 0x04cb0001},
+       {0x00016104, 0xfff80015},
+       {0x00016108, 0x00080010},
+       {0x0001610c, 0x00170000},
+       {0x00016140, 0x10804000},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x01000015},
+       {0x00016284, 0x14d20000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016290, 0x4b96210f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+};
+
+static const u32 ar9331_1p1_soc_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00060005},
+       {0x0000a004, 0x00810080},
+       {0x0000a008, 0x00830082},
+       {0x0000a00c, 0x00850084},
+       {0x0000a010, 0x01820181},
+       {0x0000a014, 0x01840183},
+       {0x0000a018, 0x01880185},
+       {0x0000a01c, 0x018a0189},
+       {0x0000a020, 0x02850284},
+       {0x0000a024, 0x02890288},
+       {0x0000a028, 0x028b028a},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x24242428},
+       {0x0000a098, 0x171e1e1e},
+       {0x0000a09c, 0x02020b0b},
+       {0x0000a0a0, 0x02020202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x22072208},
+       {0x0000a0c4, 0x22052206},
+       {0x0000a0c8, 0x22032204},
+       {0x0000a0cc, 0x22012202},
+       {0x0000a0d0, 0x221f2200},
+       {0x0000a0d4, 0x221d221e},
+       {0x0000a0d8, 0x33023303},
+       {0x0000a0dc, 0x33003301},
+       {0x0000a0e0, 0x331e331f},
+       {0x0000a0e4, 0x4402331d},
+       {0x0000a0e8, 0x44004401},
+       {0x0000a0ec, 0x441e441f},
+       {0x0000a0f0, 0x55025503},
+       {0x0000a0f4, 0x55005501},
+       {0x0000a0f8, 0x551e551f},
+       {0x0000a0fc, 0x6602551d},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p1_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a8f6b},
+       {0x0000980c, 0x04800000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x5f3ca3de},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14750600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0x00000000},
+       {0x00009c08, 0x03200000},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x1883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c00400},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038233c},
+       {0x00009e24, 0x9927b515},
+       {0x00009e28, 0x12ef0200},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2dc, 0x00000000},
+       {0x0000a2e0, 0x00000000},
+       {0x0000a2e4, 0x00000000},
+       {0x0000a2e8, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0cdbd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00000000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x04000000},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p1[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
+       {0x0000a2dc, 0xffff2a52, 0xffff2a52, 0xffff2a52, 0xffff2a52},
+       {0x0000a2e0, 0xffffcc84, 0xffffcc84, 0xffffcc84, 0xffffcc84},
+       {0x0000a2e4, 0xfffff000, 0xfffff000, 0xfffff000, 0xfffff000},
+       {0x0000a2e8, 0xfffe0000, 0xfffe0000, 0xfffe0000, 0xfffe0000},
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d0, 0x000050d0},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x2d000a20, 0x2d000a20},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000a22, 0x31000a22},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000a24, 0x35000a24},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x38000a43, 0x38000a43},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x3b000e42, 0x3b000e42},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x3f000e44, 0x3f000e44},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x42000e64, 0x42000e64},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x46000e66, 0x46000e66},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x4a000ea6, 0x4a000ea6},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0280c802, 0x0280c802, 0x0280c802, 0x0280c802},
+       {0x0000a624, 0x03010a03, 0x03010a03, 0x03010a03, 0x03010a03},
+       {0x0000a628, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a62c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a630, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a634, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a638, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x0000a63c, 0x03010c04, 0x03010c04, 0x03010c04, 0x03010c04},
+       {0x00016044, 0x034922db, 0x034922db, 0x034922db, 0x034922db},
+       {0x00016284, 0x14d3f000, 0x14d3f000, 0x14d3f000, 0x14d3f000},
+};
+
+static const u32 ar9331_1p1_mac_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9331_1p1_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p1_xtal_40M[][2] = {
+       /* Addr      allmodes  */
+       {0x00007038, 0x000004c2},
+       {0x00008244, 0x0010f400},
+       {0x0000824c, 0x0001e800},
+       {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p1_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486200},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008248, 0x00000800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9d400010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p1[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x00830082},
+       {0x0000a014, 0x01810180},
+       {0x0000a018, 0x01830182},
+       {0x0000a01c, 0x01850184},
+       {0x0000a020, 0x01890188},
+       {0x0000a024, 0x018b018a},
+       {0x0000a028, 0x018d018c},
+       {0x0000a02c, 0x01910190},
+       {0x0000a030, 0x01930192},
+       {0x0000a034, 0x01950194},
+       {0x0000a038, 0x038a0196},
+       {0x0000a03c, 0x038c038b},
+       {0x0000a040, 0x0390038d},
+       {0x0000a044, 0x03920391},
+       {0x0000a048, 0x03940393},
+       {0x0000a04c, 0x03960395},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x22222229},
+       {0x0000a084, 0x1d1d1d1d},
+       {0x0000a088, 0x1d1d1d1d},
+       {0x0000a08c, 0x1d1d1d1d},
+       {0x0000a090, 0x171d1d1d},
+       {0x0000a094, 0x11111717},
+       {0x0000a098, 0x00030311},
+       {0x0000a09c, 0x00000000},
+       {0x0000a0a0, 0x00000000},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x01000101},
+       {0x0000a0c8, 0x011e011f},
+       {0x0000a0cc, 0x011c011d},
+       {0x0000a0d0, 0x02030204},
+       {0x0000a0d4, 0x02010202},
+       {0x0000a0d8, 0x021f0200},
+       {0x0000a0dc, 0x0302021e},
+       {0x0000a0e0, 0x03000301},
+       {0x0000a0e4, 0x031e031f},
+       {0x0000a0e8, 0x0402031d},
+       {0x0000a0ec, 0x04000401},
+       {0x0000a0f0, 0x041e041f},
+       {0x0000a0f4, 0x0502041d},
+       {0x0000a0f8, 0x05000501},
+       {0x0000a0fc, 0x051e051f},
+       {0x0000a100, 0x06010602},
+       {0x0000a104, 0x061f0600},
+       {0x0000a108, 0x061d061e},
+       {0x0000a10c, 0x07020703},
+       {0x0000a110, 0x07000701},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x01000101},
+       {0x0000a148, 0x011e011f},
+       {0x0000a14c, 0x011c011d},
+       {0x0000a150, 0x02030204},
+       {0x0000a154, 0x02010202},
+       {0x0000a158, 0x021f0200},
+       {0x0000a15c, 0x0302021e},
+       {0x0000a160, 0x03000301},
+       {0x0000a164, 0x031e031f},
+       {0x0000a168, 0x0402031d},
+       {0x0000a16c, 0x04000401},
+       {0x0000a170, 0x041e041f},
+       {0x0000a174, 0x0502041d},
+       {0x0000a178, 0x05000501},
+       {0x0000a17c, 0x051e051f},
+       {0x0000a180, 0x06010602},
+       {0x0000a184, 0x061f0600},
+       {0x0000a188, 0x061d061e},
+       {0x0000a18c, 0x07020703},
+       {0x0000a190, 0x07000701},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000196},
+};
+
+static const u32 ar9331_common_tx_gain_offset1_1[][1] = {
+       {0},
+       {3},
+       {0},
+       {0},
+};
+
+static const u32 ar9331_1p1_chansel_xtal_25M[] = {
+       0x0101479e,
+       0x0101d027,
+       0x010258af,
+       0x0102e138,
+       0x010369c0,
+       0x0103f249,
+       0x01047ad1,
+       0x0105035a,
+       0x01058be2,
+       0x0106146b,
+       0x01069cf3,
+       0x0107257c,
+       0x0107ae04,
+       0x0108f5b2,
+};
+
+static const u32 ar9331_1p1_chansel_xtal_40M[] = {
+       0x00a0ccbe,
+       0x00a12213,
+       0x00a17769,
+       0x00a1ccbe,
+       0x00a22213,
+       0x00a27769,
+       0x00a2ccbe,
+       0x00a32213,
+       0x00a37769,
+       0x00a3ccbe,
+       0x00a42213,
+       0x00a47769,
+       0x00a4ccbe,
+       0x00a5998b,
+};
+
+#endif /* INITVALS_9330_1P1_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9330_1p2_initvals.h
new file mode 100644 (file)
index 0000000..0e6ca08
--- /dev/null
@@ -0,0 +1,1080 @@
+/*
+ * Copyright (c) 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 INITVALS_9330_1P2_H
+#define INITVALS_9330_1P2_H
+
+static const u32 ar9331_modes_lowest_ob_db_tx_gain_1p2[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+       {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+       {0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+       {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+       {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+       {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+       {0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+       {0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+       {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a4, 0x037216a4},
+       {0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+       {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+       {0x00009e10, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e},
+       {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+       {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+       {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+       {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
+       {0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222},
+       {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+       {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+       {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+       {0x0000a204, 0x00003fc0, 0x00003fc4, 0x00003fc4, 0x00003fc0},
+       {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+       {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
+       {0x0000a234, 0x00000fff, 0x00000fff, 0x10000fff, 0x00000fff},
+       {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+       {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+       {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+       {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+       {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+       {0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+       {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+       {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+       {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+       {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
+       {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+       {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000ae04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+       {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9331_modes_high_ob_db_tx_gain_1p2[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+       {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_modes_low_ob_db_tx_gain_1p2[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+       {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_baseband_core_txfir_coeff_japan_2484[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a398, 0x00000000},
+       {0x0000a39c, 0x6f7f0301},
+       {0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9331_1p2_xtal_25M[][2] = {
+       /* Addr      allmodes  */
+       {0x00007038, 0x000002f8},
+       {0x00008244, 0x0010f3d7},
+       {0x0000824c, 0x0001e7ae},
+       {0x0001609c, 0x0f508f29},
+};
+
+static const u32 ar9331_1p2_radio_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00016000, 0x36db6db6},
+       {0x00016004, 0x6db6db40},
+       {0x00016008, 0x73800000},
+       {0x0001600c, 0x00000000},
+       {0x00016040, 0x7f80fff8},
+       {0x00016044, 0x03d6d2db},
+       {0x00016048, 0x6c924268},
+       {0x0001604c, 0x000f0278},
+       {0x00016050, 0x4db6db8c},
+       {0x00016054, 0x6db60000},
+       {0x00016080, 0x00080000},
+       {0x00016084, 0x0e48048c},
+       {0x00016088, 0x14214514},
+       {0x0001608c, 0x119f081c},
+       {0x00016090, 0x24926490},
+       {0x00016098, 0xd411eb84},
+       {0x000160a0, 0xc2108ffe},
+       {0x000160a4, 0x812fc370},
+       {0x000160a8, 0x423c8000},
+       {0x000160ac, 0x24651800},
+       {0x000160b0, 0x03284f3e},
+       {0x000160b4, 0x92480040},
+       {0x000160c0, 0x006db6db},
+       {0x000160c4, 0x0186db60},
+       {0x000160c8, 0x6db6db6c},
+       {0x000160cc, 0x6de6c300},
+       {0x000160d0, 0x14500820},
+       {0x00016100, 0x04cb0001},
+       {0x00016104, 0xfff80015},
+       {0x00016108, 0x00080010},
+       {0x0001610c, 0x00170000},
+       {0x00016140, 0x10804000},
+       {0x00016144, 0x01884080},
+       {0x00016148, 0x000080c0},
+       {0x00016280, 0x01000015},
+       {0x00016284, 0x14d20000},
+       {0x00016288, 0x00318000},
+       {0x0001628c, 0x50000000},
+       {0x00016290, 0x4b96210f},
+       {0x00016380, 0x00000000},
+       {0x00016384, 0x00000000},
+       {0x00016388, 0x00800700},
+       {0x0001638c, 0x00800700},
+       {0x00016390, 0x00800700},
+       {0x00016394, 0x00000000},
+       {0x00016398, 0x00000000},
+       {0x0001639c, 0x00000000},
+       {0x000163a0, 0x00000001},
+       {0x000163a4, 0x00000001},
+       {0x000163a8, 0x00000000},
+       {0x000163ac, 0x00000000},
+       {0x000163b0, 0x00000000},
+       {0x000163b4, 0x00000000},
+       {0x000163b8, 0x00000000},
+       {0x000163bc, 0x00000000},
+       {0x000163c0, 0x000000a0},
+       {0x000163c4, 0x000c0000},
+       {0x000163c8, 0x14021402},
+       {0x000163cc, 0x00001402},
+       {0x000163d0, 0x00000000},
+       {0x000163d4, 0x00000000},
+};
+
+static const u32 ar9331_1p2_soc_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00007010, 0x00000022, 0x00000022, 0x00000022, 0x00000022},
+};
+
+static const u32 ar9331_common_wo_xlna_rx_gain_1p2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00060005},
+       {0x0000a004, 0x00810080},
+       {0x0000a008, 0x00830082},
+       {0x0000a00c, 0x00850084},
+       {0x0000a010, 0x01820181},
+       {0x0000a014, 0x01840183},
+       {0x0000a018, 0x01880185},
+       {0x0000a01c, 0x018a0189},
+       {0x0000a020, 0x02850284},
+       {0x0000a024, 0x02890288},
+       {0x0000a028, 0x028b028a},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x24242428},
+       {0x0000a098, 0x171e1e1e},
+       {0x0000a09c, 0x02020b0b},
+       {0x0000a0a0, 0x02020202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x22072208},
+       {0x0000a0c4, 0x22052206},
+       {0x0000a0c8, 0x22032204},
+       {0x0000a0cc, 0x22012202},
+       {0x0000a0d0, 0x221f2200},
+       {0x0000a0d4, 0x221d221e},
+       {0x0000a0d8, 0x33023303},
+       {0x0000a0dc, 0x33003301},
+       {0x0000a0e0, 0x331e331f},
+       {0x0000a0e4, 0x4402331d},
+       {0x0000a0e8, 0x44004401},
+       {0x0000a0ec, 0x441e441f},
+       {0x0000a0f0, 0x55025503},
+       {0x0000a0f4, 0x55005501},
+       {0x0000a0f8, 0x551e551f},
+       {0x0000a0fc, 0x6602551d},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9331_1p2_baseband_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00009800, 0xafe68e30},
+       {0x00009804, 0xfd14e000},
+       {0x00009808, 0x9c0a8f6b},
+       {0x0000980c, 0x04800000},
+       {0x00009814, 0x9280c00a},
+       {0x00009818, 0x00000000},
+       {0x0000981c, 0x00020028},
+       {0x00009834, 0x5f3ca3de},
+       {0x00009838, 0x0108ecff},
+       {0x0000983c, 0x14750600},
+       {0x00009880, 0x201fff00},
+       {0x00009884, 0x00001042},
+       {0x000098a4, 0x00200400},
+       {0x000098b0, 0x32840bbe},
+       {0x000098d0, 0x004b6a8e},
+       {0x000098d4, 0x00000820},
+       {0x000098dc, 0x00000000},
+       {0x000098f0, 0x00000000},
+       {0x000098f4, 0x00000000},
+       {0x00009c04, 0x00000000},
+       {0x00009c08, 0x03200000},
+       {0x00009c0c, 0x00000000},
+       {0x00009c10, 0x00000000},
+       {0x00009c14, 0x00046384},
+       {0x00009c18, 0x05b6b440},
+       {0x00009c1c, 0x00b6b440},
+       {0x00009d00, 0xc080a333},
+       {0x00009d04, 0x40206c10},
+       {0x00009d08, 0x009c4060},
+       {0x00009d0c, 0x1883800a},
+       {0x00009d10, 0x01834061},
+       {0x00009d14, 0x00c00400},
+       {0x00009d18, 0x00000000},
+       {0x00009e08, 0x0038233c},
+       {0x00009e24, 0x9927b515},
+       {0x00009e28, 0x12ef0200},
+       {0x00009e30, 0x06336f77},
+       {0x00009e34, 0x6af6532f},
+       {0x00009e38, 0x0cc80c00},
+       {0x00009e40, 0x0d261820},
+       {0x00009e4c, 0x00001004},
+       {0x00009e50, 0x00ff03f1},
+       {0x00009fc0, 0x803e4788},
+       {0x00009fc4, 0x0001efb5},
+       {0x00009fcc, 0x40000014},
+       {0x0000a20c, 0x00000000},
+       {0x0000a220, 0x00000000},
+       {0x0000a224, 0x00000000},
+       {0x0000a228, 0x10002310},
+       {0x0000a23c, 0x00000000},
+       {0x0000a244, 0x0c000000},
+       {0x0000a2a0, 0x00000001},
+       {0x0000a2c0, 0x00000001},
+       {0x0000a2c8, 0x00000000},
+       {0x0000a2cc, 0x18c43433},
+       {0x0000a2d4, 0x00000000},
+       {0x0000a2dc, 0x00000000},
+       {0x0000a2e0, 0x00000000},
+       {0x0000a2e4, 0x00000000},
+       {0x0000a2e8, 0x00000000},
+       {0x0000a2ec, 0x00000000},
+       {0x0000a2f0, 0x00000000},
+       {0x0000a2f4, 0x00000000},
+       {0x0000a2f8, 0x00000000},
+       {0x0000a344, 0x00000000},
+       {0x0000a34c, 0x00000000},
+       {0x0000a350, 0x0000a000},
+       {0x0000a364, 0x00000000},
+       {0x0000a370, 0x00000000},
+       {0x0000a390, 0x00000001},
+       {0x0000a394, 0x00000444},
+       {0x0000a398, 0x001f0e0f},
+       {0x0000a39c, 0x0075393f},
+       {0x0000a3a0, 0xb79f6427},
+       {0x0000a3a4, 0x00000000},
+       {0x0000a3a8, 0xaaaaaaaa},
+       {0x0000a3ac, 0x3c466478},
+       {0x0000a3c0, 0x20202020},
+       {0x0000a3c4, 0x22222220},
+       {0x0000a3c8, 0x20200020},
+       {0x0000a3cc, 0x20202020},
+       {0x0000a3d0, 0x20202020},
+       {0x0000a3d4, 0x20202020},
+       {0x0000a3d8, 0x20202020},
+       {0x0000a3dc, 0x20202020},
+       {0x0000a3e0, 0x20202020},
+       {0x0000a3e4, 0x20202020},
+       {0x0000a3e8, 0x20202020},
+       {0x0000a3ec, 0x20202020},
+       {0x0000a3f0, 0x00000000},
+       {0x0000a3f4, 0x00000006},
+       {0x0000a3f8, 0x0cdbd380},
+       {0x0000a3fc, 0x000f0f01},
+       {0x0000a400, 0x8fa91f01},
+       {0x0000a404, 0x00000000},
+       {0x0000a408, 0x0e79e5c6},
+       {0x0000a40c, 0x00820820},
+       {0x0000a414, 0x1ce739ce},
+       {0x0000a418, 0x2d001dce},
+       {0x0000a41c, 0x1ce739ce},
+       {0x0000a420, 0x000001ce},
+       {0x0000a424, 0x1ce739ce},
+       {0x0000a428, 0x000001ce},
+       {0x0000a42c, 0x1ce739ce},
+       {0x0000a430, 0x1ce739ce},
+       {0x0000a434, 0x00000000},
+       {0x0000a438, 0x00001801},
+       {0x0000a43c, 0x00000000},
+       {0x0000a440, 0x00000000},
+       {0x0000a444, 0x00000000},
+       {0x0000a448, 0x04000000},
+       {0x0000a44c, 0x00000001},
+       {0x0000a450, 0x00010000},
+       {0x0000a458, 0x00000000},
+       {0x0000a640, 0x00000000},
+       {0x0000a644, 0x3fad9d74},
+       {0x0000a648, 0x0048060a},
+       {0x0000a64c, 0x00003c37},
+       {0x0000a670, 0x03020100},
+       {0x0000a674, 0x09080504},
+       {0x0000a678, 0x0d0c0b0a},
+       {0x0000a67c, 0x13121110},
+       {0x0000a680, 0x31301514},
+       {0x0000a684, 0x35343332},
+       {0x0000a688, 0x00000036},
+       {0x0000a690, 0x00000838},
+       {0x0000a7c0, 0x00000000},
+       {0x0000a7c4, 0xfffffffc},
+       {0x0000a7c8, 0x00000000},
+       {0x0000a7cc, 0x00000000},
+       {0x0000a7d0, 0x00000000},
+       {0x0000a7d4, 0x00000004},
+       {0x0000a7dc, 0x00000001},
+};
+
+static const u32 ar9331_modes_high_power_tx_gain_1p2[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x0000a410, 0x000050d7, 0x000050d7, 0x000050d7, 0x000050d7},
+       {0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+       {0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+       {0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+       {0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+       {0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+       {0x0000a520, 0x2f001f04, 0x2f001f04, 0x23000a00, 0x23000a00},
+       {0x0000a524, 0x35001fc4, 0x35001fc4, 0x27000a02, 0x27000a02},
+       {0x0000a528, 0x3c022f04, 0x3c022f04, 0x2b000a04, 0x2b000a04},
+       {0x0000a52c, 0x41023e85, 0x41023e85, 0x3f001620, 0x3f001620},
+       {0x0000a530, 0x48023ec6, 0x48023ec6, 0x41001621, 0x41001621},
+       {0x0000a534, 0x4d023f01, 0x4d023f01, 0x44001640, 0x44001640},
+       {0x0000a538, 0x53023f4b, 0x53023f4b, 0x46001641, 0x46001641},
+       {0x0000a53c, 0x5a027f09, 0x5a027f09, 0x48001642, 0x48001642},
+       {0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x4b001644, 0x4b001644},
+       {0x0000a544, 0x6502feca, 0x6502feca, 0x4e001a81, 0x4e001a81},
+       {0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x51001a83, 0x51001a83},
+       {0x0000a54c, 0x7203feca, 0x7203feca, 0x54001c84, 0x54001c84},
+       {0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x57001ce3, 0x57001ce3},
+       {0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x5b001ce5, 0x5b001ce5},
+       {0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5f001ce9, 0x5f001ce9},
+       {0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x66001eec, 0x66001eec},
+       {0x0000a560, 0x900fff0b, 0x900fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a564, 0x960fffcb, 0x960fffcb, 0x66001eec, 0x66001eec},
+       {0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x66001eec, 0x66001eec},
+       {0x0000a580, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+       {0x0000a584, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+       {0x0000a588, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+       {0x0000a58c, 0x11062202, 0x11062202, 0x0b000200, 0x0b000200},
+       {0x0000a590, 0x17022e00, 0x17022e00, 0x0f000202, 0x0f000202},
+       {0x0000a594, 0x1d000ec2, 0x1d000ec2, 0x11000400, 0x11000400},
+       {0x0000a598, 0x25020ec0, 0x25020ec0, 0x15000402, 0x15000402},
+       {0x0000a59c, 0x2b020ec3, 0x2b020ec3, 0x19000404, 0x19000404},
+       {0x0000a5a0, 0x2f001f04, 0x2f001f04, 0x1b000603, 0x1b000603},
+       {0x0000a5a4, 0x35001fc4, 0x35001fc4, 0x1f000a02, 0x1f000a02},
+       {0x0000a5a8, 0x3c022f04, 0x3c022f04, 0x23000a04, 0x23000a04},
+       {0x0000a5ac, 0x41023e85, 0x41023e85, 0x26000a20, 0x26000a20},
+       {0x0000a5b0, 0x48023ec6, 0x48023ec6, 0x2a000e20, 0x2a000e20},
+       {0x0000a5b4, 0x4d023f01, 0x4d023f01, 0x2e000e22, 0x2e000e22},
+       {0x0000a5b8, 0x53023f4b, 0x53023f4b, 0x31000e24, 0x31000e24},
+       {0x0000a5bc, 0x5a027f09, 0x5a027f09, 0x34001640, 0x34001640},
+       {0x0000a5c0, 0x5f027fc9, 0x5f027fc9, 0x38001660, 0x38001660},
+       {0x0000a5c4, 0x6502feca, 0x6502feca, 0x3b001861, 0x3b001861},
+       {0x0000a5c8, 0x6b02ff4a, 0x6b02ff4a, 0x3e001a81, 0x3e001a81},
+       {0x0000a5cc, 0x7203feca, 0x7203feca, 0x42001a83, 0x42001a83},
+       {0x0000a5d0, 0x7703ff0b, 0x7703ff0b, 0x44001c84, 0x44001c84},
+       {0x0000a5d4, 0x7d06ffcb, 0x7d06ffcb, 0x48001ce3, 0x48001ce3},
+       {0x0000a5d8, 0x8407ff0b, 0x8407ff0b, 0x4c001ce5, 0x4c001ce5},
+       {0x0000a5dc, 0x8907ffcb, 0x8907ffcb, 0x50001ce9, 0x50001ce9},
+       {0x0000a5e0, 0x900fff0b, 0x900fff0b, 0x54001ceb, 0x54001ceb},
+       {0x0000a5e4, 0x960fffcb, 0x960fffcb, 0x56001eec, 0x56001eec},
+       {0x0000a5e8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5ec, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f0, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f4, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5f8, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a5fc, 0x9c1fff0b, 0x9c1fff0b, 0x56001eec, 0x56001eec},
+       {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02008501, 0x02008501, 0x02008501, 0x02008501},
+       {0x0000a61c, 0x02008802, 0x02008802, 0x02008802, 0x02008802},
+       {0x0000a620, 0x0300c802, 0x0300c802, 0x0300c802, 0x0300c802},
+       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x0300cc03, 0x0300cc03},
+       {0x0000a628, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a62c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a630, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a634, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a638, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+       {0x0000a63c, 0x04011004, 0x04011004, 0x04011004, 0x04011004},
+};
+
+static const u32 ar9331_1p2_mac_postamble[][5] = {
+       /*  Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20  */
+       {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+       {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+       {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+       {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+       {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+       {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+       {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+       {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9331_1p2_soc_preamble[][2] = {
+       /* Addr      allmodes  */
+       {0x00007020, 0x00000000},
+       {0x00007034, 0x00000002},
+       {0x00007038, 0x000002f8},
+};
+
+static const u32 ar9331_1p2_xtal_40M[][2] = {
+       /* Addr      allmodes  */
+       {0x00007038, 0x000004c2},
+       {0x00008244, 0x0010f400},
+       {0x0000824c, 0x0001e800},
+       {0x0001609c, 0x0b283f31},
+};
+
+static const u32 ar9331_1p2_mac_core[][2] = {
+       /* Addr      allmodes  */
+       {0x00000008, 0x00000000},
+       {0x00000030, 0x00020085},
+       {0x00000034, 0x00000005},
+       {0x00000040, 0x00000000},
+       {0x00000044, 0x00000000},
+       {0x00000048, 0x00000008},
+       {0x0000004c, 0x00000010},
+       {0x00000050, 0x00000000},
+       {0x00001040, 0x002ffc0f},
+       {0x00001044, 0x002ffc0f},
+       {0x00001048, 0x002ffc0f},
+       {0x0000104c, 0x002ffc0f},
+       {0x00001050, 0x002ffc0f},
+       {0x00001054, 0x002ffc0f},
+       {0x00001058, 0x002ffc0f},
+       {0x0000105c, 0x002ffc0f},
+       {0x00001060, 0x002ffc0f},
+       {0x00001064, 0x002ffc0f},
+       {0x000010f0, 0x00000100},
+       {0x00001270, 0x00000000},
+       {0x000012b0, 0x00000000},
+       {0x000012f0, 0x00000000},
+       {0x0000143c, 0x00000000},
+       {0x0000147c, 0x00000000},
+       {0x00008000, 0x00000000},
+       {0x00008004, 0x00000000},
+       {0x00008008, 0x00000000},
+       {0x0000800c, 0x00000000},
+       {0x00008018, 0x00000000},
+       {0x00008020, 0x00000000},
+       {0x00008038, 0x00000000},
+       {0x0000803c, 0x00000000},
+       {0x00008040, 0x00000000},
+       {0x00008044, 0x00000000},
+       {0x00008048, 0x00000000},
+       {0x0000804c, 0xffffffff},
+       {0x00008054, 0x00000000},
+       {0x00008058, 0x00000000},
+       {0x0000805c, 0x000fc78f},
+       {0x00008060, 0x0000000f},
+       {0x00008064, 0x00000000},
+       {0x00008070, 0x00000310},
+       {0x00008074, 0x00000020},
+       {0x00008078, 0x00000000},
+       {0x0000809c, 0x0000000f},
+       {0x000080a0, 0x00000000},
+       {0x000080a4, 0x02ff0000},
+       {0x000080a8, 0x0e070605},
+       {0x000080ac, 0x0000000d},
+       {0x000080b0, 0x00000000},
+       {0x000080b4, 0x00000000},
+       {0x000080b8, 0x00000000},
+       {0x000080bc, 0x00000000},
+       {0x000080c0, 0x2a800000},
+       {0x000080c4, 0x06900168},
+       {0x000080c8, 0x13881c20},
+       {0x000080cc, 0x01f40000},
+       {0x000080d0, 0x00252500},
+       {0x000080d4, 0x00a00000},
+       {0x000080d8, 0x00400000},
+       {0x000080dc, 0x00000000},
+       {0x000080e0, 0xffffffff},
+       {0x000080e4, 0x0000ffff},
+       {0x000080e8, 0x3f3f3f3f},
+       {0x000080ec, 0x00000000},
+       {0x000080f0, 0x00000000},
+       {0x000080f4, 0x00000000},
+       {0x000080fc, 0x00020000},
+       {0x00008100, 0x00000000},
+       {0x00008108, 0x00000052},
+       {0x0000810c, 0x00000000},
+       {0x00008110, 0x00000000},
+       {0x00008114, 0x000007ff},
+       {0x00008118, 0x000000aa},
+       {0x0000811c, 0x00003210},
+       {0x00008124, 0x00000000},
+       {0x00008128, 0x00000000},
+       {0x0000812c, 0x00000000},
+       {0x00008130, 0x00000000},
+       {0x00008134, 0x00000000},
+       {0x00008138, 0x00000000},
+       {0x0000813c, 0x0000ffff},
+       {0x00008144, 0xffffffff},
+       {0x00008168, 0x00000000},
+       {0x0000816c, 0x00000000},
+       {0x00008170, 0x18486200},
+       {0x00008174, 0x33332210},
+       {0x00008178, 0x00000000},
+       {0x0000817c, 0x00020000},
+       {0x000081c0, 0x00000000},
+       {0x000081c4, 0x33332210},
+       {0x000081c8, 0x00000000},
+       {0x000081cc, 0x00000000},
+       {0x000081d4, 0x00000000},
+       {0x000081ec, 0x00000000},
+       {0x000081f0, 0x00000000},
+       {0x000081f4, 0x00000000},
+       {0x000081f8, 0x00000000},
+       {0x000081fc, 0x00000000},
+       {0x00008240, 0x00100000},
+       {0x00008248, 0x00000800},
+       {0x00008250, 0x00000000},
+       {0x00008254, 0x00000000},
+       {0x00008258, 0x00000000},
+       {0x0000825c, 0x40000000},
+       {0x00008260, 0x00080922},
+       {0x00008264, 0x9d400010},
+       {0x00008268, 0xffffffff},
+       {0x0000826c, 0x0000ffff},
+       {0x00008270, 0x00000000},
+       {0x00008274, 0x40000000},
+       {0x00008278, 0x003e4180},
+       {0x0000827c, 0x00000004},
+       {0x00008284, 0x0000002c},
+       {0x00008288, 0x0000002c},
+       {0x0000828c, 0x000000ff},
+       {0x00008294, 0x00000000},
+       {0x00008298, 0x00000000},
+       {0x0000829c, 0x00000000},
+       {0x00008300, 0x00000140},
+       {0x00008314, 0x00000000},
+       {0x0000831c, 0x0000010d},
+       {0x00008328, 0x00000000},
+       {0x0000832c, 0x00000007},
+       {0x00008330, 0x00000302},
+       {0x00008334, 0x00000700},
+       {0x00008338, 0x00ff0000},
+       {0x0000833c, 0x02400000},
+       {0x00008340, 0x000107ff},
+       {0x00008344, 0xaa48105b},
+       {0x00008348, 0x008f0000},
+       {0x0000835c, 0x00000000},
+       {0x00008360, 0xffffffff},
+       {0x00008364, 0xffffffff},
+       {0x00008368, 0x00000000},
+       {0x00008370, 0x00000000},
+       {0x00008374, 0x000000ff},
+       {0x00008378, 0x00000000},
+       {0x0000837c, 0x00000000},
+       {0x00008380, 0xffffffff},
+       {0x00008384, 0xffffffff},
+       {0x00008390, 0xffffffff},
+       {0x00008394, 0xffffffff},
+       {0x00008398, 0x00000000},
+       {0x0000839c, 0x00000000},
+       {0x000083a0, 0x00000000},
+       {0x000083a4, 0x0000fa14},
+       {0x000083a8, 0x000f0c00},
+       {0x000083ac, 0x33332210},
+       {0x000083b0, 0x33332210},
+       {0x000083b4, 0x33332210},
+       {0x000083b8, 0x33332210},
+       {0x000083bc, 0x00000000},
+       {0x000083c0, 0x00000000},
+       {0x000083c4, 0x00000000},
+       {0x000083c8, 0x00000000},
+       {0x000083cc, 0x00000200},
+       {0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9331_common_rx_gain_1p2[][2] = {
+       /* Addr      allmodes  */
+       {0x0000a000, 0x00010000},
+       {0x0000a004, 0x00030002},
+       {0x0000a008, 0x00050004},
+       {0x0000a00c, 0x00810080},
+       {0x0000a010, 0x01800082},
+       {0x0000a014, 0x01820181},
+       {0x0000a018, 0x01840183},
+       {0x0000a01c, 0x01880185},
+       {0x0000a020, 0x018a0189},
+       {0x0000a024, 0x02850284},
+       {0x0000a028, 0x02890288},
+       {0x0000a02c, 0x03850384},
+       {0x0000a030, 0x03890388},
+       {0x0000a034, 0x038b038a},
+       {0x0000a038, 0x038d038c},
+       {0x0000a03c, 0x03910390},
+       {0x0000a040, 0x03930392},
+       {0x0000a044, 0x03950394},
+       {0x0000a048, 0x00000396},
+       {0x0000a04c, 0x00000000},
+       {0x0000a050, 0x00000000},
+       {0x0000a054, 0x00000000},
+       {0x0000a058, 0x00000000},
+       {0x0000a05c, 0x00000000},
+       {0x0000a060, 0x00000000},
+       {0x0000a064, 0x00000000},
+       {0x0000a068, 0x00000000},
+       {0x0000a06c, 0x00000000},
+       {0x0000a070, 0x00000000},
+       {0x0000a074, 0x00000000},
+       {0x0000a078, 0x00000000},
+       {0x0000a07c, 0x00000000},
+       {0x0000a080, 0x28282828},
+       {0x0000a084, 0x28282828},
+       {0x0000a088, 0x28282828},
+       {0x0000a08c, 0x28282828},
+       {0x0000a090, 0x28282828},
+       {0x0000a094, 0x21212128},
+       {0x0000a098, 0x171c1c1c},
+       {0x0000a09c, 0x02020212},
+       {0x0000a0a0, 0x00000202},
+       {0x0000a0a4, 0x00000000},
+       {0x0000a0a8, 0x00000000},
+       {0x0000a0ac, 0x00000000},
+       {0x0000a0b0, 0x00000000},
+       {0x0000a0b4, 0x00000000},
+       {0x0000a0b8, 0x00000000},
+       {0x0000a0bc, 0x00000000},
+       {0x0000a0c0, 0x001f0000},
+       {0x0000a0c4, 0x111f1100},
+       {0x0000a0c8, 0x111d111e},
+       {0x0000a0cc, 0x111b111c},
+       {0x0000a0d0, 0x22032204},
+       {0x0000a0d4, 0x22012202},
+       {0x0000a0d8, 0x221f2200},
+       {0x0000a0dc, 0x221d221e},
+       {0x0000a0e0, 0x33013302},
+       {0x0000a0e4, 0x331f3300},
+       {0x0000a0e8, 0x4402331e},
+       {0x0000a0ec, 0x44004401},
+       {0x0000a0f0, 0x441e441f},
+       {0x0000a0f4, 0x55015502},
+       {0x0000a0f8, 0x551f5500},
+       {0x0000a0fc, 0x6602551e},
+       {0x0000a100, 0x66006601},
+       {0x0000a104, 0x661e661f},
+       {0x0000a108, 0x7703661d},
+       {0x0000a10c, 0x77017702},
+       {0x0000a110, 0x00007700},
+       {0x0000a114, 0x00000000},
+       {0x0000a118, 0x00000000},
+       {0x0000a11c, 0x00000000},
+       {0x0000a120, 0x00000000},
+       {0x0000a124, 0x00000000},
+       {0x0000a128, 0x00000000},
+       {0x0000a12c, 0x00000000},
+       {0x0000a130, 0x00000000},
+       {0x0000a134, 0x00000000},
+       {0x0000a138, 0x00000000},
+       {0x0000a13c, 0x00000000},
+       {0x0000a140, 0x001f0000},
+       {0x0000a144, 0x111f1100},
+       {0x0000a148, 0x111d111e},
+       {0x0000a14c, 0x111b111c},
+       {0x0000a150, 0x22032204},
+       {0x0000a154, 0x22012202},
+       {0x0000a158, 0x221f2200},
+       {0x0000a15c, 0x221d221e},
+       {0x0000a160, 0x33013302},
+       {0x0000a164, 0x331f3300},
+       {0x0000a168, 0x4402331e},
+       {0x0000a16c, 0x44004401},
+       {0x0000a170, 0x441e441f},
+       {0x0000a174, 0x55015502},
+       {0x0000a178, 0x551f5500},
+       {0x0000a17c, 0x6602551e},
+       {0x0000a180, 0x66006601},
+       {0x0000a184, 0x661e661f},
+       {0x0000a188, 0x7703661d},
+       {0x0000a18c, 0x77017702},
+       {0x0000a190, 0x00007700},
+       {0x0000a194, 0x00000000},
+       {0x0000a198, 0x00000000},
+       {0x0000a19c, 0x00000000},
+       {0x0000a1a0, 0x00000000},
+       {0x0000a1a4, 0x00000000},
+       {0x0000a1a8, 0x00000000},
+       {0x0000a1ac, 0x00000000},
+       {0x0000a1b0, 0x00000000},
+       {0x0000a1b4, 0x00000000},
+       {0x0000a1b8, 0x00000000},
+       {0x0000a1bc, 0x00000000},
+       {0x0000a1c0, 0x00000000},
+       {0x0000a1c4, 0x00000000},
+       {0x0000a1c8, 0x00000000},
+       {0x0000a1cc, 0x00000000},
+       {0x0000a1d0, 0x00000000},
+       {0x0000a1d4, 0x00000000},
+       {0x0000a1d8, 0x00000000},
+       {0x0000a1dc, 0x00000000},
+       {0x0000a1e0, 0x00000000},
+       {0x0000a1e4, 0x00000000},
+       {0x0000a1e8, 0x00000000},
+       {0x0000a1ec, 0x00000000},
+       {0x0000a1f0, 0x00000396},
+       {0x0000a1f4, 0x00000396},
+       {0x0000a1f8, 0x00000396},
+       {0x0000a1fc, 0x00000296},
+};
+
+#endif /* INITVALS_9330_1P2_H */
index 57933db..359576f 100644 (file)
@@ -55,8 +55,6 @@ struct ath_node;
                (_l) &= ((_sz) - 1);            \
        } while (0)
 
-#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
-
 #define TSF_TO_TU(_h,_l) \
        ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
 
@@ -580,7 +578,7 @@ struct ath9k_vif_iter_data {
        int naps;      /* number of AP vifs */
        int nmeshes;   /* number of mesh vifs */
        int nstations; /* number of station vifs */
-       int nwds;      /* number of nwd vifs */
+       int nwds;      /* number of WDS vifs */
        int nadhocs;   /* number of adhoc vifs */
        int nothers;   /* number of vifs not specified above. */
 };
index 6de2655..07827b5 100644 (file)
@@ -251,6 +251,15 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
        case AR5416_AR9100_DEVID:
                ah->hw_version.macVersion = AR_SREV_VERSION_9100;
                break;
+       case AR9300_DEVID_AR9330:
+               ah->hw_version.macVersion = AR_SREV_VERSION_9330;
+               if (ah->get_mac_revision) {
+                       ah->hw_version.macRev = ah->get_mac_revision();
+               } else {
+                       val = REG_READ(ah, AR_SREV);
+                       ah->hw_version.macRev = MS(val, AR_SREV_REVISION2);
+               }
+               return;
        case AR9300_DEVID_AR9340:
                ah->hw_version.macVersion = AR_SREV_VERSION_9340;
                val = REG_READ(ah, AR_SREV);
@@ -551,6 +560,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        case AR_SREV_VERSION_9287:
        case AR_SREV_VERSION_9271:
        case AR_SREV_VERSION_9300:
+       case AR_SREV_VERSION_9330:
        case AR_SREV_VERSION_9485:
        case AR_SREV_VERSION_9340:
                break;
@@ -561,7 +571,8 @@ static int __ath9k_hw_init(struct ath_hw *ah)
                return -EOPNOTSUPP;
        }
 
-       if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah))
+       if (AR_SREV_9271(ah) || AR_SREV_9100(ah) || AR_SREV_9340(ah) ||
+           AR_SREV_9330(ah))
                ah->is_pciexpress = false;
 
        ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID);
@@ -604,7 +615,10 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        else
                ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
 
-       ah->bb_watchdog_timeout_ms = 25;
+       if (AR_SREV_9330(ah))
+               ah->bb_watchdog_timeout_ms = 85;
+       else
+               ah->bb_watchdog_timeout_ms = 25;
 
        common->state = ATH_HW_INITIALIZED;
 
@@ -630,6 +644,7 @@ int ath9k_hw_init(struct ath_hw *ah)
        case AR2427_DEVID_PCIE:
        case AR9300_DEVID_PCIE:
        case AR9300_DEVID_AR9485_PCIE:
+       case AR9300_DEVID_AR9330:
        case AR9300_DEVID_AR9340:
                break;
        default:
@@ -722,6 +737,39 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
                REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
                              AR_CH0_BB_DPLL2_PLL_PWD, 0x0);
                udelay(1000);
+       } else if (AR_SREV_9330(ah)) {
+               u32 ddr_dpll2, pll_control2, kd;
+
+               if (ah->is_clk_25mhz) {
+                       ddr_dpll2 = 0x18e82f01;
+                       pll_control2 = 0xe04a3d;
+                       kd = 0x1d;
+               } else {
+                       ddr_dpll2 = 0x19e82f01;
+                       pll_control2 = 0x886666;
+                       kd = 0x3d;
+               }
+
+               /* program DDR PLL ki and kd value */
+               REG_WRITE(ah, AR_CH0_DDR_DPLL2, ddr_dpll2);
+
+               /* program DDR PLL phase_shift */
+               REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+                             AR_CH0_DPLL3_PHASE_SHIFT, 0x1);
+
+               REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+               udelay(1000);
+
+               /* program refdiv, nint, frac to RTC register */
+               REG_WRITE(ah, AR_RTC_PLL_CONTROL2, pll_control2);
+
+               /* program BB PLL kd and ki value */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KD, kd);
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2, AR_CH0_DPLL2_KI, 0x06);
+
+               /* program BB PLL phase_shift */
+               REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+                             AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
        } else if (AR_SREV_9340(ah)) {
                u32 regval, pll2_divint, pll2_divfrac, refdiv;
 
@@ -763,7 +811,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
 
        REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
 
-       if (AR_SREV_9485(ah) || AR_SREV_9340(ah))
+       if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah))
                udelay(1000);
 
        /* Switch the core clock for ar9271 to 117Mhz */
@@ -1114,6 +1162,41 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
                        rst_flags |= AR_RTC_RC_MAC_COLD;
        }
 
+       if (AR_SREV_9330(ah)) {
+               int npend = 0;
+               int i;
+
+               /* AR9330 WAR:
+                * call external reset function to reset WMAC if:
+                * - doing a cold reset
+                * - we have pending frames in the TX queues
+                */
+
+               for (i = 0; i < AR_NUM_QCU; i++) {
+                       npend = ath9k_hw_numtxpending(ah, i);
+                       if (npend)
+                               break;
+               }
+
+               if (ah->external_reset &&
+                   (npend || type == ATH9K_RESET_COLD)) {
+                       int reset_err = 0;
+
+                       ath_dbg(ath9k_hw_common(ah), ATH_DBG_RESET,
+                               "reset MAC via external reset\n");
+
+                       reset_err = ah->external_reset();
+                       if (reset_err) {
+                               ath_err(ath9k_hw_common(ah),
+                                       "External reset failed, err=%d\n",
+                                       reset_err);
+                               return false;
+                       }
+
+                       REG_WRITE(ah, AR_RTC_RESET, 1);
+               }
+       }
+
        REG_WRITE(ah, AR_RTC_RC, rst_flags);
 
        REGWRITE_BUFFER_FLUSH(ah);
@@ -1545,7 +1628,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                                REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
                }
 #ifdef __BIG_ENDIAN
-               else if (AR_SREV_9340(ah))
+               else if (AR_SREV_9330(ah) || AR_SREV_9340(ah))
                        REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
                else
                        REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@@ -1983,7 +2066,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 
        if (AR_SREV_9300_20_OR_LATER(ah)) {
                pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
-               if (!AR_SREV_9485(ah))
+               if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah))
                        pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
 
                pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@@ -2025,7 +2108,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
        }
 
 
-       if (AR_SREV_9485(ah)) {
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
                ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1);
                /*
                 * enable the diversity-combining algorithm only when
@@ -2574,6 +2657,7 @@ static struct {
        { AR_SREV_VERSION_9287,         "9287" },
        { AR_SREV_VERSION_9271,         "9271" },
        { AR_SREV_VERSION_9300,         "9300" },
+       { AR_SREV_VERSION_9330,         "9330" },
        { AR_SREV_VERSION_9485,         "9485" },
 };
 
index 6a6fb54..818acdd 100644 (file)
@@ -45,6 +45,7 @@
 #define AR9300_DEVID_PCIE      0x0030
 #define AR9300_DEVID_AR9340    0x0031
 #define AR9300_DEVID_AR9485_PCIE 0x0032
+#define AR9300_DEVID_AR9330    0x0035
 
 #define AR5416_AR9100_DEVID    0x000b
 
 #define ATH9K_HW_RX_HP_QDEPTH  16
 #define ATH9K_HW_RX_LP_QDEPTH  128
 
-#define PAPRD_GAIN_TABLE_ENTRIES    32
-#define PAPRD_TABLE_SZ              24
+#define PAPRD_GAIN_TABLE_ENTRIES       32
+#define PAPRD_TABLE_SZ                 24
+#define PAPRD_IDEAL_AGC2_PWR_RANGE     0xe0
 
 enum ath_hw_txq_subtype {
        ATH_TXQ_AC_BE = 0,
@@ -860,6 +862,8 @@ struct ath_hw {
        u32 ent_mode;
 
        bool is_clk_25mhz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
 };
 
 struct ath_bus_ops {
index 1202bb0..616e30b 100644 (file)
@@ -246,7 +246,7 @@ static void setup_ht_cap(struct ath_softc *sc,
        ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
        ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
 
-       if (AR_SREV_9485(ah))
+       if (AR_SREV_9330(ah) || AR_SREV_9485(ah))
                max_streams = 1;
        else if (AR_SREV_9300_20_OR_LATER(ah))
                max_streams = 3;
@@ -575,6 +575,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
                sc->sc_ah->gpio_val = pdata->gpio_val;
                sc->sc_ah->led_pin = pdata->led_pin;
                ah->is_clk_25mhz = pdata->is_clk_25mhz;
+               ah->get_mac_revision = pdata->get_mac_revision;
+               ah->external_reset = pdata->external_reset;
        }
 
        common = ath9k_hw_common(ah);
index 7f94533..5ae303b 100644 (file)
@@ -360,7 +360,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
        txctl.paprd = BIT(chain);
 
        if (ath_tx_start(hw, skb, &txctl) != 0) {
-               ath_dbg(common, ATH_DBG_XMIT, "PAPRD TX failed\n");
+               ath_dbg(common, ATH_DBG_CALIBRATE, "PAPRD TX failed\n");
                dev_kfree_skb_any(skb);
                return false;
        }
@@ -369,7 +369,7 @@ static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int
                        msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
 
        if (!time_left)
-               ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
+               ath_dbg(common, ATH_DBG_CALIBRATE,
                        "Timeout waiting for paprd training on TX chain %d\n",
                        chain);
 
@@ -431,11 +431,18 @@ void ath_paprd_calibrate(struct work_struct *work)
                if (!ath_paprd_send_frame(sc, skb, chain))
                        goto fail_paprd;
 
-               if (!ar9003_paprd_is_done(ah))
+               if (!ar9003_paprd_is_done(ah)) {
+                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                               "PAPRD not yet done on chain %d\n", chain);
                        break;
+               }
 
-               if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
+               if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+                       ath_dbg(common, ATH_DBG_CALIBRATE,
+                               "PAPRD create curve failed on chain %d\n",
+                                                                  chain);
                        break;
+               }
 
                chain_ok = 1;
        }
@@ -1259,7 +1266,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
        /* disable HAL and put h/w to sleep */
        ath9k_hw_disable(ah);
-       ath9k_hw_configpcipowersave(ah, 1, 1);
 
        spin_unlock_bh(&sc->sc_pcu_lock);
 
index ba7f36a..e7fe4d9 100644 (file)
@@ -533,7 +533,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
                                        [valid_rate_count] = j;
                                ath_rc_priv->valid_phy_ratecnt[phy] += 1;
                                ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
-                               hi = A_MAX(hi, j);
+                               hi = max(hi, j);
                        }
                }
        }
@@ -569,7 +569,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
                                [ath_rc_priv->valid_phy_ratecnt[phy]] = j;
                        ath_rc_priv->valid_phy_ratecnt[phy] += 1;
                        ath_rc_set_valid_rate_idx(ath_rc_priv, j, 1);
-                       hi = A_MAX(hi, j);
+                       hi = max(hi, j);
                }
        }
 
@@ -1228,7 +1228,7 @@ static void ath_rc_init(struct ath_softc *sc,
                                                       ht_mcs,
                                                       ath_rc_priv->ht_cap);
                }
-               hi = A_MAX(hi, hthi);
+               hi = max(hi, hthi);
        }
 
        ath_rc_priv->rate_table_size = hi + 1;
index c4c5d9f..70dc8ec 100644 (file)
@@ -40,6 +40,7 @@ static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio,
                        result = true;
                break;
        case 1:
+       case 2:
                if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) &&
                        (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) &&
                                (alt_rssi_avg >= (main_rssi_avg - 5))) ||
@@ -1076,39 +1077,39 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
                antcomb->rssi_lna1 = main_rssi_avg;
 
        switch ((ant_conf.main_lna_conf << 4) | ant_conf.alt_lna_conf) {
-       case (0x10): /* LNA2 A-B */
+       case 0x10: /* LNA2 A-B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
                break;
-       case (0x20): /* LNA1 A-B */
+       case 0x20: /* LNA1 A-B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA2;
                break;
-       case (0x21): /* LNA1 LNA2 */
+       case 0x21: /* LNA1 LNA2 */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->second_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                break;
-       case (0x12): /* LNA2 LNA1 */
+       case 0x12: /* LNA2 LNA1 */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->second_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                break;
-       case (0x13): /* LNA2 A+B */
+       case 0x13: /* LNA2 A+B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
                antcomb->second_quick_scan_conf = ATH_ANT_DIV_COMB_LNA1;
                break;
-       case (0x23): /* LNA1 A+B */
+       case 0x23: /* LNA1 A+B */
                antcomb->main_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
                antcomb->first_quick_scan_conf =
                        ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
@@ -1325,65 +1326,148 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                /* Adjust the fast_div_bias based on main and alt lna conf */
                switch ((ant_conf->main_lna_conf << 4) |
                                ant_conf->alt_lna_conf) {
-               case (0x01): /* A-B LNA2 */
+               case 0x01: /* A-B LNA2 */
                        ant_conf->fast_div_bias = 0x3b;
                        break;
-               case (0x02): /* A-B LNA1 */
+               case 0x02: /* A-B LNA1 */
                        ant_conf->fast_div_bias = 0x3d;
                        break;
-               case (0x03): /* A-B A+B */
+               case 0x03: /* A-B A+B */
                        ant_conf->fast_div_bias = 0x1;
                        break;
-               case (0x10): /* LNA2 A-B */
+               case 0x10: /* LNA2 A-B */
                        ant_conf->fast_div_bias = 0x7;
                        break;
-               case (0x12): /* LNA2 LNA1 */
+               case 0x12: /* LNA2 LNA1 */
                        ant_conf->fast_div_bias = 0x2;
                        break;
-               case (0x13): /* LNA2 A+B */
+               case 0x13: /* LNA2 A+B */
                        ant_conf->fast_div_bias = 0x7;
                        break;
-               case (0x20): /* LNA1 A-B */
+               case 0x20: /* LNA1 A-B */
                        ant_conf->fast_div_bias = 0x6;
                        break;
-               case (0x21): /* LNA1 LNA2 */
+               case 0x21: /* LNA1 LNA2 */
                        ant_conf->fast_div_bias = 0x0;
                        break;
-               case (0x23): /* LNA1 A+B */
+               case 0x23: /* LNA1 A+B */
                        ant_conf->fast_div_bias = 0x6;
                        break;
-               case (0x30): /* A+B A-B */
+               case 0x30: /* A+B A-B */
                        ant_conf->fast_div_bias = 0x1;
                        break;
-               case (0x31): /* A+B LNA2 */
+               case 0x31: /* A+B LNA2 */
                        ant_conf->fast_div_bias = 0x3b;
                        break;
-               case (0x32): /* A+B LNA1 */
+               case 0x32: /* A+B LNA1 */
                        ant_conf->fast_div_bias = 0x3d;
                        break;
                default:
                        break;
                }
+       } else if (ant_conf->div_group == 1) {
+               /* Adjust the fast_div_bias based on main and alt_lna_conf */
+               switch ((ant_conf->main_lna_conf << 4) |
+                       ant_conf->alt_lna_conf) {
+               case 0x01: /* A-B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x02: /* A-B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x03: /* A-B A+B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x10: /* LNA2 A-B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x12: /* LNA2 LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x13: /* LNA2 A+B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x20: /* LNA1 A-B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x21: /* LNA1 LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x23: /* LNA1 A+B */
+                       if (!(antcomb->scan) &&
+                           (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                               ant_conf->fast_div_bias = 0x3f;
+                       else
+                               ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x30: /* A+B A-B */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x31: /* A+B LNA2 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               case 0x32: /* A+B LNA1 */
+                       ant_conf->fast_div_bias = 0x1;
+                       ant_conf->main_gaintb = 0;
+                       ant_conf->alt_gaintb = 0;
+                       break;
+               default:
+                       break;
+               }
        } else if (ant_conf->div_group == 2) {
                /* Adjust the fast_div_bias based on main and alt_lna_conf */
                switch ((ant_conf->main_lna_conf << 4) |
                                ant_conf->alt_lna_conf) {
-               case (0x01): /* A-B LNA2 */
+               case 0x01: /* A-B LNA2 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x02): /* A-B LNA1 */
+               case 0x02: /* A-B LNA1 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x03): /* A-B A+B */
+               case 0x03: /* A-B A+B */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x10): /* LNA2 A-B */
+               case 0x10: /* LNA2 A-B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
@@ -1392,12 +1476,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x12): /* LNA2 LNA1 */
+               case 0x12: /* LNA2 LNA1 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x13): /* LNA2 A+B */
+               case 0x13: /* LNA2 A+B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
@@ -1406,7 +1490,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x20): /* LNA1 A-B */
+               case 0x20: /* LNA1 A-B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
@@ -1415,12 +1499,12 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x21): /* LNA1 LNA2 */
+               case 0x21: /* LNA1 LNA2 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x23): /* LNA1 A+B */
+               case 0x23: /* LNA1 A+B */
                        if (!(antcomb->scan) &&
                                (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
                                ant_conf->fast_div_bias = 0x1;
@@ -1429,17 +1513,17 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x30): /* A+B A-B */
+               case 0x30: /* A+B A-B */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x31): /* A+B LNA2 */
+               case 0x31: /* A+B LNA2 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
                        break;
-               case (0x32): /* A+B LNA1 */
+               case 0x32: /* A+B LNA1 */
                        ant_conf->fast_div_bias = 0x1;
                        ant_conf->main_gaintb = 0;
                        ant_conf->alt_gaintb = 0;
@@ -1447,9 +1531,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                default:
                        break;
                }
-
        }
-
 }
 
 /* Antenna diversity and combining */
index c18ee99..a483388 100644 (file)
 #define AR_SREV_REVISION_9271_11       1
 #define AR_SREV_VERSION_9300           0x1c0
 #define AR_SREV_REVISION_9300_20       2 /* 2.0 and 2.1 */
+#define AR_SREV_VERSION_9330           0x200
+#define AR_SREV_REVISION_9330_10       0
+#define AR_SREV_REVISION_9330_11       1
+#define AR_SREV_REVISION_9330_12       2
 #define AR_SREV_VERSION_9485           0x240
 #define AR_SREV_REVISION_9485_10       0
 #define AR_SREV_REVISION_9485_11        1
 #define AR_SREV_9300_20_OR_LATER(_ah) \
        ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
 
+#define AR_SREV_9330(_ah) \
+       (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
+#define AR_SREV_9330_10(_ah) \
+       (AR_SREV_9330((_ah)) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_10))
+#define AR_SREV_9330_11(_ah) \
+       (AR_SREV_9330((_ah)) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_11))
+#define AR_SREV_9330_12(_ah) \
+       (AR_SREV_9330((_ah)) && \
+        ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
+
 #define AR_SREV_9485(_ah) \
        (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
 #define AR_SREV_9485_10(_ah) \
index fe26bf4..d5add69 100644 (file)
@@ -31,6 +31,11 @@ config B43_BCMA
        depends on B43 && BCMA && BROKEN
        default y
 
+config B43_SSB
+       bool
+       depends on B43 && SSB
+       default y
+
 # Auto-select SSB PCI-HOST support, if possible
 config B43_PCI_AUTOSELECT
        bool
@@ -112,6 +117,14 @@ config B43_PHY_LP
          and embedded devices. It supports 802.11a/g
          (802.11a support is optional, and currently disabled).
 
+config B43_PHY_HT
+       bool "Support for HT-PHY devices (BROKEN)"
+       depends on B43 && BROKEN
+       ---help---
+         Support for the HT-PHY.
+
+         Say N, this is BROKEN and crashes driver.
+
 # This config option automatically enables b43 LEDS support,
 # if it's possible.
 config B43_LEDS
index 95f7c00..900dc9c 100644 (file)
@@ -10,6 +10,8 @@ b43-y                         += phy_a.o
 b43-$(CONFIG_B43_PHY_N)                += phy_n.o
 b43-$(CONFIG_B43_PHY_LP)       += phy_lp.o
 b43-$(CONFIG_B43_PHY_LP)       += tables_lpphy.o
+b43-$(CONFIG_B43_PHY_HT)       += phy_ht.o
+b43-$(CONFIG_B43_PHY_HT)       += radio_2059.o
 b43-y                          += sysfs.o
 b43-y                          += xmit.o
 b43-y                          += lo.o
index 1cb2dde..666515e 100644 (file)
@@ -92,6 +92,8 @@
 #define B43_MMIO_PIO11_BASE4           0x300
 #define B43_MMIO_PIO11_BASE5           0x340
 
+#define B43_MMIO_RADIO24_CONTROL       0x3D8   /* core rev >= 24 only */
+#define B43_MMIO_RADIO24_DATA          0x3DA   /* core rev >= 24 only */
 #define B43_MMIO_PHY_VER               0x3E0
 #define B43_MMIO_PHY_RADIO             0x3E2
 #define B43_MMIO_PHY0                  0x3E6
@@ -363,6 +365,10 @@ enum {
 #define B43_PHYTYPE_G                  0x02
 #define B43_PHYTYPE_N                  0x04
 #define B43_PHYTYPE_LP                 0x05
+#define B43_PHYTYPE_SSLPN              0x06
+#define B43_PHYTYPE_HT                 0x07
+#define B43_PHYTYPE_LCN                        0x08
+#define B43_PHYTYPE_LCNXN              0x09
 
 /* PHYRegisters */
 #define B43_PHY_ILT_A_CTRL             0x0072
index 6c63aec..4200713 100644 (file)
@@ -25,7 +25,7 @@
 
 
 /* SSB */
-
+#ifdef CONFIG_B43_SSB
 static inline int b43_bus_ssb_bus_may_powerdown(struct b43_bus_dev *dev)
 {
        return ssb_bus_may_powerdown(dev->sdev->bus);
@@ -83,7 +83,11 @@ void b43_bus_ssb_block_write(struct b43_bus_dev *dev, const void *buffer,
 
 struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
 {
-       struct b43_bus_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       struct b43_bus_dev *dev;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
 
        dev->bus_type = B43_BUS_SSB;
        dev->sdev = sdev;
@@ -120,3 +124,4 @@ struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev)
 
        return dev;
 }
+#endif /* CONFIG_B43_SSB */
index cae3146..e9a01e3 100644 (file)
@@ -123,6 +123,7 @@ static const struct bcma_device_id b43_bcma_tbl[] = {
 MODULE_DEVICE_TABLE(bcma, b43_bcma_tbl);
 #endif
 
+#ifdef CONFIG_B43_SSB
 static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5),
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6),
@@ -136,8 +137,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16),
        SSB_DEVTABLE_END
 };
-
 MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl);
+#endif
 
 /* Channel and ratetables are shared for all devices.
  * They can't be const, because ieee80211 puts some precalculated
@@ -4096,6 +4097,12 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                if (phy_rev > 2)
                        unsupported = 1;
                break;
+#endif
+#ifdef CONFIG_B43_PHY_HT
+       case B43_PHYTYPE_HT:
+               if (phy_rev > 1)
+                       unsupported = 1;
+               break;
 #endif
        default:
                unsupported = 1;
@@ -4153,6 +4160,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
                if (radio_ver != 0x2062 && radio_ver != 0x2063)
                        unsupported = 1;
                break;
+       case B43_PHYTYPE_HT:
+               if (radio_ver != 0x2059)
+                       unsupported = 1;
+               break;
        default:
                B43_WARN_ON(1);
        }
@@ -5016,6 +5027,7 @@ static struct bcma_driver b43_bcma_driver = {
 };
 #endif
 
+#ifdef CONFIG_B43_SSB
 static
 int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
 {
@@ -5025,6 +5037,8 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
        int first = 0;
 
        dev = b43_bus_dev_ssb_init(sdev);
+       if (!dev)
+               return -ENOMEM;
 
        wl = ssb_get_devtypedata(sdev);
        if (!wl) {
@@ -5091,6 +5105,14 @@ static void b43_ssb_remove(struct ssb_device *sdev)
        }
 }
 
+static struct ssb_driver b43_ssb_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = b43_ssb_tbl,
+       .probe          = b43_ssb_probe,
+       .remove         = b43_ssb_remove,
+};
+#endif /* CONFIG_B43_SSB */
+
 /* Perform a hardware reset. This can be called from any context. */
 void b43_controller_restart(struct b43_wldev *dev, const char *reason)
 {
@@ -5101,13 +5123,6 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason)
        ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
 }
 
-static struct ssb_driver b43_ssb_driver = {
-       .name           = KBUILD_MODNAME,
-       .id_table       = b43_ssb_tbl,
-       .probe          = b43_ssb_probe,
-       .remove         = b43_ssb_remove,
-};
-
 static void b43_print_driverinfo(void)
 {
        const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "",
@@ -5151,14 +5166,18 @@ static int __init b43_init(void)
        if (err)
                goto err_sdio_exit;
 #endif
+#ifdef CONFIG_B43_SSB
        err = ssb_driver_register(&b43_ssb_driver);
        if (err)
                goto err_bcma_driver_exit;
+#endif
        b43_print_driverinfo();
 
        return err;
 
+#ifdef CONFIG_B43_SSB
 err_bcma_driver_exit:
+#endif
 #ifdef CONFIG_B43_BCMA
        bcma_driver_unregister(&b43_bcma_driver);
 err_sdio_exit:
@@ -5173,7 +5192,9 @@ err_dfs_exit:
 
 static void __exit b43_exit(void)
 {
+#ifdef CONFIG_B43_SSB
        ssb_driver_unregister(&b43_ssb_driver);
+#endif
 #ifdef CONFIG_B43_BCMA
        bcma_driver_unregister(&b43_bcma_driver);
 #endif
index 425af28..9705950 100644 (file)
@@ -31,6 +31,7 @@
 #include "phy_a.h"
 #include "phy_n.h"
 #include "phy_lp.h"
+#include "phy_ht.h"
 #include "b43.h"
 #include "main.h"
 
@@ -57,6 +58,11 @@ int b43_phy_allocate(struct b43_wldev *dev)
        case B43_PHYTYPE_LP:
 #ifdef CONFIG_B43_PHY_LP
                phy->ops = &b43_phyops_lp;
+#endif
+               break;
+       case B43_PHYTYPE_HT:
+#ifdef CONFIG_B43_PHY_HT
+               phy->ops = &b43_phyops_ht;
 #endif
                break;
        }
index 2401bee..47dcb80 100644 (file)
@@ -194,6 +194,7 @@ struct b43_phy_a;
 struct b43_phy_g;
 struct b43_phy_n;
 struct b43_phy_lp;
+struct b43_phy_ht;
 
 struct b43_phy {
        /* Hardware operation callbacks. */
@@ -216,6 +217,8 @@ struct b43_phy {
                struct b43_phy_n *n;
                /* LP-PHY specific information */
                struct b43_phy_lp *lp;
+               /* HT-PHY specific information */
+               struct b43_phy_ht *ht;
        };
 
        /* Band support flags. */
diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c
new file mode 100644 (file)
index 0000000..72f01ce
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n HT-PHY support
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/slab.h>
+
+#include "b43.h"
+#include "phy_ht.h"
+#include "radio_2059.h"
+#include "main.h"
+
+static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
+                       const struct b43_phy_ht_channeltab_e_radio2059 *e)
+{
+       u8 i;
+       u16 routing;
+
+       b43_radio_write(dev, 0x16, e->radio_syn16);
+       b43_radio_write(dev, 0x17, e->radio_syn17);
+       b43_radio_write(dev, 0x22, e->radio_syn22);
+       b43_radio_write(dev, 0x25, e->radio_syn25);
+       b43_radio_write(dev, 0x27, e->radio_syn27);
+       b43_radio_write(dev, 0x28, e->radio_syn28);
+       b43_radio_write(dev, 0x29, e->radio_syn29);
+       b43_radio_write(dev, 0x2c, e->radio_syn2c);
+       b43_radio_write(dev, 0x2d, e->radio_syn2d);
+       b43_radio_write(dev, 0x37, e->radio_syn37);
+       b43_radio_write(dev, 0x41, e->radio_syn41);
+       b43_radio_write(dev, 0x43, e->radio_syn43);
+       b43_radio_write(dev, 0x47, e->radio_syn47);
+       b43_radio_write(dev, 0x4a, e->radio_syn4a);
+       b43_radio_write(dev, 0x58, e->radio_syn58);
+       b43_radio_write(dev, 0x5a, e->radio_syn5a);
+       b43_radio_write(dev, 0x6a, e->radio_syn6a);
+       b43_radio_write(dev, 0x6d, e->radio_syn6d);
+       b43_radio_write(dev, 0x6e, e->radio_syn6e);
+       b43_radio_write(dev, 0x92, e->radio_syn92);
+       b43_radio_write(dev, 0x98, e->radio_syn98);
+
+       for (i = 0; i < 2; i++) {
+               routing = i ? 0x800 : 0x400;
+               b43_radio_write(dev, routing | 0x4a, e->radio_rxtx4a);
+               b43_radio_write(dev, routing | 0x58, e->radio_rxtx58);
+               b43_radio_write(dev, routing | 0x5a, e->radio_rxtx5a);
+               b43_radio_write(dev, routing | 0x6a, e->radio_rxtx6a);
+               b43_radio_write(dev, routing | 0x6d, e->radio_rxtx6d);
+               b43_radio_write(dev, routing | 0x6e, e->radio_rxtx6e);
+               b43_radio_write(dev, routing | 0x92, e->radio_rxtx92);
+               b43_radio_write(dev, routing | 0x98, e->radio_rxtx98);
+       }
+
+       udelay(50);
+
+       /* Calibration */
+       b43_radio_mask(dev, 0x2b, ~0x1);
+       b43_radio_mask(dev, 0x2e, ~0x4);
+       b43_radio_set(dev, 0x2e, 0x4);
+       b43_radio_set(dev, 0x2b, 0x1);
+
+       udelay(300);
+}
+
+static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
+                               const struct b43_phy_ht_channeltab_e_phy *e,
+                               struct ieee80211_channel *new_channel)
+{
+       /* TODO */
+}
+
+static int b43_phy_ht_set_channel(struct b43_wldev *dev,
+                                 struct ieee80211_channel *channel,
+                                 enum nl80211_channel_type channel_type)
+{
+       struct b43_phy *phy = &dev->phy;
+
+       const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL;
+
+       if (phy->radio_ver == 0x2059) {
+               chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev,
+                                                       channel->center_freq);
+               if (!chent_r2059)
+                       return -ESRCH;
+       } else {
+               return -ESRCH;
+       }
+
+       /* TODO: In case of N-PHY some bandwidth switching goes here */
+
+       if (phy->radio_ver == 0x2059) {
+               b43_radio_2059_channel_setup(dev, chent_r2059);
+               b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs),
+                                        channel);
+       } else {
+               return -ESRCH;
+       }
+
+       return 0;
+}
+
+/**************************************************
+ * Basic PHY ops.
+ **************************************************/
+
+static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
+{
+       struct b43_phy_ht *phy_ht;
+
+       phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
+       if (!phy_ht)
+               return -ENOMEM;
+       dev->phy.ht = phy_ht;
+
+       return 0;
+}
+
+static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
+{
+       struct b43_phy *phy = &dev->phy;
+       struct b43_phy_ht *phy_ht = phy->ht;
+
+       memset(phy_ht, 0, sizeof(*phy_ht));
+}
+
+static void b43_phy_ht_op_free(struct b43_wldev *dev)
+{
+       struct b43_phy *phy = &dev->phy;
+       struct b43_phy_ht *phy_ht = phy->ht;
+
+       kfree(phy_ht);
+       phy->ht = NULL;
+}
+
+/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
+static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev,
+                                       bool blocked)
+{
+       if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
+               b43err(dev->wl, "MAC not suspended\n");
+
+       if (blocked) {
+               b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+       } else {
+               b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+               b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x1);
+               b43_phy_mask(dev, B43_PHY_HT_RF_CTL1, ~0);
+               b43_phy_maskset(dev, B43_PHY_HT_RF_CTL1, ~0, 0x2);
+       }
+}
+
+static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
+{
+       if (on) {
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00cd);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x0000);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00cd);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x0000);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00cd);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x0000);
+       } else {
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0x07ff);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL2, 0x00fd);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0x07ff);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL4, 0x00fd);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0x07ff);
+               b43_phy_write(dev, B43_PHY_HT_AFE_CTL6, 0x00fd);
+       }
+}
+
+static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
+                                       unsigned int new_channel)
+{
+       struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
+       enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
+
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
+               if ((new_channel < 1) || (new_channel > 14))
+                       return -EINVAL;
+       } else {
+               return -EINVAL;
+       }
+
+       return b43_phy_ht_set_channel(dev, channel, channel_type);
+}
+
+static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
+{
+       if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+               return 1;
+       return 36;
+}
+
+/**************************************************
+ * R/W ops.
+ **************************************************/
+
+static u16 b43_phy_ht_op_read(struct b43_wldev *dev, u16 reg)
+{
+       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_PHY_DATA);
+}
+
+static void b43_phy_ht_op_write(struct b43_wldev *dev, u16 reg, u16 value)
+{
+       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA, value);
+}
+
+static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
+                                u16 set)
+{
+       b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_PHY_DATA,
+                   (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
+}
+
+static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
+{
+       /* HT-PHY needs 0x200 for read access */
+       reg |= 0x200;
+
+       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       return b43_read16(dev, B43_MMIO_RADIO24_DATA);
+}
+
+static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
+                                     u16 value)
+{
+       b43_write16(dev, B43_MMIO_RADIO24_CONTROL, reg);
+       b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
+}
+
+/**************************************************
+ * PHY ops struct.
+ **************************************************/
+
+const struct b43_phy_operations b43_phyops_ht = {
+       .allocate               = b43_phy_ht_op_allocate,
+       .free                   = b43_phy_ht_op_free,
+       .prepare_structs        = b43_phy_ht_op_prepare_structs,
+       /*
+       .init                   = b43_phy_ht_op_init,
+       */
+       .phy_read               = b43_phy_ht_op_read,
+       .phy_write              = b43_phy_ht_op_write,
+       .phy_maskset            = b43_phy_ht_op_maskset,
+       .radio_read             = b43_phy_ht_op_radio_read,
+       .radio_write            = b43_phy_ht_op_radio_write,
+       .software_rfkill        = b43_phy_ht_op_software_rfkill,
+       .switch_analog          = b43_phy_ht_op_switch_analog,
+       .switch_channel         = b43_phy_ht_op_switch_channel,
+       .get_default_chan       = b43_phy_ht_op_get_default_chan,
+       /*
+       .recalc_txpower         = b43_phy_ht_op_recalc_txpower,
+       .adjust_txpower         = b43_phy_ht_op_adjust_txpower,
+       */
+};
diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h
new file mode 100644 (file)
index 0000000..afa448d
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef B43_PHY_HT_H_
+#define B43_PHY_HT_H_
+
+#include "phy_common.h"
+
+
+#define B43_PHY_HT_TABLE_ADDR                  0x072 /* Table address */
+#define B43_PHY_HT_TABLE_DATALO                        0x073 /* Table data low */
+#define B43_PHY_HT_TABLE_DATAHI                        0x074 /* Table data high */
+
+#define B43_PHY_HT_RF_CTL1                     B43_PHY_EXTG(0x010)
+
+#define B43_PHY_HT_AFE_CTL1                    B43_PHY_EXTG(0x110)
+#define B43_PHY_HT_AFE_CTL2                    B43_PHY_EXTG(0x111)
+#define B43_PHY_HT_AFE_CTL3                    B43_PHY_EXTG(0x114)
+#define B43_PHY_HT_AFE_CTL4                    B43_PHY_EXTG(0x115)
+#define B43_PHY_HT_AFE_CTL5                    B43_PHY_EXTG(0x118)
+#define B43_PHY_HT_AFE_CTL6                    B43_PHY_EXTG(0x119)
+
+
+/* Values for PHY registers used on channel switching */
+struct b43_phy_ht_channeltab_e_phy {
+       /* TODO */
+};
+
+
+struct b43_phy_ht {
+};
+
+
+struct b43_phy_operations;
+extern const struct b43_phy_operations b43_phyops_ht;
+
+#endif /* B43_PHY_HT_H_ */
index ad14f3b..e7dfdac 100644 (file)
@@ -4025,11 +4025,24 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
 {
-       u16 val = on ? 0 : 0x7FFF;
+       u16 override = on ? 0x0 : 0x7FFF;
+       u16 core = on ? 0xD : 0x00FD;
 
-       if (dev->phy.rev >= 3)
-               b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
-       b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
+       if (dev->phy.rev >= 3) {
+               if (on) {
+                       b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+                       b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+                       b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+                       b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+               } else {
+                       b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
+                       b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
+                       b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+                       b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
+               }
+       } else {
+               b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
+       }
 }
 
 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
index d9bfa0f..67f9612 100644 (file)
@@ -251,4 +251,9 @@ struct b43_nphy_channeltab_entry_rev2 {
 void b2055_upload_inittab(struct b43_wldev *dev,
                          bool ghz5, bool ignore_uploadflag);
 
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev2 *
+b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
+
 #endif /* B43_RADIO_2055_H_ */
index d601f6e..d52df6b 100644 (file)
@@ -1117,4 +1117,9 @@ struct b43_nphy_channeltab_entry_rev3 {
 void b2056_upload_inittabs(struct b43_wldev *dev,
                           bool ghz5, bool ignore_uploadflag);
 
+/* Get the NPHY Channel Switch Table entry for a channel.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry_rev3 *
+b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
+
 #endif /* B43_RADIO_2056_H_ */
diff --git a/drivers/net/wireless/b43/radio_2059.c b/drivers/net/wireless/b43/radio_2059.c
new file mode 100644 (file)
index 0000000..55d7da7
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+
+  Broadcom B43 wireless driver
+  IEEE 802.11n 2059 radio device data tables
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; see the file COPYING.  If not, write to
+  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+  Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "radio_2059.h"
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq)
+{
+       return NULL;
+}
diff --git a/drivers/net/wireless/b43/radio_2059.h b/drivers/net/wireless/b43/radio_2059.h
new file mode 100644 (file)
index 0000000..c2874b1
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef B43_RADIO_2059_H_
+#define B43_RADIO_2059_H_
+
+#include <linux/types.h>
+
+#include "phy_ht.h"
+
+/* Values for various registers uploaded on channel switching */
+struct b43_phy_ht_channeltab_e_radio2059 {
+       /* The channel frequency in MHz */
+       u16 freq;
+       /* Values for radio registers */
+       u8 radio_syn16;
+       u8 radio_syn17;
+       u8 radio_syn22;
+       u8 radio_syn25;
+       u8 radio_syn27;
+       u8 radio_syn28;
+       u8 radio_syn29;
+       u8 radio_syn2c;
+       u8 radio_syn2d;
+       u8 radio_syn37;
+       u8 radio_syn41;
+       u8 radio_syn43;
+       u8 radio_syn47;
+       u8 radio_syn4a;
+       u8 radio_syn58;
+       u8 radio_syn5a;
+       u8 radio_syn6a;
+       u8 radio_syn6d;
+       u8 radio_syn6e;
+       u8 radio_syn92;
+       u8 radio_syn98;
+       u8 radio_rxtx4a;
+       u8 radio_rxtx58;
+       u8 radio_rxtx5a;
+       u8 radio_rxtx6a;
+       u8 radio_rxtx6d;
+       u8 radio_rxtx6e;
+       u8 radio_rxtx92;
+       u8 radio_rxtx98;
+       /* Values for PHY registers */
+       struct b43_phy_ht_channeltab_e_phy phy_regs;
+};
+
+const struct b43_phy_ht_channeltab_e_radio2059
+*b43_phy_ht_get_channeltab_e_r2059(struct b43_wldev *dev, u16 freq);
+
+#endif /* B43_RADIO_2059_H_ */
index e6c733d..4fd6775 100644 (file)
@@ -93,8 +93,8 @@ void b43_sdio_free_irq(struct b43_wldev *dev)
        sdio->irq_handler = NULL;
 }
 
-static int b43_sdio_probe(struct sdio_func *func,
-                         const struct sdio_device_id *id)
+static int __devinit b43_sdio_probe(struct sdio_func *func,
+                                   const struct sdio_device_id *id)
 {
        struct b43_sdio *sdio;
        struct sdio_func_tuple *tuple;
@@ -171,7 +171,7 @@ out:
        return error;
 }
 
-static void b43_sdio_remove(struct sdio_func *func)
+static void __devexit b43_sdio_remove(struct sdio_func *func)
 {
        struct b43_sdio *sdio = sdio_get_drvdata(func);
 
index 1856936..a81696b 100644 (file)
@@ -60,16 +60,8 @@ struct nphy_gain_ctl_workaround_entry {
 struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
        struct b43_wldev *dev, bool ghz5, bool ext_lna);
 
-/* Get the NPHY Channel Switch Table entry for a channel.
- * Returns NULL on failure to find an entry. */
-const struct b43_nphy_channeltab_entry_rev2 *
-b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel);
-const struct b43_nphy_channeltab_entry_rev3 *
-b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq);
-
 
 /* The N-PHY tables. */
-
 #define B43_NTAB_TYPEMASK              0xF0000000
 #define B43_NTAB_8BIT                  0x10000000
 #define B43_NTAB_16BIT                 0x20000000
index d096dc2..dab67a1 100644 (file)
@@ -408,7 +408,6 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
        iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
 #endif
-       iwl_legacy_recover_from_statistics(priv, pkt);
 
        memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
 }
@@ -2640,7 +2639,6 @@ static struct iwl_lib_ops iwl3945_lib = {
        .txq_free_tfd = iwl3945_hw_txq_free_tfd,
        .txq_init = iwl3945_hw_tx_queue_init,
        .load_ucode = iwl3945_load_bsm,
-       .dump_nic_event_log = iwl3945_dump_nic_event_log,
        .dump_nic_error_log = iwl3945_dump_nic_error_log,
        .apm_ops = {
                .init = iwl3945_apm_init,
@@ -2698,9 +2696,7 @@ static struct iwl_base_params iwl3945_base_params = {
        .set_l0s = false,
        .use_bsm = true,
        .led_compensation = 64,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
-       .max_event_log_size = 512,
 };
 
 static struct iwl_cfg iwl3945_bg_cfg = {
index a7a4739..2be6d9e 100644 (file)
@@ -694,47 +694,6 @@ void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
               sizeof(struct iwl_rx_phy_res));
 }
 
-static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv,
-                                          struct ieee80211_vif *vif,
-                                          enum ieee80211_band band,
-                                          struct iwl_scan_channel *scan_ch)
-{
-       const struct ieee80211_supported_band *sband;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int added = 0;
-       u16 channel = 0;
-
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband) {
-               IWL_ERR(priv, "invalid band\n");
-               return added;
-       }
-
-       active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
-       passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-
-       channel = iwl_legacy_get_single_channel_number(priv, band);
-       if (channel) {
-               scan_ch->channel = cpu_to_le16(channel);
-               scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-               /* Set txpower levels to defaults */
-               scan_ch->dsp_atten = 110;
-               if (band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-               added++;
-       } else
-               IWL_ERR(priv, "no valid channel found\n");
-       return added;
-}
-
 static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
                                     struct ieee80211_vif *vif,
                                     enum ieee80211_band band,
@@ -858,16 +817,13 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
        if (iwl_legacy_is_any_associated(priv)) {
-               u16 interval = 0;
+               u16 interval;
                u32 extra;
                u32 suspend_time = 100;
                u32 scan_suspend_time = 100;
 
                IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-               if (priv->is_internal_short_scan)
-                       interval = 0;
-               else
-                       interval = vif->bss_conf.beacon_int;
+               interval = vif->bss_conf.beacon_int;
 
                scan->suspend_time = 0;
                scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -882,9 +838,7 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
                               scan_suspend_time, interval);
        }
 
-       if (priv->is_internal_short_scan) {
-               IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-       } else if (priv->scan_request->n_ssids) {
+       if (priv->scan_request->n_ssids) {
                int i, p = 0;
                IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
                for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -981,38 +935,21 @@ int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
        rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
        scan->rx_chain = cpu_to_le16(rx_chain);
-       if (!priv->is_internal_short_scan) {
-               cmd_len = iwl_legacy_fill_probe_req(priv,
+
+       cmd_len = iwl_legacy_fill_probe_req(priv,
                                        (struct ieee80211_mgmt *)scan->data,
                                        vif->addr,
                                        priv->scan_request->ie,
                                        priv->scan_request->ie_len,
                                        IWL_MAX_SCAN_SIZE - sizeof(*scan));
-       } else {
-               /* use bcast addr, will not be transmitted but must be valid */
-               cmd_len = iwl_legacy_fill_probe_req(priv,
-                                       (struct ieee80211_mgmt *)scan->data,
-                                       iwlegacy_bcast_addr, NULL, 0,
-                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
-       }
        scan->tx_cmd.len = cpu_to_le16(cmd_len);
 
        scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
                               RXON_FILTER_BCON_AWARE_MSK);
 
-       if (priv->is_internal_short_scan) {
-               scan->channel_count =
-                       iwl4965_get_single_channel_for_scan(priv, vif, band,
-                               (void *)&scan->data[le16_to_cpu(
-                               scan->tx_cmd.len)]);
-       } else {
-               scan->channel_count =
-                       iwl4965_get_channels_for_scan(priv, vif, band,
-                               is_active, n_probes,
-                               (void *)&scan->data[le16_to_cpu(
-                               scan->tx_cmd.len)]);
-       }
+       scan->channel_count = iwl4965_get_channels_for_scan(priv, vif, band,
+                                               is_active, n_probes,
+                                               (void *)&scan->data[cmd_len]);
        if (scan->channel_count == 0) {
                IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
                return -EIO;
index b9fa2f6..2b144bb 100644 (file)
@@ -151,81 +151,6 @@ static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
 
 #define REG_RECALIB_PERIOD (60)
 
-/**
- * iwl4965_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl4965_good_plcp_health(struct iwl_priv *priv,
-                               struct iwl_rx_packet *pkt)
-{
-       bool rc = true;
-       int combined_plcp_delta;
-       unsigned int plcp_msec;
-       unsigned long plcp_received_jiffies;
-
-       if (priv->cfg->base_params->plcp_delta_threshold ==
-           IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
-               IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
-               return rc;
-       }
-
-       /*
-        * check for plcp_err and trigger radio reset if it exceeds
-        * the plcp error threshold plcp_delta.
-        */
-       plcp_received_jiffies = jiffies;
-       plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-                                       (long) priv->plcp_jiffies);
-       priv->plcp_jiffies = plcp_received_jiffies;
-       /*
-        * check to make sure plcp_msec is not 0 to prevent division
-        * by zero.
-        */
-       if (plcp_msec) {
-               struct statistics_rx_phy *ofdm;
-               struct statistics_rx_ht_phy *ofdm_ht;
-
-               ofdm = &pkt->u.stats.rx.ofdm;
-               ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
-               combined_plcp_delta =
-                   (le32_to_cpu(ofdm->plcp_err) -
-                   le32_to_cpu(priv->_4965.statistics.
-                               rx.ofdm.plcp_err)) +
-                   (le32_to_cpu(ofdm_ht->plcp_err) -
-                   le32_to_cpu(priv->_4965.statistics.
-                               rx.ofdm_ht.plcp_err));
-
-               if ((combined_plcp_delta > 0) &&
-                   ((combined_plcp_delta * 100) / plcp_msec) >
-                       priv->cfg->base_params->plcp_delta_threshold) {
-                       /*
-                        * if plcp_err exceed the threshold,
-                        * the following data is printed in csv format:
-                        *    Text: plcp_err exceeded %d,
-                        *    Received ofdm.plcp_err,
-                        *    Current ofdm.plcp_err,
-                        *    Received ofdm_ht.plcp_err,
-                        *    Current ofdm_ht.plcp_err,
-                        *    combined_plcp_delta,
-                        *    plcp_msec
-                        */
-                       IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-                               "%u, %u, %u, %u, %d, %u mSecs\n",
-                               priv->cfg->base_params->plcp_delta_threshold,
-                               le32_to_cpu(ofdm->plcp_err),
-                               le32_to_cpu(ofdm->plcp_err),
-                               le32_to_cpu(ofdm_ht->plcp_err),
-                               le32_to_cpu(ofdm_ht->plcp_err),
-                               combined_plcp_delta, plcp_msec);
-
-                       rc = false;
-               }
-       }
-       return rc;
-}
-
 void iwl4965_rx_statistics(struct iwl_priv *priv,
                              struct iwl_rx_mem_buffer *rxb)
 {
@@ -248,8 +173,7 @@ void iwl4965_rx_statistics(struct iwl_priv *priv,
        iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
 #endif
 
-       iwl_legacy_recover_from_statistics(priv, pkt);
-
+       /* TODO: reading some of statistics is unneeded */
        memcpy(&priv->_4965.statistics, &pkt->u.stats,
                sizeof(priv->_4965.statistics));
 
index 9cf96cb..bd4b000 100644 (file)
@@ -2069,7 +2069,6 @@ static struct iwl_lib_ops iwl4965_lib = {
        .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
        .init_alive_start = iwl4965_init_alive_start,
        .load_ucode = iwl4965_load_bsm,
-       .dump_nic_event_log = iwl4965_dump_nic_event_log,
        .dump_nic_error_log = iwl4965_dump_nic_error_log,
        .dump_fh = iwl4965_dump_fh,
        .set_channel_switch = iwl4965_hw_channel_switch,
@@ -2100,7 +2099,6 @@ static struct iwl_lib_ops iwl4965_lib = {
                .tx_stats_read = iwl4965_ucode_tx_stats_read,
                .general_stats_read = iwl4965_ucode_general_stats_read,
        },
-       .check_plcp_health = iwl4965_good_plcp_health,
 };
 
 static const struct iwl_legacy_ops iwl4965_legacy_ops = {
@@ -2150,10 +2148,8 @@ static struct iwl_base_params iwl4965_base_params = {
        .use_bsm = true,
        .led_compensation = 61,
        .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
-       .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
        .wd_timeout = IWL_DEF_WD_TIMEOUT,
        .temperature_kelvin = true,
-       .max_event_log_size = 512,
        .ucode_tracing = true,
        .sensitivity_calib_by_driver = true,
        .chain_noise_calib_by_driver = true,
index 17a1d50..ee21210 100644 (file)
@@ -2297,14 +2297,7 @@ struct iwl_spectrum_notification {
 #define IWL_POWER_VEC_SIZE 5
 
 #define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK       cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_SAVE_ENA_MSK           cpu_to_le16(BIT(0))
-#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK     cpu_to_le16(BIT(1))
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK          cpu_to_le16(BIT(2))
 #define IWL_POWER_PCI_PM_MSK                   cpu_to_le16(BIT(3))
-#define IWL_POWER_FAST_PD                      cpu_to_le16(BIT(4))
-#define IWL_POWER_BEACON_FILTERING             cpu_to_le16(BIT(5))
-#define IWL_POWER_SHADOW_REG_ENA               cpu_to_le16(BIT(6))
-#define IWL_POWER_CT_KILL_SET                  cpu_to_le16(BIT(7))
 
 struct iwl3945_powertable_cmd {
        __le16 flags;
index 3be76bd..35cd253 100644 (file)
@@ -931,7 +931,6 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
        priv->cfg->ops->lib->dump_nic_error_log(priv);
        if (priv->cfg->ops->lib->dump_fh)
                priv->cfg->ops->lib->dump_fh(priv, NULL, false);
-       priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
        if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
                iwl_legacy_print_rx_config_cmd(priv,
@@ -1707,41 +1706,14 @@ iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
 EXPORT_SYMBOL(iwl_legacy_update_stats);
 #endif
 
-static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
-{
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       if (!iwl_legacy_is_any_associated(priv)) {
-               IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
-               return;
-       }
-       /*
-        * There is no easy and better way to force reset the radio,
-        * the only known method is switching channel which will force to
-        * reset and tune the radio.
-        * Use internal short scan (single channel) operation to should
-        * achieve this objective.
-        * Driver should reset the radio when number of consecutive missed
-        * beacon, or any other uCode error condition detected.
-        */
-       IWL_DEBUG_INFO(priv, "perform radio reset.\n");
-       iwl_legacy_internal_short_hw_scan(priv);
-}
-
-
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
 {
        struct iwl_force_reset *force_reset;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return -EINVAL;
 
-       if (mode >= IWL_MAX_FORCE_RESET) {
-               IWL_DEBUG_INFO(priv, "invalid reset request.\n");
-               return -EINVAL;
-       }
-       force_reset = &priv->force_reset[mode];
+       force_reset = &priv->force_reset;
        force_reset->reset_request_count++;
        if (!external) {
                if (force_reset->last_force_reset_jiffies &&
@@ -1754,37 +1726,34 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
        }
        force_reset->reset_success_count++;
        force_reset->last_force_reset_jiffies = jiffies;
-       IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
-       switch (mode) {
-       case IWL_RF_RESET:
-               _iwl_legacy_force_rf_reset(priv);
-               break;
-       case IWL_FW_RESET:
-               /*
-                * if the request is from external(ex: debugfs),
-                * then always perform the request in regardless the module
-                * parameter setting
-                * if the request is from internal (uCode error or driver
-                * detect failure), then fw_restart module parameter
-                * need to be check before performing firmware reload
-                */
-               if (!external && !priv->cfg->mod_params->restart_fw) {
-                       IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
-                                      "module parameter setting\n");
-                       break;
-               }
-               IWL_ERR(priv, "On demand firmware reload\n");
-               /* Set the FW error flag -- cleared on iwl_down */
-               set_bit(STATUS_FW_ERROR, &priv->status);
-               wake_up_interruptible(&priv->wait_command_queue);
-               /*
-                * Keep the restart process from trying to send host
-                * commands by clearing the INIT status bit
-                */
-               clear_bit(STATUS_READY, &priv->status);
-               queue_work(priv->workqueue, &priv->restart);
-               break;
+
+       /*
+        * if the request is from external(ex: debugfs),
+        * then always perform the request in regardless the module
+        * parameter setting
+        * if the request is from internal (uCode error or driver
+        * detect failure), then fw_restart module parameter
+        * need to be check before performing firmware reload
+        */
+
+       if (!external && !priv->cfg->mod_params->restart_fw) {
+               IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+                              "module parameter setting\n");
+               return 0;
        }
+
+       IWL_ERR(priv, "On demand firmware reload\n");
+
+       /* Set the FW error flag -- cleared on iwl_down */
+       set_bit(STATUS_FW_ERROR, &priv->status);
+       wake_up_interruptible(&priv->wait_command_queue);
+       /*
+        * Keep the restart process from trying to send host
+        * commands by clearing the INIT status bit
+        */
+       clear_bit(STATUS_READY, &priv->status);
+       queue_work(priv->workqueue, &priv->restart);
+
        return 0;
 }
 
@@ -1879,7 +1848,7 @@ static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
        if (time_after(jiffies, timeout)) {
                IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
                                q->id, priv->cfg->base_params->wd_timeout);
-               ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+               ret = iwl_legacy_force_reset(priv, false);
                return (ret == -EAGAIN) ? 0 : 1;
        }
 
index c5fbda0..a2de7e9 100644 (file)
@@ -143,8 +143,7 @@ struct iwl_lib_ops {
        int (*is_valid_rtc_data_addr)(u32 addr);
        /* 1st ucode load */
        int (*load_ucode)(struct iwl_priv *priv);
-       int (*dump_nic_event_log)(struct iwl_priv *priv,
-                                 bool full_log, char **buf, bool display);
+
        void (*dump_nic_error_log)(struct iwl_priv *priv);
        int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
        int (*set_channel_switch)(struct iwl_priv *priv,
@@ -161,9 +160,6 @@ struct iwl_lib_ops {
 
        /* temperature */
        struct iwl_temp_ops temp_ops;
-       /* check for plcp health */
-       bool (*check_plcp_health)(struct iwl_priv *priv,
-                                       struct iwl_rx_packet *pkt);
 
        struct iwl_debugfs_ops debugfs_ops;
 
@@ -207,11 +203,8 @@ struct iwl_mod_params {
  *     to the deviation to achieve the desired led frequency.
  *     The detail algorithm is described in iwl-led.c
  * @chain_noise_num_beacons: number of beacons used to compute chain noise
- * @plcp_delta_threshold: plcp error rate threshold used to trigger
- *     radio tuning when there is a high receiving plcp error rate
  * @wd_timeout: TX queues watchdog timeout
  * @temperature_kelvin: temperature report by uCode in kelvin
- * @max_event_log_size: size of event log buffer size for ucode event logging
  * @ucode_tracing: support ucode continuous tracing
  * @sensitivity_calib_by_driver: driver has the capability to perform
  *     sensitivity calibration operation
@@ -229,10 +222,8 @@ struct iwl_base_params {
 
        u16 led_compensation;
        int chain_noise_num_beacons;
-       u8 plcp_delta_threshold;
        unsigned int wd_timeout;
        bool temperature_kelvin;
-       u32 max_event_log_size;
        const bool ucode_tracing;
        const bool sensitivity_calib_by_driver;
        const bool chain_noise_calib_by_driver;
@@ -441,7 +432,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
                    struct ieee80211_vif *vif,
                    struct cfg80211_scan_request *req);
 void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
-int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+int iwl_legacy_force_reset(struct iwl_priv *priv, bool external);
 u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
                        struct ieee80211_mgmt *frame,
                       const u8 *ta, const u8 *ie, int ie_len, int left);
@@ -521,8 +512,6 @@ extern const struct dev_pm_ops iwl_legacy_pm_ops;
 *  Error Handling Debugging
 ******************************************************/
 void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
-                          bool full_log, char **buf, bool display);
 #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
 void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
                             struct iwl_rxon_context *ctx);
index 2d32438..996996a 100644 (file)
@@ -391,48 +391,6 @@ static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
        return ret;
 }
 
-static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
-                                        char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char *buf;
-       int pos = 0;
-       ssize_t ret = -ENOMEM;
-
-       ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
-                                       priv, true, &buf, true);
-       if (buf) {
-               ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-               kfree(buf);
-       }
-       return ret;
-}
-
-static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       u32 event_log_flag;
-       char buf[8];
-       int buf_size;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &event_log_flag) != 1)
-               return -EFAULT;
-       if (event_log_flag == 1)
-               priv->cfg->ops->lib->dump_nic_event_log(priv, true,
-                                                       NULL, false);
-
-       return count;
-}
-
-
-
 static ssize_t
 iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
                                       size_t count, loff_t *ppos)
@@ -706,7 +664,6 @@ static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
 }
 
 DEBUGFS_READ_WRITE_FILE_OPS(sram);
-DEBUGFS_READ_WRITE_FILE_OPS(log_event);
 DEBUGFS_READ_FILE_OPS(nvm);
 DEBUGFS_READ_FILE_OPS(stations);
 DEBUGFS_READ_FILE_OPS(channels);
@@ -1098,56 +1055,6 @@ static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_write(struct file *file,
        return count;
 }
 
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char buf[128];
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
-                       priv->event_log.ucode_trace ? "On" : "Off");
-       pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
-                       priv->event_log.non_wraps_count);
-       pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
-                       priv->event_log.wraps_once_count);
-       pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
-                       priv->event_log.wraps_more_count);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_ucode_tracing_write(struct file *file,
-                                        const char __user *user_buf,
-                                        size_t count, loff_t *ppos)
-{
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int trace;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &trace) != 1)
-               return -EFAULT;
-
-       if (trace) {
-               priv->event_log.ucode_trace = true;
-               /* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
-               mod_timer(&priv->ucode_trace,
-                       jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
-       } else {
-               priv->event_log.ucode_trace = false;
-               del_timer_sync(&priv->ucode_trace);
-       }
-
-       return count;
-}
-
 static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
                                         char __user *user_buf,
                                         size_t count, loff_t *ppos) {
@@ -1236,72 +1143,31 @@ static ssize_t iwl_legacy_dbgfs_missed_beacon_write(struct file *file,
        return count;
 }
 
-static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
-                                       char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       int pos = 0;
-       char buf[12];
-       const size_t bufsz = sizeof(buf);
-
-       pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
-                       priv->cfg->base_params->plcp_delta_threshold);
-
-       return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
-static ssize_t iwl_legacy_dbgfs_plcp_delta_write(struct file *file,
-                                       const char __user *user_buf,
-                                       size_t count, loff_t *ppos) {
-
-       struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int plcp;
-
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &plcp) != 1)
-               return -EINVAL;
-       if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
-               (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
-               priv->cfg->base_params->plcp_delta_threshold =
-                       IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
-       else
-               priv->cfg->base_params->plcp_delta_threshold = plcp;
-       return count;
-}
-
 static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
                                        char __user *user_buf,
                                        size_t count, loff_t *ppos) {
 
        struct iwl_priv *priv = file->private_data;
-       int i, pos = 0;
+       int pos = 0;
        char buf[300];
        const size_t bufsz = sizeof(buf);
        struct iwl_force_reset *force_reset;
 
-       for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
-               force_reset = &priv->force_reset[i];
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "Force reset method %d\n", i);
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "\tnumber of reset request: %d\n",
-                               force_reset->reset_request_count);
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "\tnumber of reset request success: %d\n",
-                               force_reset->reset_success_count);
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "\tnumber of reset request reject: %d\n",
-                               force_reset->reset_reject_count);
-               pos += scnprintf(buf + pos, bufsz - pos,
-                               "\treset duration: %lu\n",
-                               force_reset->reset_duration);
-       }
+       force_reset = &priv->force_reset;
+
+       pos += scnprintf(buf + pos, bufsz - pos,
+                       "\tnumber of reset request: %d\n",
+                       force_reset->reset_request_count);
+       pos += scnprintf(buf + pos, bufsz - pos,
+                       "\tnumber of reset request success: %d\n",
+                       force_reset->reset_success_count);
+       pos += scnprintf(buf + pos, bufsz - pos,
+                       "\tnumber of reset request reject: %d\n",
+                       force_reset->reset_reject_count);
+       pos += scnprintf(buf + pos, bufsz - pos,
+                       "\treset duration: %lu\n",
+                       force_reset->reset_duration);
+
        return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
@@ -1309,25 +1175,11 @@ static ssize_t iwl_legacy_dbgfs_force_reset_write(struct file *file,
                                        const char __user *user_buf,
                                        size_t count, loff_t *ppos) {
 
+       int ret;
        struct iwl_priv *priv = file->private_data;
-       char buf[8];
-       int buf_size;
-       int reset, ret;
 
-       memset(buf, 0, sizeof(buf));
-       buf_size = min(count, sizeof(buf) -  1);
-       if (copy_from_user(buf, user_buf, buf_size))
-               return -EFAULT;
-       if (sscanf(buf, "%d", &reset) != 1)
-               return -EINVAL;
-       switch (reset) {
-       case IWL_RF_RESET:
-       case IWL_FW_RESET:
-               ret = iwl_legacy_force_reset(priv, reset, true);
-               break;
-       default:
-               return -EINVAL;
-       }
+       ret = iwl_legacy_force_reset(priv, true);
+
        return ret ? ret : count;
 }
 
@@ -1367,10 +1219,8 @@ DEBUGFS_READ_FILE_OPS(chain_noise);
 DEBUGFS_READ_FILE_OPS(power_save_status);
 DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
 DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
-DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
 DEBUGFS_READ_FILE_OPS(fh_reg);
 DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
-DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
 DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
 DEBUGFS_READ_FILE_OPS(rxon_flags);
 DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
@@ -1403,7 +1253,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
 
        DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
-       DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
        DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
@@ -1420,7 +1269,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
-       DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
@@ -1430,8 +1278,6 @@ int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
                DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
        if (priv->cfg->base_params->chain_noise_calib_by_driver)
                DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
-       if (priv->cfg->base_params->ucode_tracing)
-               DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
        DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
index 0a8d07f..9c786ed 100644 (file)
@@ -855,32 +855,6 @@ struct traffic_stats {
 #endif
 };
 
-/*
- * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
- * to perform continuous uCode event logging operation if enabled
- */
-#define UCODE_TRACE_PERIOD (100)
-
-/*
- * iwl_event_log: current uCode event log position
- *
- * @ucode_trace: enable/disable ucode continuous trace timer
- * @num_wraps: how many times the event buffer wraps
- * @next_entry:  the entry just before the next one that uCode would fill
- * @non_wraps_count: counter for no wrap detected when dump ucode events
- * @wraps_once_count: counter for wrap once detected when dump ucode events
- * @wraps_more_count: counter for wrap more than once detected
- *                   when dump ucode events
- */
-struct iwl_event_log {
-       bool ucode_trace;
-       u32 num_wraps;
-       u32 next_entry;
-       int non_wraps_count;
-       int wraps_once_count;
-       int wraps_more_count;
-};
-
 /*
  * host interrupt timeout value
  * used with setting interrupt coalescing timer
@@ -896,18 +870,6 @@ struct iwl_event_log {
 #define IWL_HOST_INT_CALIB_TIMEOUT_DEF (0x10)
 #define IWL_HOST_INT_CALIB_TIMEOUT_MIN (0x0)
 
-/*
- * This is the threshold value of plcp error rate per 100mSecs.  It is
- * used to set and check for the validity of plcp_delta.
- */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (1)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
-#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF    (100)
-#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF        (200)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
-#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE     (0)
-
-#define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
 #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
 
 /* TX queue watchdog timeouts in mSecs */
@@ -915,12 +877,6 @@ struct iwl_event_log {
 #define IWL_LONG_WD_TIMEOUT    (10000)
 #define IWL_MAX_WD_TIMEOUT     (120000)
 
-enum iwl_reset {
-       IWL_RF_RESET = 0,
-       IWL_FW_RESET,
-       IWL_MAX_FORCE_RESET,
-};
-
 struct iwl_force_reset {
        int reset_request_count;
        int reset_success_count;
@@ -1033,11 +989,8 @@ struct iwl_priv {
        /* track IBSS manager (last beacon) status */
        u32 ibss_manager;
 
-       /* storing the jiffies when the plcp error rate is received */
-       unsigned long plcp_jiffies;
-
        /* force reset */
-       struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+       struct iwl_force_reset force_reset;
 
        /* we allocate array of iwl_channel_info for NIC's valid channels.
         *    Access via channel # using indirect index array */
@@ -1058,7 +1011,6 @@ struct iwl_priv {
        enum ieee80211_band scan_band;
        struct cfg80211_scan_request *scan_request;
        struct ieee80211_vif *scan_vif;
-       bool is_internal_short_scan;
        u8 scan_tx_ant[IEEE80211_NUM_BANDS];
        u8 mgmt_tx_ant;
 
@@ -1213,12 +1165,6 @@ struct iwl_priv {
 #endif
 #if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
                struct {
-                       /*
-                        * reporting the number of tids has AGG on. 0 means
-                        * no AGGREGATION
-                        */
-                       u8 agg_tids_count;
-
                        struct iwl_rx_phy_res last_phy_res;
                        bool last_phy_res_valid;
 
@@ -1257,7 +1203,6 @@ struct iwl_priv {
        struct iwl_rxon_context *beacon_ctx;
        struct sk_buff *beacon_skb;
 
-       struct work_struct start_internal_scan;
        struct work_struct tx_flush;
 
        struct tasklet_struct irq_tasklet;
@@ -1294,12 +1239,9 @@ struct iwl_priv {
        u32 disable_tx_power_cal;
        struct work_struct run_time_calib_work;
        struct timer_list statistics_periodic;
-       struct timer_list ucode_trace;
        struct timer_list watchdog;
        bool hw_ready;
 
-       struct iwl_event_log event_log;
-
        struct led_classdev led;
        unsigned long blink_on, blink_off;
        bool led_registered;
index 080b852..acec991 100644 (file)
@@ -38,8 +38,5 @@ EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
 EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
-EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
 #endif
index 9612aa0..a443725 100644 (file)
@@ -96,47 +96,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi_legacy_ucode
 
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
-       TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
-       TP_ARGS(priv, time, data, ev),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-
-               __field(u32, time)
-               __field(u32, data)
-               __field(u32, ev)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->time = time;
-               __entry->data = data;
-               __entry->ev = ev;
-       ),
-       TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
-                 __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
-
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
-       TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
-       TP_ARGS(priv, wraps, n_entry, p_entry),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-
-               __field(u32, wraps)
-               __field(u32, n_entry)
-               __field(u32, p_entry)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->wraps = wraps;
-               __entry->n_entry = n_entry;
-               __entry->p_entry = p_entry;
-       ),
-       TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
-                 __entry->priv, __entry->wraps, __entry->n_entry,
-                 __entry->p_entry)
-);
-
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM iwlwifi
 
@@ -242,25 +201,6 @@ TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
                  __entry->blink2, __entry->ilink1, __entry->ilink2)
 );
 
-TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
-       TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
-       TP_ARGS(priv, time, data, ev),
-       TP_STRUCT__entry(
-               PRIV_ENTRY
-
-               __field(u32, time)
-               __field(u32, data)
-               __field(u32, ev)
-       ),
-       TP_fast_assign(
-               PRIV_ASSIGN;
-               __entry->time = time;
-               __entry->data = data;
-               __entry->ev = ev;
-       ),
-       TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
-                 __entry->priv, __entry->time, __entry->data, __entry->ev)
-);
 #endif /* __IWLWIFI_DEVICE_TRACE */
 
 #undef TRACE_INCLUDE_PATH
index a6effda..5cf23ea 100644 (file)
@@ -132,7 +132,16 @@ static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
                        ieee80211_stop_queue(priv->hw, ac);
 }
 
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
 #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
 #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
 
 static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
index 654cf23..9b5d0ab 100644 (file)
@@ -227,27 +227,6 @@ void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
 
-void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
-                               struct iwl_rx_packet *pkt)
-{
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-       if (iwl_legacy_is_any_associated(priv)) {
-               if (priv->cfg->ops->lib->check_plcp_health) {
-                       if (!priv->cfg->ops->lib->check_plcp_health(
-                           priv, pkt)) {
-                               /*
-                                * high plcp error detected
-                                * reset Radio
-                                */
-                               iwl_legacy_force_reset(priv,
-                                                       IWL_RF_RESET, false);
-                       }
-               }
-       }
-}
-EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
-
 /*
  * returns non-zero if packet should be dropped
  */
index 353234a..a6b5222 100644 (file)
@@ -101,7 +101,6 @@ static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
                ieee80211_scan_completed(priv->hw, aborted);
        }
 
-       priv->is_internal_short_scan = false;
        priv->scan_vif = NULL;
        priv->scan_request = NULL;
 }
@@ -329,10 +328,8 @@ void iwl_legacy_init_scan_params(struct iwl_priv *priv)
 }
 EXPORT_SYMBOL(iwl_legacy_init_scan_params);
 
-static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
-                                         struct ieee80211_vif *vif,
-                                         bool internal,
-                                         enum ieee80211_band band)
+static int iwl_legacy_scan_initiate(struct iwl_priv *priv,
+                                   struct ieee80211_vif *vif)
 {
        int ret;
 
@@ -359,18 +356,14 @@ static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
                return -EBUSY;
        }
 
-       IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
-                       internal ? "internal short " : "");
+       IWL_DEBUG_SCAN(priv, "Starting scan...\n");
 
        set_bit(STATUS_SCANNING, &priv->status);
-       priv->is_internal_short_scan = internal;
        priv->scan_start = jiffies;
-       priv->scan_band = band;
 
        ret = priv->cfg->ops->utils->request_scan(priv, vif);
        if (ret) {
                clear_bit(STATUS_SCANNING, &priv->status);
-               priv->is_internal_short_scan = false;
                return ret;
        }
 
@@ -394,8 +387,7 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->mutex);
 
-       if (test_bit(STATUS_SCANNING, &priv->status) &&
-           !priv->is_internal_short_scan) {
+       if (test_bit(STATUS_SCANNING, &priv->status)) {
                IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
                ret = -EAGAIN;
                goto out_unlock;
@@ -404,17 +396,9 @@ int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
        /* mac80211 will only ask for one band at a time */
        priv->scan_request = req;
        priv->scan_vif = vif;
+       priv->scan_band = req->channels[0]->band;
 
-       /*
-        * If an internal scan is in progress, just set
-        * up the scan_request as per above.
-        */
-       if (priv->is_internal_short_scan) {
-               IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
-               ret = 0;
-       } else
-               ret = iwl_legacy_scan_initiate(priv, vif, false,
-                                       req->channels[0]->band);
+       ret = iwl_legacy_scan_initiate(priv, vif);
 
        IWL_DEBUG_MAC80211(priv, "leave\n");
 
@@ -425,40 +409,6 @@ out_unlock:
 }
 EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
 
-/*
- * internal short scan, this function should only been called while associated.
- * It will reset and tune the radio to prevent possible RF related problem
- */
-void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
-{
-       queue_work(priv->workqueue, &priv->start_internal_scan);
-}
-
-static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
-{
-       struct iwl_priv *priv =
-               container_of(work, struct iwl_priv, start_internal_scan);
-
-       IWL_DEBUG_SCAN(priv, "Start internal scan\n");
-
-       mutex_lock(&priv->mutex);
-
-       if (priv->is_internal_short_scan == true) {
-               IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
-               goto unlock;
-       }
-
-       if (test_bit(STATUS_SCANNING, &priv->status)) {
-               IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
-               goto unlock;
-       }
-
-       if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
-               IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
- unlock:
-       mutex_unlock(&priv->mutex);
-}
-
 static void iwl_legacy_bg_scan_check(struct work_struct *data)
 {
        struct iwl_priv *priv =
@@ -542,8 +492,7 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
            container_of(work, struct iwl_priv, scan_completed);
        bool aborted;
 
-       IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
-                      priv->is_internal_short_scan ? "internal short " : "");
+       IWL_DEBUG_SCAN(priv, "Completed scan.\n");
 
        cancel_delayed_work(&priv->scan_check);
 
@@ -558,27 +507,6 @@ static void iwl_legacy_bg_scan_completed(struct work_struct *work)
                goto out_settings;
        }
 
-       if (priv->is_internal_short_scan && !aborted) {
-               int err;
-
-               /* Check if mac80211 requested scan during our internal scan */
-               if (priv->scan_request == NULL)
-                       goto out_complete;
-
-               /* If so request a new scan */
-               err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false,
-                                       priv->scan_request->channels[0]->band);
-               if (err) {
-                       IWL_DEBUG_SCAN(priv,
-                               "failed to initiate pending scan: %d\n", err);
-                       aborted = true;
-                       goto out_complete;
-               }
-
-               goto out;
-       }
-
-out_complete:
        iwl_legacy_complete_scan(priv, aborted);
 
 out_settings:
@@ -590,8 +518,7 @@ out_settings:
         * We do not commit power settings while scan is pending,
         * do it now if the settings changed.
         */
-       iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
-                                                               false);
+       iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
        iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
 
        priv->cfg->ops->utils->post_scan(priv);
@@ -604,15 +531,12 @@ void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
 {
        INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
        INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
-       INIT_WORK(&priv->start_internal_scan,
-                               iwl_legacy_bg_start_internal_scan);
        INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
 }
 EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
 
 void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
 {
-       cancel_work_sync(&priv->start_internal_scan);
        cancel_work_sync(&priv->abort_scan);
        cancel_work_sync(&priv->scan_completed);
 
index 0ee6be6..795826a 100644 (file)
@@ -1409,212 +1409,6 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
        }
 }
 
-#define EVENT_START_OFFSET  (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
-                                 u32 num_events, u32 mode,
-                                 int pos, char **buf, size_t bufsz)
-{
-       u32 i;
-       u32 base;       /* SRAM byte address of event log header */
-       u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
-       u32 ptr;        /* SRAM byte address of log data */
-       u32 ev, time, data; /* event log data */
-       unsigned long reg_flags;
-
-       if (num_events == 0)
-               return pos;
-
-       base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
-       if (mode == 0)
-               event_size = 2 * sizeof(u32);
-       else
-               event_size = 3 * sizeof(u32);
-
-       ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-       /* Make sure device is powered up for SRAM reads */
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-
-       /* Set starting address; reads will auto-increment */
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-       rmb();
-
-       /* "time" is actually "data" for mode 0 (no timestamp).
-        * place event id # at far right for easier visual parsing. */
-       for (i = 0; i < num_events; i++) {
-               ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (mode == 0) {
-                       /* data, ev */
-                       if (bufsz) {
-                               pos += scnprintf(*buf + pos, bufsz - pos,
-                                               "0x%08x:%04u\n",
-                                               time, ev);
-                       } else {
-                               IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
-                               trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
-                                                             time, ev);
-                       }
-               } else {
-                       data = _iwl_legacy_read_direct32(priv,
-                                                       HBUS_TARG_MEM_RDAT);
-                       if (bufsz) {
-                               pos += scnprintf(*buf + pos, bufsz - pos,
-                                               "%010u:0x%08x:%04u\n",
-                                                time, data, ev);
-                       } else {
-                               IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
-                                       time, data, ev);
-                               trace_iwlwifi_legacy_dev_ucode_event(priv, time,
-                                                             data, ev);
-                       }
-               }
-       }
-
-       /* Allow device to power down */
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-       return pos;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
-                                     u32 num_wraps, u32 next_entry,
-                                     u32 size, u32 mode,
-                                     int pos, char **buf, size_t bufsz)
-{
-       /*
-        * display the newest DEFAULT_LOG_ENTRIES entries
-        * i.e the entries just before the next ont that uCode would fill.
-        */
-       if (num_wraps) {
-               if (next_entry < size) {
-                       pos = iwl3945_print_event_log(priv,
-                                            capacity - (size - next_entry),
-                                            size - next_entry, mode,
-                                            pos, buf, bufsz);
-                       pos = iwl3945_print_event_log(priv, 0,
-                                                     next_entry, mode,
-                                                     pos, buf, bufsz);
-               } else
-                       pos = iwl3945_print_event_log(priv, next_entry - size,
-                                                     size, mode,
-                                                     pos, buf, bufsz);
-       } else {
-               if (next_entry < size)
-                       pos = iwl3945_print_event_log(priv, 0,
-                                                     next_entry, mode,
-                                                     pos, buf, bufsz);
-               else
-                       pos = iwl3945_print_event_log(priv, next_entry - size,
-                                                     size, mode,
-                                                     pos, buf, bufsz);
-       }
-       return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-                           char **buf, bool display)
-{
-       u32 base;       /* SRAM byte address of event log header */
-       u32 capacity;   /* event log capacity in # entries */
-       u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-       u32 num_wraps;  /* # times uCode wrapped to top of log */
-       u32 next_entry; /* index of next entry to be written by uCode */
-       u32 size;       /* # entries that we'll print */
-       int pos = 0;
-       size_t bufsz = 0;
-
-       base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-       if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-               IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-               return  -EINVAL;
-       }
-
-       /* event log header */
-       capacity = iwl_legacy_read_targ_mem(priv, base);
-       mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
-       num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
-       next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-       if (capacity > priv->cfg->base_params->max_event_log_size) {
-               IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-                       capacity, priv->cfg->base_params->max_event_log_size);
-               capacity = priv->cfg->base_params->max_event_log_size;
-       }
-
-       if (next_entry > priv->cfg->base_params->max_event_log_size) {
-               IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-                       next_entry, priv->cfg->base_params->max_event_log_size);
-               next_entry = priv->cfg->base_params->max_event_log_size;
-       }
-
-       size = num_wraps ? capacity : next_entry;
-
-       /* bail out if nothing in log */
-       if (size == 0) {
-               IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-               return pos;
-       }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
-               size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-                       ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-       size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-               ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
-       IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
-                 size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (display) {
-               if (full_log)
-                       bufsz = capacity * 48;
-               else
-                       bufsz = size * 48;
-               *buf = kmalloc(bufsz, GFP_KERNEL);
-               if (!*buf)
-                       return -ENOMEM;
-       }
-       if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
-               /* if uCode has wrapped back to top of log,
-                * start at the oldest entry,
-                * i.e the next one that uCode would fill.
-                */
-               if (num_wraps)
-                       pos = iwl3945_print_event_log(priv, next_entry,
-                                               capacity - next_entry, mode,
-                                               pos, buf, bufsz);
-
-               /* (then/else) start at top of log */
-               pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
-                                             pos, buf, bufsz);
-       } else
-               pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-                                                   next_entry, size, mode,
-                                                   pos, buf, bufsz);
-#else
-       pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-                                           next_entry, size, mode,
-                                           pos, buf, bufsz);
-#endif
-       return pos;
-}
-
 static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 {
        u32 inta, handled = 0;
@@ -1762,49 +1556,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
 #endif
 }
 
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
-                                              struct ieee80211_vif *vif,
-                                              enum ieee80211_band band,
-                                              struct iwl3945_scan_channel *scan_ch)
-{
-       const struct ieee80211_supported_band *sband;
-       u16 passive_dwell = 0;
-       u16 active_dwell = 0;
-       int added = 0;
-       u8 channel = 0;
-
-       sband = iwl_get_hw_mode(priv, band);
-       if (!sband) {
-               IWL_ERR(priv, "invalid band\n");
-               return added;
-       }
-
-       active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
-       passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
-
-       if (passive_dwell <= active_dwell)
-               passive_dwell = active_dwell + 1;
-
-
-       channel = iwl_legacy_get_single_channel_number(priv, band);
-
-       if (channel) {
-               scan_ch->channel = channel;
-               scan_ch->type = 0;      /* passive */
-               scan_ch->active_dwell = cpu_to_le16(active_dwell);
-               scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-               /* Set txpower levels to defaults */
-               scan_ch->tpc.dsp_atten = 110;
-               if (band == IEEE80211_BAND_5GHZ)
-                       scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else
-                       scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-               added++;
-       } else
-               IWL_ERR(priv, "no valid channel found\n");
-       return added;
-}
-
 static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
                                         enum ieee80211_band band,
                                     u8 is_active, u8 n_probes,
@@ -2816,6 +2567,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        enum ieee80211_band band;
        bool is_active = false;
        int ret;
+       u16 len;
 
        lockdep_assert_held(&priv->mutex);
 
@@ -2834,17 +2586,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
        if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
-               u16 interval = 0;
+               u16 interval;
                u32 extra;
                u32 suspend_time = 100;
                u32 scan_suspend_time = 100;
 
                IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
 
-               if (priv->is_internal_short_scan)
-                       interval = 0;
-               else
-                       interval = vif->bss_conf.beacon_int;
+               interval = vif->bss_conf.beacon_int;
 
                scan->suspend_time = 0;
                scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -2866,9 +2615,7 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
                               scan_suspend_time, interval);
        }
 
-       if (priv->is_internal_short_scan) {
-               IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-       } else if (priv->scan_request->n_ssids) {
+       if (priv->scan_request->n_ssids) {
                int i, p = 0;
                IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
                for (i = 0; i < priv->scan_request->n_ssids; i++) {
@@ -2919,36 +2666,17 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
        scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
                                        IWL_GOOD_CRC_TH_DISABLED;
 
-       if (!priv->is_internal_short_scan) {
-               scan->tx_cmd.len = cpu_to_le16(
-                       iwl_legacy_fill_probe_req(priv,
-                               (struct ieee80211_mgmt *)scan->data,
-                               vif->addr,
-                               priv->scan_request->ie,
-                               priv->scan_request->ie_len,
-                               IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-       } else {
-               /* use bcast addr, will not be transmitted but must be valid */
-               scan->tx_cmd.len = cpu_to_le16(
-                       iwl_legacy_fill_probe_req(priv,
-                               (struct ieee80211_mgmt *)scan->data,
-                               iwlegacy_bcast_addr, NULL, 0,
-                               IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-       }
+       len = iwl_legacy_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+                                       vif->addr, priv->scan_request->ie,
+                                       priv->scan_request->ie_len,
+                                       IWL_MAX_SCAN_SIZE - sizeof(*scan));
+       scan->tx_cmd.len = cpu_to_le16(len);
+
        /* select Rx antennas */
        scan->flags |= iwl3945_get_antenna_flags(priv);
 
-       if (priv->is_internal_short_scan) {
-               scan->channel_count =
-                       iwl3945_get_single_channel_for_scan(priv, vif, band,
-                               (void *)&scan->data[le16_to_cpu(
-                               scan->tx_cmd.len)]);
-       } else {
-               scan->channel_count =
-                       iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
-       }
-
+       scan->channel_count = iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+                                                           (void *)&scan->data[len], vif);
        if (scan->channel_count == 0) {
                IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
                return -EIO;
@@ -3824,10 +3552,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
 
        /* initialize force reset */
-       priv->force_reset[IWL_RF_RESET].reset_duration =
-               IWL_DELAY_NEXT_FORCE_RF_RESET;
-       priv->force_reset[IWL_FW_RESET].reset_duration =
-               IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+       priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
        if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
                IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
index 7157ba5..46242d2 100644 (file)
@@ -488,134 +488,6 @@ static void iwl4965_bg_statistics_periodic(unsigned long data)
        iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
 }
 
-
-static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
-                                       u32 start_idx, u32 num_events,
-                                       u32 mode)
-{
-       u32 i;
-       u32 ptr;        /* SRAM byte address of log data */
-       u32 ev, time, data; /* event log data */
-       unsigned long reg_flags;
-
-       if (mode == 0)
-               ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
-       else
-               ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
-
-       /* Make sure device is powered up for SRAM reads */
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       if (iwl_grab_nic_access(priv)) {
-               spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-               return;
-       }
-
-       /* Set starting address; reads will auto-increment */
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-       rmb();
-
-       /*
-        * "time" is actually "data" for mode 0 (no timestamp).
-        * place event id # at far right for easier visual parsing.
-        */
-       for (i = 0; i < num_events; i++) {
-               ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (mode == 0) {
-                       trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
-                                                       0, time, ev);
-               } else {
-                       data = _iwl_legacy_read_direct32(priv,
-                                               HBUS_TARG_MEM_RDAT);
-                       trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
-                                               time, data, ev);
-               }
-       }
-       /* Allow device to power down */
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-}
-
-static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
-{
-       u32 capacity;   /* event log capacity in # entries */
-       u32 base;       /* SRAM byte address of event log header */
-       u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-       u32 num_wraps;  /* # times uCode wrapped to top of log */
-       u32 next_entry; /* index of next entry to be written by uCode */
-
-       if (priv->ucode_type == UCODE_INIT)
-               base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
-       else
-               base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-       if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               capacity = iwl_legacy_read_targ_mem(priv, base);
-               num_wraps = iwl_legacy_read_targ_mem(priv,
-                                               base + (2 * sizeof(u32)));
-               mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
-               next_entry = iwl_legacy_read_targ_mem(priv,
-                                               base + (3 * sizeof(u32)));
-       } else
-               return;
-
-       if (num_wraps == priv->event_log.num_wraps) {
-               iwl4965_print_cont_event_trace(priv,
-                                      base, priv->event_log.next_entry,
-                                      next_entry - priv->event_log.next_entry,
-                                      mode);
-               priv->event_log.non_wraps_count++;
-       } else {
-               if ((num_wraps - priv->event_log.num_wraps) > 1)
-                       priv->event_log.wraps_more_count++;
-               else
-                       priv->event_log.wraps_once_count++;
-               trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
-                               num_wraps - priv->event_log.num_wraps,
-                               next_entry, priv->event_log.next_entry);
-               if (next_entry < priv->event_log.next_entry) {
-                       iwl4965_print_cont_event_trace(priv, base,
-                              priv->event_log.next_entry,
-                              capacity - priv->event_log.next_entry,
-                              mode);
-
-                       iwl4965_print_cont_event_trace(priv, base, 0,
-                               next_entry, mode);
-               } else {
-                       iwl4965_print_cont_event_trace(priv, base,
-                              next_entry, capacity - next_entry,
-                              mode);
-
-                       iwl4965_print_cont_event_trace(priv, base, 0,
-                               next_entry, mode);
-               }
-       }
-       priv->event_log.num_wraps = num_wraps;
-       priv->event_log.next_entry = next_entry;
-}
-
-/**
- * iwl4965_bg_ucode_trace - Timer callback to log ucode event
- *
- * The timer is continually set to execute every
- * UCODE_TRACE_PERIOD milliseconds after the last timer expired
- * this function is to perform continuous uCode event logging operation
- * if enabled
- */
-static void iwl4965_bg_ucode_trace(unsigned long data)
-{
-       struct iwl_priv *priv = (struct iwl_priv *)data;
-
-       if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-               return;
-
-       if (priv->event_log.ucode_trace) {
-               iwl4965_continuous_event_trace(priv);
-               /* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
-               mod_timer(&priv->ucode_trace,
-                        jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
-       }
-}
-
 static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
                                struct iwl_rx_mem_buffer *rxb)
 {
@@ -1711,209 +1583,6 @@ void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
                pc, blink1, blink2, ilink1, ilink2, hcmd);
 }
 
-#define EVENT_START_OFFSET  (4 * sizeof(u32))
-
-/**
- * iwl4965_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
-                              u32 num_events, u32 mode,
-                              int pos, char **buf, size_t bufsz)
-{
-       u32 i;
-       u32 base;       /* SRAM byte address of event log header */
-       u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
-       u32 ptr;        /* SRAM byte address of log data */
-       u32 ev, time, data; /* event log data */
-       unsigned long reg_flags;
-
-       if (num_events == 0)
-               return pos;
-
-       if (priv->ucode_type == UCODE_INIT) {
-               base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
-       } else {
-               base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-       }
-
-       if (mode == 0)
-               event_size = 2 * sizeof(u32);
-       else
-               event_size = 3 * sizeof(u32);
-
-       ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-       /* Make sure device is powered up for SRAM reads */
-       spin_lock_irqsave(&priv->reg_lock, reg_flags);
-       iwl_grab_nic_access(priv);
-
-       /* Set starting address; reads will auto-increment */
-       _iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-       rmb();
-
-       /* "time" is actually "data" for mode 0 (no timestamp).
-       * place event id # at far right for easier visual parsing. */
-       for (i = 0; i < num_events; i++) {
-               ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-               if (mode == 0) {
-                       /* data, ev */
-                       if (bufsz) {
-                               pos += scnprintf(*buf + pos, bufsz - pos,
-                                               "EVT_LOG:0x%08x:%04u\n",
-                                               time, ev);
-                       } else {
-                               trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
-                                       time, ev);
-                               IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
-                                       time, ev);
-                       }
-               } else {
-                       data = _iwl_legacy_read_direct32(priv,
-                                               HBUS_TARG_MEM_RDAT);
-                       if (bufsz) {
-                               pos += scnprintf(*buf + pos, bufsz - pos,
-                                               "EVT_LOGT:%010u:0x%08x:%04u\n",
-                                                time, data, ev);
-                       } else {
-                               IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
-                                       time, data, ev);
-                               trace_iwlwifi_legacy_dev_ucode_event(priv, time,
-                                       data, ev);
-                       }
-               }
-       }
-
-       /* Allow device to power down */
-       iwl_release_nic_access(priv);
-       spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-       return pos;
-}
-
-/**
- * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
-                                   u32 num_wraps, u32 next_entry,
-                                   u32 size, u32 mode,
-                                   int pos, char **buf, size_t bufsz)
-{
-       /*
-        * display the newest DEFAULT_LOG_ENTRIES entries
-        * i.e the entries just before the next ont that uCode would fill.
-        */
-       if (num_wraps) {
-               if (next_entry < size) {
-                       pos = iwl4965_print_event_log(priv,
-                                               capacity - (size - next_entry),
-                                               size - next_entry, mode,
-                                               pos, buf, bufsz);
-                       pos = iwl4965_print_event_log(priv, 0,
-                                                 next_entry, mode,
-                                                 pos, buf, bufsz);
-               } else
-                       pos = iwl4965_print_event_log(priv, next_entry - size,
-                                                 size, mode, pos, buf, bufsz);
-       } else {
-               if (next_entry < size) {
-                       pos = iwl4965_print_event_log(priv, 0, next_entry,
-                                                 mode, pos, buf, bufsz);
-               } else {
-                       pos = iwl4965_print_event_log(priv, next_entry - size,
-                                                 size, mode, pos, buf, bufsz);
-               }
-       }
-       return pos;
-}
-
-#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-                           char **buf, bool display)
-{
-       u32 base;       /* SRAM byte address of event log header */
-       u32 capacity;   /* event log capacity in # entries */
-       u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-       u32 num_wraps;  /* # times uCode wrapped to top of log */
-       u32 next_entry; /* index of next entry to be written by uCode */
-       u32 size;       /* # entries that we'll print */
-       int pos = 0;
-       size_t bufsz = 0;
-
-       if (priv->ucode_type == UCODE_INIT) {
-               base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
-       } else {
-               base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-       }
-
-       if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
-               IWL_ERR(priv,
-                       "Invalid event log pointer 0x%08X for %s uCode\n",
-                       base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
-               return -EINVAL;
-       }
-
-       /* event log header */
-       capacity = iwl_legacy_read_targ_mem(priv, base);
-       mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
-       num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
-       next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-       size = num_wraps ? capacity : next_entry;
-
-       /* bail out if nothing in log */
-       if (size == 0) {
-               IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-               return pos;
-       }
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
-               size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
-                       ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-       size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
-               ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-       IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
-               size);
-
-#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
-       if (display) {
-               if (full_log)
-                       bufsz = capacity * 48;
-               else
-                       bufsz = size * 48;
-               *buf = kmalloc(bufsz, GFP_KERNEL);
-               if (!*buf)
-                       return -ENOMEM;
-       }
-       if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
-               /*
-                * if uCode has wrapped back to top of log,
-                * start at the oldest entry,
-                * i.e the next one that uCode would fill.
-                */
-               if (num_wraps)
-                       pos = iwl4965_print_event_log(priv, next_entry,
-                                               capacity - next_entry, mode,
-                                               pos, buf, bufsz);
-               /* (then/else) start at top of log */
-               pos = iwl4965_print_event_log(priv, 0,
-                                         next_entry, mode, pos, buf, bufsz);
-       } else
-               pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
-                                               next_entry, size, mode,
-                                               pos, buf, bufsz);
-#else
-       pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
-                                       next_entry, size, mode,
-                                       pos, buf, bufsz);
-#endif
-       return pos;
-}
-
 static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
 {
        struct iwl_ct_kill_config cmd;
@@ -2773,20 +2442,10 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
        case IEEE80211_AMPDU_TX_START:
                IWL_DEBUG_HT(priv, "start Tx\n");
                ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
-               if (ret == 0) {
-                       priv->_4965.agg_tids_count++;
-                       IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
-                                    priv->_4965.agg_tids_count);
-               }
                break;
        case IEEE80211_AMPDU_TX_STOP:
                IWL_DEBUG_HT(priv, "stop Tx\n");
                ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
-               if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
-                       priv->_4965.agg_tids_count--;
-                       IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
-                                    priv->_4965.agg_tids_count);
-               }
                if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                        ret = 0;
                break;
@@ -2851,7 +2510,6 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
 
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
        u16 ch;
-       unsigned long flags = 0;
 
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
@@ -2868,64 +2526,64 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
        if (!iwl_legacy_is_associated_ctx(ctx))
                goto out;
 
-       if (priv->cfg->ops->lib->set_channel_switch) {
+       if (!priv->cfg->ops->lib->set_channel_switch)
+               goto out;
 
-               ch = channel->hw_value;
-               if (le16_to_cpu(ctx->active.channel) != ch) {
-                       ch_info = iwl_legacy_get_channel_info(priv,
-                                                      channel->band,
-                                                      ch);
-                       if (!iwl_legacy_is_channel_valid(ch_info)) {
-                               IWL_DEBUG_MAC80211(priv, "invalid channel\n");
-                               goto out;
-                       }
-                       spin_lock_irqsave(&priv->lock, flags);
-
-                       priv->current_ht_config.smps = conf->smps_mode;
-
-                       /* Configure HT40 channels */
-                       ctx->ht.enabled = conf_is_ht(conf);
-                       if (ctx->ht.enabled) {
-                               if (conf_is_ht40_minus(conf)) {
-                                       ctx->ht.extension_chan_offset =
-                                       IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-                                       ctx->ht.is_40mhz = true;
-                               } else if (conf_is_ht40_plus(conf)) {
-                                       ctx->ht.extension_chan_offset =
-                                       IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-                                       ctx->ht.is_40mhz = true;
-                               } else {
-                                       ctx->ht.extension_chan_offset =
-                                               IEEE80211_HT_PARAM_CHA_SEC_NONE;
-                                       ctx->ht.is_40mhz = false;
-                               }
-                       } else
-                               ctx->ht.is_40mhz = false;
-
-                       if ((le16_to_cpu(ctx->staging.channel) != ch))
-                               ctx->staging.flags = 0;
-
-                       iwl_legacy_set_rxon_channel(priv, channel, ctx);
-                       iwl_legacy_set_rxon_ht(priv, ht_conf);
-                       iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
-                                              ctx->vif);
-                       spin_unlock_irqrestore(&priv->lock, flags);
-
-                       iwl_legacy_set_rate(priv);
-                       /*
-                        * at this point, staging_rxon has the
-                        * configuration for channel switch
-                        */
-                       set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
-                       priv->switch_channel = cpu_to_le16(ch);
-                       if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
-                               clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
-                                         &priv->status);
-                               priv->switch_channel = 0;
-                               ieee80211_chswitch_done(ctx->vif, false);
-                       }
+       ch = channel->hw_value;
+       if (le16_to_cpu(ctx->active.channel) == ch)
+               goto out;
+
+       ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+       if (!iwl_legacy_is_channel_valid(ch_info)) {
+               IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+               goto out;
+       }
+
+       spin_lock_irq(&priv->lock);
+
+       priv->current_ht_config.smps = conf->smps_mode;
+
+       /* Configure HT40 channels */
+       ctx->ht.enabled = conf_is_ht(conf);
+       if (ctx->ht.enabled) {
+               if (conf_is_ht40_minus(conf)) {
+                       ctx->ht.extension_chan_offset =
+                               IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+                       ctx->ht.is_40mhz = true;
+               } else if (conf_is_ht40_plus(conf)) {
+                       ctx->ht.extension_chan_offset =
+                               IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+                       ctx->ht.is_40mhz = true;
+               } else {
+                       ctx->ht.extension_chan_offset =
+                               IEEE80211_HT_PARAM_CHA_SEC_NONE;
+                       ctx->ht.is_40mhz = false;
                }
+       } else
+               ctx->ht.is_40mhz = false;
+
+       if ((le16_to_cpu(ctx->staging.channel) != ch))
+               ctx->staging.flags = 0;
+
+       iwl_legacy_set_rxon_channel(priv, channel, ctx);
+       iwl_legacy_set_rxon_ht(priv, ht_conf);
+       iwl_legacy_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
+
+       spin_unlock_irq(&priv->lock);
+
+       iwl_legacy_set_rate(priv);
+       /*
+        * at this point, staging_rxon has the
+        * configuration for channel switch
+        */
+       set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+       priv->switch_channel = cpu_to_le16(ch);
+       if (priv->cfg->ops->lib->set_channel_switch(priv, ch_switch)) {
+               clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
+               priv->switch_channel = 0;
+               ieee80211_chswitch_done(ctx->vif, false);
        }
+
 out:
        mutex_unlock(&priv->mutex);
        IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -3034,10 +2692,6 @@ static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
        priv->statistics_periodic.data = (unsigned long)priv;
        priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
 
-       init_timer(&priv->ucode_trace);
-       priv->ucode_trace.data = (unsigned long)priv;
-       priv->ucode_trace.function = iwl4965_bg_ucode_trace;
-
        init_timer(&priv->watchdog);
        priv->watchdog.data = (unsigned long)priv;
        priv->watchdog.function = iwl_legacy_bg_watchdog;
@@ -3056,7 +2710,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
        iwl_legacy_cancel_scan_deferred_work(priv);
 
        del_timer_sync(&priv->statistics_periodic);
-       del_timer_sync(&priv->ucode_trace);
 }
 
 static void iwl4965_init_hw_rates(struct iwl_priv *priv,
@@ -3132,13 +2785,9 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
        priv->iw_mode = NL80211_IFTYPE_STATION;
        priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
        priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-       priv->_4965.agg_tids_count = 0;
 
        /* initialize force reset */
-       priv->force_reset[IWL_RF_RESET].reset_duration =
-               IWL_DELAY_NEXT_FORCE_RF_RESET;
-       priv->force_reset[IWL_FW_RESET].reset_duration =
-               IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+       priv->force_reset.reset_duration = IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
        /* Choose which receivers/antennas to use */
        if (priv->cfg->ops->hcmd->set_rxon_chain)
index 8226604..9a56ce5 100644 (file)
@@ -13,6 +13,7 @@ iwlagn-objs             += iwl-5000.o
 iwlagn-objs             += iwl-6000.o
 iwlagn-objs             += iwl-1000.o
 iwlagn-objs             += iwl-2000.o
+iwlagn-objs             += iwl-pci.o
 
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
index 7aa240e..2daca80 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -194,8 +192,6 @@ static struct iwl_lib_ops iwl1000_lib = {
        .temp_ops = {
                .temperature = iwlagn_temperature,
         },
-       .txfifo_flush = iwlagn_txfifo_flush,
-       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 };
 
 static const struct iwl_ops iwl1000_ops = {
index 5484ab7..1c13300 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -76,21 +74,7 @@ static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
 /* NIC configuration for 2000 series */
 static void iwl2000_nic_config(struct iwl_priv *priv)
 {
-       u16 radio_cfg;
-
-       radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-       /* write radio config values to register */
-       if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
-       iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                       EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-                       EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-                       EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-       /* set CSR_HW_CONFIG_REG for uCode use */
-       iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                   CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-                   CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+       iwl_rf_config(priv);
 
        if (priv->cfg->iq_invert)
                iwl_set_bit(priv, CSR_GP_DRIVER_REG,
@@ -204,8 +188,6 @@ static struct iwl_lib_ops iwl2000_lib = {
        .temp_ops = {
                .temperature = iwlagn_temperature,
        },
-       .txfifo_flush = iwlagn_txfifo_flush,
-       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 };
 
 static const struct iwl_ops iwl2000_ops = {
index 05ad476..f9630a3 100644 (file)
@@ -75,7 +75,7 @@ static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
 {
        u16 temperature, voltage;
        __le16 *temp_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
+               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
 
        temperature = le16_to_cpu(temp_calib[0]);
        voltage = le16_to_cpu(temp_calib[1]);
index 4353a65..937a8f1 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
 static void iwl5000_nic_config(struct iwl_priv *priv)
 {
        unsigned long flags;
-       u16 radio_cfg;
 
-       spin_lock_irqsave(&priv->lock, flags);
-
-       radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+       iwl_rf_config(priv);
 
-       /* write radio config values to register */
-       if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX)
-               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-                           EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-                           EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-       /* set CSR_HW_CONFIG_REG for uCode use */
-       iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                   CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-                   CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+       spin_lock_irqsave(&priv->lock, flags);
 
        /* W/A : NIC is stuck in a reset state after Early PCIe power off
         * (PCIe power is lost before PERST# is asserted),
@@ -361,8 +346,6 @@ static struct iwl_lib_ops iwl5000_lib = {
        .temp_ops = {
                .temperature = iwlagn_temperature,
         },
-       .txfifo_flush = iwlagn_txfifo_flush,
-       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 };
 
 static struct iwl_lib_ops iwl5150_lib = {
@@ -391,8 +374,6 @@ static struct iwl_lib_ops iwl5150_lib = {
        .temp_ops = {
                .temperature = iwl5150_temperature,
         },
-       .txfifo_flush = iwlagn_txfifo_flush,
-       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 };
 
 static const struct iwl_ops iwl5000_ops = {
index 6e5ce44..3fcc092 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -97,21 +95,7 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
 /* NIC configuration for 6000 series */
 static void iwl6000_nic_config(struct iwl_priv *priv)
 {
-       u16 radio_cfg;
-
-       radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-       /* write radio config values to register */
-       if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
-               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                           EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-                           EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-                           EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-       /* set CSR_HW_CONFIG_REG for uCode use */
-       iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-                   CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-                   CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+       iwl_rf_config(priv);
 
        /* no locking required for register write */
        if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
@@ -301,8 +285,6 @@ static struct iwl_lib_ops iwl6000_lib = {
        .temp_ops = {
                .temperature = iwlagn_temperature,
         },
-       .txfifo_flush = iwlagn_txfifo_flush,
-       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 };
 
 static struct iwl_lib_ops iwl6030_lib = {
@@ -333,8 +315,6 @@ static struct iwl_lib_ops iwl6030_lib = {
        .temp_ops = {
                .temperature = iwlagn_temperature,
         },
-       .txfifo_flush = iwlagn_txfifo_flush,
-       .dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 };
 
 static struct iwl_nic_ops iwl6050_nic_ops = {
index 2ef9448..7745816 100644 (file)
@@ -108,18 +108,16 @@ err:
 
 int iwl_eeprom_check_sku(struct iwl_priv *priv)
 {
-       u16 eeprom_sku;
        u16 radio_cfg;
 
-       eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
-
        if (!priv->cfg->sku) {
                /* not using sku overwrite */
-               priv->cfg->sku =
-                       ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >>
-                       EEPROM_SKU_CAP_BAND_POS);
-               if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE)
-                       priv->cfg->sku |= IWL_SKU_N;
+               priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
+               if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
+                   !priv->cfg->ht_params) {
+                       IWL_ERR(priv, "Invalid 11n configuration\n");
+                       return -EINVAL;
+               }
        }
        if (!priv->cfg->sku) {
                IWL_ERR(priv, "Invalid device sku\n");
index 23eee0c..ba7ed91 100644 (file)
@@ -111,10 +111,8 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
 
                memset(&cmd, 0, sizeof(cmd));
 
-               cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd;
-               cmd.hdr.first_group = 0;
-               cmd.hdr.groups_num = 1;
-               cmd.hdr.data_valid = 1;
+               iwl_set_calib_hdr(&cmd.hdr,
+                       priv->_agn.phy_calib_chain_noise_gain_cmd);
                cmd.delta_gain_1 = data->delta_gain_code[1];
                cmd.delta_gain_2 = data->delta_gain_code[2];
                iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
@@ -144,10 +142,8 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
                data->beacon_count = 0;
 
                memset(&cmd, 0, sizeof(cmd));
-               cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd;
-               cmd.hdr.first_group = 0;
-               cmd.hdr.groups_num = 1;
-               cmd.hdr.data_valid = 1;
+               iwl_set_calib_hdr(&cmd.hdr,
+                       priv->_agn.phy_calib_chain_noise_reset_cmd);
                ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
                                        sizeof(cmd), &cmd);
                if (ret)
index 7bd19f4..0e5b842 100644 (file)
 /* RSSI to dBm */
 #define IWLAGN_RSSI_OFFSET     44
 
-/* PCI registers */
-#define PCI_CFG_RETRY_TIMEOUT  0x041
-
-/* PCI register values */
-#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
-#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
-
 #define IWLAGN_DEFAULT_TX_RETRY  15
 
 /* Limit range of txpower output target to be between these values */
index 0d5fda4..f1b40ec 100644 (file)
@@ -44,7 +44,7 @@
 void iwl_free_isr_ict(struct iwl_priv *priv)
 {
        if (priv->_agn.ict_tbl_vir) {
-               dma_free_coherent(&priv->pci_dev->dev,
+               dma_free_coherent(priv->bus.dev,
                                  (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
                                  priv->_agn.ict_tbl_vir,
                                  priv->_agn.ict_tbl_dma);
@@ -61,7 +61,7 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
 
        /* allocate shrared data table */
        priv->_agn.ict_tbl_vir =
-               dma_alloc_coherent(&priv->pci_dev->dev,
+               dma_alloc_coherent(priv->bus.dev,
                                   (sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
                                   &priv->_agn.ict_tbl_dma, GFP_KERNEL);
        if (!priv->_agn.ict_tbl_vir)
index 677f73c..efdab65 100644 (file)
@@ -438,7 +438,7 @@ static void iwlagn_rx_reply_tx(struct iwl_priv *priv,
                if (tx_resp->bt_kill_count && tx_resp->frame_count == 1 &&
                    priv->cfg->bt_params &&
                    priv->cfg->bt_params->advanced_bt_coexist) {
-                       IWL_WARN(priv, "receive reply tx with bt_kill\n");
+                       IWL_DEBUG_COEX(priv, "receive reply tx with bt_kill\n");
                }
                iwlagn_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
 
@@ -622,6 +622,9 @@ struct iwl_mod_params iwlagn_mod_params = {
        .amsdu_size_8K = 1,
        .restart_fw = 1,
        .plcp_check = true,
+       .bt_coex_active = true,
+       .no_sleep_autoadjust = true,
+       .power_level = IWL_POWER_INDEX_1,
        /* the rest are 0 by default */
 };
 
@@ -637,9 +640,9 @@ void iwlagn_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
                /* In the reset function, these buffers may have been allocated
                 * to an SKB, so we need to unmap and free potential storage */
                if (rxq->pool[i].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+                       dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
                        __iwl_free_pages(priv, rxq->pool[i].page);
                        rxq->pool[i].page = NULL;
                }
@@ -911,9 +914,9 @@ void iwlagn_rx_allocate(struct iwl_priv *priv, gfp_t priority)
                BUG_ON(rxb->page);
                rxb->page = page;
                /* Get physical address of the RB */
-               rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
+               rxb->page_dma = dma_map_page(priv->bus.dev, page, 0,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
                /* dma address must be no more than 36 bits */
                BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
                /* and also 256 byte aligned! */
@@ -956,17 +959,18 @@ void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
        int i;
        for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
                if (rxq->pool[i].page != NULL) {
-                       pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+                       dma_unmap_page(priv->bus.dev, rxq->pool[i].page_dma,
                                PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
                        __iwl_free_pages(priv, rxq->pool[i].page);
                        rxq->pool[i].page = NULL;
                }
        }
 
-       dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-                         rxq->bd_dma);
-       dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+       dma_free_coherent(priv->bus.dev, 4 * RX_QUEUE_SIZE,
+                         rxq->bd, rxq->bd_dma);
+       dma_free_coherent(priv->bus.dev,
+                         sizeof(struct iwl_rb_status),
                          rxq->rb_stts, rxq->rb_stts_dma);
        rxq->bd = NULL;
        rxq->rb_stts  = NULL;
@@ -1528,9 +1532,18 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
        might_sleep();
 
        memset(&flush_cmd, 0, sizeof(flush_cmd));
-       flush_cmd.fifo_control = IWL_TX_FIFO_VO_MSK | IWL_TX_FIFO_VI_MSK |
-                                IWL_TX_FIFO_BE_MSK | IWL_TX_FIFO_BK_MSK;
-       if (priv->cfg->sku & IWL_SKU_N)
+       if (flush_control & BIT(IWL_RXON_CTX_BSS))
+               flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+                                IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+                                IWL_SCD_MGMT_MSK;
+       if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
+           (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
+               flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
+                               IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
+                               IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
+                               IWL_PAN_SCD_MULTICAST_MSK;
+
+       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
                flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
 
        IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
@@ -1544,7 +1557,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
 {
        mutex_lock(&priv->mutex);
        ieee80211_stop_queues(priv->hw);
-       if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+       if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
                IWL_ERR(priv, "flush request fail\n");
                goto done;
        }
@@ -1699,7 +1712,8 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
         * (might be in monitor mode), or the interface is in
         * IBSS mode (no proper uCode support for coex then).
         */
-       if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
+       if (!iwlagn_mod_params.bt_coex_active ||
+           priv->iw_mode == NL80211_IFTYPE_ADHOC) {
                basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
        } else {
                basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
@@ -1710,7 +1724,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 
                if (priv->bt_ch_announce)
                        basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
-               IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags);
+               IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);
        }
        priv->bt_enable_flag = basic.flags;
        if (priv->bt_full_concurrent)
@@ -1720,7 +1734,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
                memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
                        sizeof(iwlagn_def_3w_lookup));
 
-       IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
+       IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",
                       basic.flags ? "active" : "disabled",
                       priv->bt_full_concurrent ?
                       "full concurrency" : "3-wire");
@@ -1758,7 +1772,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
         * coex profile notifications. Ignore that since only bad consequence
         * can be not matching debug print with actual state.
         */
-       IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
+       IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",
                       priv->bt_traffic_load);
 
        switch (priv->bt_traffic_load) {
@@ -1810,7 +1824,7 @@ out:
 static void iwlagn_print_uartmsg(struct iwl_priv *priv,
                                struct iwl_bt_uart_msg *uart_msg)
 {
-       IWL_DEBUG_NOTIF(priv, "Message Type = 0x%X, SSN = 0x%X, "
+       IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "
                        "Update Req = 0x%X",
                (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
                        BT_UART_MSG_FRAME1MSGTYPE_POS,
@@ -1819,7 +1833,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
                (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
                        BT_UART_MSG_FRAME1UPDATEREQ_POS);
 
-       IWL_DEBUG_NOTIF(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
+       IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
                        "Chl_SeqN = 0x%X, In band = 0x%X",
                (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
                        BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
@@ -1830,7 +1844,7 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
                (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
                        BT_UART_MSG_FRAME2INBAND_POS);
 
-       IWL_DEBUG_NOTIF(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
+       IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
                        "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
                (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
                        BT_UART_MSG_FRAME3SCOESCO_POS,
@@ -1845,11 +1859,11 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
                (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
                        BT_UART_MSG_FRAME3OBEX_POS);
 
-       IWL_DEBUG_NOTIF(priv, "Idle duration = 0x%X",
+       IWL_DEBUG_COEX(priv, "Idle duration = 0x%X",
                (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
                        BT_UART_MSG_FRAME4IDLEDURATION_POS);
 
-       IWL_DEBUG_NOTIF(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
+       IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
                        "eSCO Retransmissions = 0x%X",
                (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
                        BT_UART_MSG_FRAME5TXACTIVITY_POS,
@@ -1858,13 +1872,13 @@ static void iwlagn_print_uartmsg(struct iwl_priv *priv,
                (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
                        BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
 
-       IWL_DEBUG_NOTIF(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
+       IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
                (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
                        BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
                (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
                        BT_UART_MSG_FRAME6DISCOVERABLE_POS);
 
-       IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = "
+       IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "
                        "0x%X, Inquiry = 0x%X, Connectable = 0x%X",
                (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
                        BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
@@ -1914,10 +1928,10 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
                return;
        }
 
-       IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
-       IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
-       IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load);
-       IWL_DEBUG_NOTIF(priv, "    CI compliance: %d\n",
+       IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
+       IWL_DEBUG_COEX(priv, "    status: %d\n", coex->bt_status);
+       IWL_DEBUG_COEX(priv, "    traffic load: %d\n", coex->bt_traffic_load);
+       IWL_DEBUG_COEX(priv, "    CI compliance: %d\n",
                        coex->bt_ci_compliance);
        iwlagn_print_uartmsg(priv, uart_msg);
 
@@ -2315,7 +2329,8 @@ int iwlagn_start_device(struct iwl_priv *priv)
 {
        int ret;
 
-       if (iwl_prepare_card_hw(priv)) {
+       if ((priv->cfg->sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
+            iwl_prepare_card_hw(priv)) {
                IWL_WARN(priv, "Exit HW not ready\n");
                return -EIO;
        }
index 348f74f..f501d74 100644 (file)
@@ -198,7 +198,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
                /* Reschedule the ct_kill timer to occur in
                 * CT_KILL_EXIT_DURATION seconds to ensure we get a
                 * thermal update */
-               IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n");
+               IWL_DEBUG_TEMP(priv, "schedule ct_kill exit timer\n");
                mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
                          jiffies + CT_KILL_EXIT_DURATION * HZ);
        }
@@ -208,15 +208,15 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
                           bool stop)
 {
        if (stop) {
-               IWL_DEBUG_POWER(priv, "Stop all queues\n");
+               IWL_DEBUG_TEMP(priv, "Stop all queues\n");
                if (priv->mac80211_registered)
                        ieee80211_stop_queues(priv->hw);
-               IWL_DEBUG_POWER(priv,
+               IWL_DEBUG_TEMP(priv,
                                "Schedule 5 seconds CT_KILL Timer\n");
                mod_timer(&priv->thermal_throttle.ct_kill_exit_tm,
                          jiffies + CT_KILL_EXIT_DURATION * HZ);
        } else {
-               IWL_DEBUG_POWER(priv, "Wake all queues\n");
+               IWL_DEBUG_TEMP(priv, "Wake all queues\n");
                if (priv->mac80211_registered)
                        ieee80211_wake_queues(priv->hw);
        }
@@ -232,7 +232,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
 
        /* temperature timer expired, ready to go into CT_KILL state */
        if (tt->state != IWL_TI_CT_KILL) {
-               IWL_DEBUG_POWER(priv, "entering CT_KILL state when "
+               IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
                                "temperature timer expired\n");
                tt->state = IWL_TI_CT_KILL;
                set_bit(STATUS_CT_KILL, &priv->status);
@@ -242,7 +242,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
 
 static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
 {
-       IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n");
+       IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");
        /* make request to retrieve statistics information */
        iwl_send_statistics_request(priv, CMD_SYNC, false);
        /* Reschedule the ct_kill wait timer */
@@ -273,7 +273,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
            (temp > tt->tt_previous_temp) &&
            ((temp - tt->tt_previous_temp) >
            IWL_TT_INCREASE_MARGIN)) {
-               IWL_DEBUG_POWER(priv,
+               IWL_DEBUG_TEMP(priv,
                        "Temperature increase %d degree Celsius\n",
                        (temp - tt->tt_previous_temp));
        }
@@ -338,9 +338,9 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
                        } else if (old_state == IWL_TI_CT_KILL &&
                                 tt->state != IWL_TI_CT_KILL)
                                iwl_perform_ct_kill_task(priv, false);
-                       IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
+                       IWL_DEBUG_TEMP(priv, "Temperature state changed %u\n",
                                        tt->state);
-                       IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
+                       IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
                                        tt->tt_power_mode);
                }
                mutex_unlock(&priv->mutex);
@@ -397,7 +397,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
                            (temp > tt->tt_previous_temp) &&
                            ((temp - tt->tt_previous_temp) >
                            IWL_TT_INCREASE_MARGIN)) {
-                               IWL_DEBUG_POWER(priv,
+                               IWL_DEBUG_TEMP(priv,
                                        "Temperature increase %d "
                                        "degree Celsius\n",
                                        (temp - tt->tt_previous_temp));
@@ -467,13 +467,13 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
                                set_bit(STATUS_CT_KILL, &priv->status);
                        tt->state = old_state;
                } else {
-                       IWL_DEBUG_POWER(priv,
+                       IWL_DEBUG_TEMP(priv,
                                        "Thermal Throttling to new state: %u\n",
                                        tt->state);
                        if (old_state != IWL_TI_CT_KILL &&
                            tt->state == IWL_TI_CT_KILL) {
                                if (force) {
-                                       IWL_DEBUG_POWER(priv,
+                                       IWL_DEBUG_TEMP(priv,
                                                "Enter IWL_TI_CT_KILL\n");
                                        set_bit(STATUS_CT_KILL, &priv->status);
                                        iwl_perform_ct_kill_task(priv, true);
@@ -483,7 +483,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
                                }
                        } else if (old_state == IWL_TI_CT_KILL &&
                                  tt->state != IWL_TI_CT_KILL) {
-                               IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n");
+                               IWL_DEBUG_TEMP(priv, "Exit IWL_TI_CT_KILL\n");
                                iwl_perform_ct_kill_task(priv, false);
                        }
                }
@@ -568,7 +568,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
+       IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
        queue_work(priv->workqueue, &priv->ct_enter);
 }
 
@@ -577,7 +577,7 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
+       IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
        queue_work(priv->workqueue, &priv->ct_exit);
 }
 
@@ -603,7 +603,7 @@ void iwl_tt_handler(struct iwl_priv *priv)
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
-       IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
+       IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
        queue_work(priv->workqueue, &priv->tt_work);
 }
 
@@ -618,7 +618,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
        int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
        struct iwl_tt_trans *transaction;
 
-       IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n");
+       IWL_DEBUG_TEMP(priv, "Initialize Thermal Throttling\n");
 
        memset(tt, 0, sizeof(struct iwl_tt_mgmt));
 
@@ -638,7 +638,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
        INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
 
        if (priv->cfg->base_params->adv_thermal_throttle) {
-               IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
+               IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
                tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
                                         IWL_TI_STATE_MAX, GFP_KERNEL);
                tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
@@ -671,7 +671,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
                        priv->thermal_throttle.advanced_tt = true;
                }
        } else {
-               IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
+               IWL_DEBUG_TEMP(priv, "Legacy Thermal Throttling\n");
                priv->thermal_throttle.advanced_tt = false;
        }
 }
index 8bd48f6..d0ac090 100644 (file)
@@ -716,10 +716,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
-       txcmd_phys = pci_map_single(priv->pci_dev,
+       txcmd_phys = dma_map_single(priv->bus.dev,
                                    &out_cmd->hdr, firstlen,
-                                   PCI_DMA_BIDIRECTIONAL);
-       if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys)))
+                                   DMA_BIDIRECTIONAL);
+       if (unlikely(dma_mapping_error(priv->bus.dev, txcmd_phys)))
                goto drop_unlock_sta;
        dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
        dma_unmap_len_set(out_meta, len, firstlen);
@@ -735,13 +735,13 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
         * if any (802.11 null frames have no payload). */
        secondlen = skb->len - hdr_len;
        if (secondlen > 0) {
-               phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-                                          secondlen, PCI_DMA_TODEVICE);
-               if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
-                       pci_unmap_single(priv->pci_dev,
+               phys_addr = dma_map_single(priv->bus.dev, skb->data + hdr_len,
+                                          secondlen, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) {
+                       dma_unmap_single(priv->bus.dev,
                                         dma_unmap_addr(out_meta, mapping),
                                         dma_unmap_len(out_meta, len),
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        DMA_BIDIRECTIONAL);
                        goto drop_unlock_sta;
                }
        }
@@ -764,8 +764,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                                offsetof(struct iwl_tx_cmd, scratch);
 
        /* take back ownership of DMA buffer to enable update */
-       pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
-                                   firstlen, PCI_DMA_BIDIRECTIONAL);
+       dma_sync_single_for_cpu(priv->bus.dev, txcmd_phys, firstlen,
+                       DMA_BIDIRECTIONAL);
        tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
        tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
 
@@ -780,8 +780,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
                iwlagn_txq_update_byte_cnt_tbl(priv, txq,
                                               le16_to_cpu(tx_cmd->len));
 
-       pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
-                                      firstlen, PCI_DMA_BIDIRECTIONAL);
+       dma_sync_single_for_device(priv->bus.dev, txcmd_phys, firstlen,
+                       DMA_BIDIRECTIONAL);
 
        trace_iwlwifi_dev_tx(priv,
                             &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
@@ -834,8 +834,8 @@ drop_unlock_priv:
 static inline int iwlagn_alloc_dma_ptr(struct iwl_priv *priv,
                                    struct iwl_dma_ptr *ptr, size_t size)
 {
-       ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
-                                      GFP_KERNEL);
+       ptr->addr = dma_alloc_coherent(priv->bus.dev, size,
+                                      &ptr->dma, GFP_KERNEL);
        if (!ptr->addr)
                return -ENOMEM;
        ptr->size = size;
@@ -848,7 +848,7 @@ static inline void iwlagn_free_dma_ptr(struct iwl_priv *priv,
        if (unlikely(!ptr->addr))
                return;
 
-       dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
+       dma_free_coherent(priv->bus.dev, ptr->size, ptr->addr, ptr->dma);
        memset(ptr, 0, sizeof(*ptr));
 }
 
index 97de5d9..de8277e 100644 (file)
@@ -143,7 +143,7 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
                FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE    |
                FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
 
-       IWL_DEBUG_INFO(priv, "%s uCode section being loaded...\n", name);
+       IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
        ret = wait_event_interruptible_timeout(priv->wait_command_queue,
                                        priv->ucode_write_complete, 5 * HZ);
        if (ret == -ERESTARTSYS) {
@@ -183,10 +183,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
        __le16 *xtal_calib =
                (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
 
-       cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
-       cmd.hdr.first_group = 0;
-       cmd.hdr.groups_num = 1;
-       cmd.hdr.data_valid = 1;
+       iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
        cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
        cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
        return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
@@ -197,15 +194,14 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
 {
        struct iwl_calib_temperature_offset_cmd cmd;
        __le16 *offset_calib =
-               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE);
-       cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD;
-       cmd.hdr.first_group = 0;
-       cmd.hdr.groups_num = 1;
-       cmd.hdr.data_valid = 1;
+               (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
+
+       memset(&cmd, 0, sizeof(cmd));
+       iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
        cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]);
        if (!(cmd.radio_sensor_offset))
                cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
-       cmd.reserved = 0;
+
        IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
                        cmd.radio_sensor_offset);
        return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
@@ -508,7 +504,7 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv,
        u32 val;
        u32 i;
 
-       IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+       IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
 
        for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
                /* read data comes through single port, auto-incr addr */
@@ -533,7 +529,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
        u32 offs;
        int errors = 0;
 
-       IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+       IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
 
        iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
                           IWLAGN_RTC_INST_LOWER_BOUND);
@@ -559,7 +555,7 @@ static void iwl_print_mismatch_inst(struct iwl_priv *priv,
 static int iwl_verify_ucode(struct iwl_priv *priv, struct fw_img *img)
 {
        if (!iwlcore_verify_inst_sparse(priv, &img->code)) {
-               IWL_DEBUG_INFO(priv, "uCode is good in inst SRAM\n");
+               IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
                return 0;
        }
 
@@ -583,7 +579,7 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
 
        palive = &pkt->u.alive_frame;
 
-       IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+       IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
                       "0x%01X 0x%01X\n",
                       palive->is_valid, palive->ver_type,
                       palive->ver_subtype);
@@ -602,12 +598,12 @@ static void iwlagn_alive_fn(struct iwl_priv *priv,
 
 int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
                                 struct fw_img *image,
-                                int subtype, int alternate_subtype)
+                                enum iwlagn_ucode_type ucode_type)
 {
        struct iwl_notification_wait alive_wait;
        struct iwlagn_alive_data alive_data;
        int ret;
-       enum iwlagn_ucode_subtype old_type;
+       enum iwlagn_ucode_type old_type;
 
        ret = iwlagn_start_device(priv);
        if (ret)
@@ -617,7 +613,7 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
                                      iwlagn_alive_fn, &alive_data);
 
        old_type = priv->ucode_type;
-       priv->ucode_type = subtype;
+       priv->ucode_type = ucode_type;
 
        ret = iwlagn_load_given_ucode(priv, image);
        if (ret) {
@@ -645,15 +641,6 @@ int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
                return -EIO;
        }
 
-       if (alive_data.subtype != subtype &&
-           alive_data.subtype != alternate_subtype) {
-               IWL_ERR(priv,
-                       "Loaded ucode is not expected type (got %d, expected %d)!\n",
-                       alive_data.subtype, subtype);
-               priv->ucode_type = old_type;
-               return -EIO;
-       }
-
        ret = iwl_verify_ucode(priv, image);
        if (ret) {
                priv->ucode_type = old_type;
@@ -685,7 +672,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
        if (!priv->ucode_init.code.len)
                return 0;
 
-       if (priv->ucode_type != UCODE_SUBTYPE_NONE_LOADED)
+       if (priv->ucode_type != IWL_UCODE_NONE)
                return 0;
 
        iwlagn_init_notification_wait(priv, &calib_wait,
@@ -694,7 +681,7 @@ int iwlagn_run_init_ucode(struct iwl_priv *priv)
 
        /* Will also start the device */
        ret = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
-                                          UCODE_SUBTYPE_INIT, -1);
+                                          IWL_UCODE_INIT);
        if (ret)
                goto error;
 
index 099c279..77ceb8d 100644 (file)
@@ -32,8 +32,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
@@ -49,8 +47,6 @@
 
 #include <asm/div64.h>
 
-#define DRV_NAME        "iwlagn"
-
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -59,6 +55,7 @@
 #include "iwl-sta.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
+#include "iwl-pci.h"
 
 
 /******************************************************************************
@@ -440,10 +437,8 @@ static void iwl_bg_tx_flush(struct work_struct *work)
        if (!iwl_is_ready_rf(priv))
                return;
 
-       if (priv->cfg->ops->lib->txfifo_flush) {
-               IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
-               iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
-       }
+       IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
+       iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 }
 
 /**
@@ -497,9 +492,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
 
                rxq->queue[i] = NULL;
 
-               pci_unmap_page(priv->pci_dev, rxb->page_dma,
+               dma_unmap_page(priv->bus.dev, rxb->page_dma,
                               PAGE_SIZE << priv->hw_params.rx_page_order,
-                              PCI_DMA_FROMDEVICE);
+                              DMA_FROM_DEVICE);
                pkt = rxb_addr(rxb);
 
                len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
@@ -581,9 +576,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
                 * rx_free list for reuse later. */
                spin_lock_irqsave(&rxq->lock, flags);
                if (rxb->page != NULL) {
-                       rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+                       rxb->page_dma = dma_map_page(priv->bus.dev, rxb->page,
                                0, PAGE_SIZE << priv->hw_params.rx_page_order,
-                               PCI_DMA_FROMDEVICE);
+                               DMA_FROM_DEVICE);
                        list_add_tail(&rxb->list, &rxq->rx_free);
                        rxq->free_count++;
                } else
@@ -939,22 +934,28 @@ static struct attribute_group iwl_attribute_group = {
  *
  ******************************************************************************/
 
-static void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc)
+static void iwl_free_fw_desc(struct iwl_priv *priv, struct fw_desc *desc)
 {
        if (desc->v_addr)
-               dma_free_coherent(&pci_dev->dev, desc->len,
+               dma_free_coherent(priv->bus.dev, desc->len,
                                  desc->v_addr, desc->p_addr);
        desc->v_addr = NULL;
        desc->len = 0;
 }
 
-static void iwl_free_fw_img(struct pci_dev *pci_dev, struct fw_img *img)
+static void iwl_free_fw_img(struct iwl_priv *priv, struct fw_img *img)
 {
-       iwl_free_fw_desc(pci_dev, &img->code);
-       iwl_free_fw_desc(pci_dev, &img->data);
+       iwl_free_fw_desc(priv, &img->code);
+       iwl_free_fw_desc(priv, &img->data);
 }
 
-static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
+static void iwl_dealloc_ucode(struct iwl_priv *priv)
+{
+       iwl_free_fw_img(priv, &priv->ucode_rt);
+       iwl_free_fw_img(priv, &priv->ucode_init);
+}
+
+static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
                             const void *data, size_t len)
 {
        if (!len) {
@@ -962,21 +963,16 @@ static int iwl_alloc_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc,
                return -EINVAL;
        }
 
-       desc->v_addr = dma_alloc_coherent(&pci_dev->dev, len,
+       desc->v_addr = dma_alloc_coherent(priv->bus.dev, len,
                                          &desc->p_addr, GFP_KERNEL);
        if (!desc->v_addr)
                return -ENOMEM;
+
        desc->len = len;
        memcpy(desc->v_addr, data, len);
        return 0;
 }
 
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-       iwl_free_fw_img(priv->pci_dev, &priv->ucode_rt);
-       iwl_free_fw_img(priv->pci_dev, &priv->ucode_init);
-}
-
 struct iwlagn_ucode_capabilities {
        u32 max_probe_length;
        u32 standard_phy_calibration_size;
@@ -1021,8 +1017,8 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
                       priv->firmware_name);
 
        return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
-                                      &priv->pci_dev->dev, GFP_KERNEL, priv,
-                                      iwl_ucode_callback);
+                                      priv->bus.dev,
+                                      GFP_KERNEL, priv, iwl_ucode_callback);
 }
 
 struct iwlagn_firmware_pieces {
@@ -1443,19 +1439,19 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        /* Runtime instructions and 2 copies of data:
         * 1) unmodified from disk
         * 2) backup cache for save/restore during power-downs */
-       if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.code,
+       if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.code,
                              pieces.inst, pieces.inst_size))
                goto err_pci_alloc;
-       if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_rt.data,
+       if (iwl_alloc_fw_desc(priv, &priv->ucode_rt.data,
                              pieces.data, pieces.data_size))
                goto err_pci_alloc;
 
        /* Initialization instructions and data */
        if (pieces.init_size && pieces.init_data_size) {
-               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.code,
+               if (iwl_alloc_fw_desc(priv, &priv->ucode_init.code,
                                      pieces.init, pieces.init_size))
                        goto err_pci_alloc;
-               if (iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init.data,
+               if (iwl_alloc_fw_desc(priv, &priv->ucode_init.data,
                                      pieces.init_data, pieces.init_data_size))
                        goto err_pci_alloc;
        }
@@ -1485,7 +1481,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        priv->new_scan_threshold_behaviour =
                !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
 
-       if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
+       if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) &&
+           (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) {
                priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
                priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
        } else
@@ -1523,7 +1520,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
        if (err)
                IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
 
-       err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+       err = sysfs_create_group(&(priv->bus.dev->kobj),
                                        &iwl_attribute_group);
        if (err) {
                IWL_ERR(priv, "failed to create sysfs device attributes\n");
@@ -1544,10 +1541,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
 
  err_pci_alloc:
        IWL_ERR(priv, "failed to allocate pci memory\n");
-       iwl_dealloc_ucode_pci(priv);
+       iwl_dealloc_ucode(priv);
  out_unbind:
        complete(&priv->_agn.firmware_loading_complete);
-       device_release_driver(&priv->pci_dev->dev);
+       device_release_driver(priv->bus.dev);
        release_firmware(ucode_raw);
 }
 
@@ -1626,7 +1623,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
        struct iwl_error_event_table table;
 
        base = priv->device_pointers.error_event_table;
-       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+       if (priv->ucode_type == IWL_UCODE_INIT) {
                if (!base)
                        base = priv->_agn.init_errlog_ptr;
        } else {
@@ -1638,7 +1635,7 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
                IWL_ERR(priv,
                        "Not valid error log pointer 0x%08X for %s uCode\n",
                        base,
-                       (priv->ucode_type == UCODE_SUBTYPE_INIT)
+                       (priv->ucode_type == IWL_UCODE_INIT)
                                        ? "Init" : "RT");
                return;
        }
@@ -1702,7 +1699,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
                return pos;
 
        base = priv->device_pointers.log_event_table;
-       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+       if (priv->ucode_type == IWL_UCODE_INIT) {
                if (!base)
                        base = priv->_agn.init_evtlog_ptr;
        } else {
@@ -1815,7 +1812,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
        size_t bufsz = 0;
 
        base = priv->device_pointers.log_event_table;
-       if (priv->ucode_type == UCODE_SUBTYPE_INIT) {
+       if (priv->ucode_type == IWL_UCODE_INIT) {
                logsize = priv->_agn.init_evtlog_size;
                if (!base)
                        base = priv->_agn.init_evtlog_ptr;
@@ -1829,7 +1826,7 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
                IWL_ERR(priv,
                        "Invalid event log pointer 0x%08X for %s uCode\n",
                        base,
-                       (priv->ucode_type == UCODE_SUBTYPE_INIT)
+                       (priv->ucode_type == IWL_UCODE_INIT)
                                        ? "Init" : "RT");
                return -EINVAL;
        }
@@ -2210,8 +2207,7 @@ static int __iwl_up(struct iwl_priv *priv)
 
        ret = iwlagn_load_ucode_wait_alive(priv,
                                           &priv->ucode_rt,
-                                          UCODE_SUBTYPE_REGULAR,
-                                          UCODE_SUBTYPE_REGULAR_NEW);
+                                          IWL_UCODE_REGULAR);
        if (ret) {
                IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
                goto error;
@@ -2516,7 +2512,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
        hw->flags |= IEEE80211_HW_SUPPORTS_PS |
                     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
 
-       if (priv->cfg->sku & IWL_SKU_N)
+       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
                hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                             IEEE80211_HW_SUPPORTS_STATIC_SMPS;
 
@@ -2549,11 +2545,10 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
                            WIPHY_FLAG_DISABLE_BEACON_HINTS |
                            WIPHY_FLAG_IBSS_RSN;
 
-       /*
-        * For now, disable PS by default because it affects
-        * RX performance significantly.
-        */
-       hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       if (iwlagn_mod_params.power_save)
+               hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
+       else
+               hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 
        hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
        /* we create the 802.11 header and a zero-length SSID element */
@@ -2757,7 +2752,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
        IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
                     sta->addr, tid);
 
-       if (!(priv->cfg->sku & IWL_SKU_N))
+       if (!(priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE))
                return -EACCES;
 
        mutex_lock(&priv->mutex);
@@ -3052,10 +3047,6 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
        mutex_lock(&priv->mutex);
        IWL_DEBUG_MAC80211(priv, "enter\n");
 
-       /* do not support "flush" */
-       if (!priv->cfg->ops->lib->txfifo_flush)
-               goto done;
-
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
                IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
                goto done;
@@ -3071,7 +3062,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
         */
        if (drop) {
                IWL_DEBUG_MAC80211(priv, "send flush command\n");
-               if (priv->cfg->ops->lib->txfifo_flush(priv, IWL_DROP_ALL)) {
+               if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
                        IWL_ERR(priv, "flush request fail\n");
                        goto done;
                }
@@ -3352,14 +3343,11 @@ struct ieee80211_ops iwlagn_hw_ops = {
        .offchannel_tx = iwl_mac_offchannel_tx,
        .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
        CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
+       CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
 };
 
 static u32 iwl_hw_detect(struct iwl_priv *priv)
 {
-       u8 rev_id;
-
-       pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id);
-       IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id);
        return iwl_read32(priv, CSR_HW_REV);
 }
 
@@ -3375,7 +3363,7 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
        priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
 
        if (iwlagn_mod_params.disable_11n)
-               priv->cfg->sku &= ~IWL_SKU_N;
+               priv->cfg->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
 
        /* Device-specific setup */
        return priv->cfg->ops->lib->set_hw_params(priv);
@@ -3425,29 +3413,9 @@ out:
        return hw;
 }
 
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static void iwl_init_context(struct iwl_priv *priv)
 {
-       int err = 0, i;
-       struct iwl_priv *priv;
-       struct ieee80211_hw *hw;
-       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-       unsigned long flags;
-       u16 pci_cmd, num_mac;
-       u32 hw_rev;
-
-       /************************
-        * 1. Allocating HW data
-        ************************/
-
-       hw = iwl_alloc_all(cfg);
-       if (!hw) {
-               err = -ENOMEM;
-               goto out;
-       }
-       priv = hw->priv;
-       /* At this point both hw and priv are allocated. */
-
-       priv->ucode_type = UCODE_SUBTYPE_NONE_LOADED;
+       int i;
 
        /*
         * The default context is always valid,
@@ -3479,8 +3447,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
 
        priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
-       priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
-       priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd = REPLY_WIPAN_RXON_ASSOC;
+       priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
+               REPLY_WIPAN_RXON_TIMING;
+       priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
+               REPLY_WIPAN_RXON_ASSOC;
        priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
        priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
        priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
@@ -3500,12 +3470,41 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
 
        BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+}
+
+int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
+               struct iwl_cfg *cfg)
+{
+       int err = 0;
+       struct iwl_priv *priv;
+       struct ieee80211_hw *hw;
+       u16 num_mac;
+       u32 hw_rev;
 
-       SET_IEEE80211_DEV(hw, &pdev->dev);
+       /************************
+        * 1. Allocating HW data
+        ************************/
+       hw = iwl_alloc_all(cfg);
+       if (!hw) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       priv = hw->priv;
+
+       priv->bus.priv = priv;
+       priv->bus.bus_specific = bus_specific;
+       priv->bus.ops = bus_ops;
+       priv->bus.irq = priv->bus.ops->get_irq(&priv->bus);
+       priv->bus.ops->set_drv_data(&priv->bus, priv);
+       priv->bus.dev = priv->bus.ops->get_dev(&priv->bus);
+
+       /* At this point both hw and priv are allocated. */
+
+       SET_IEEE80211_DEV(hw, priv->bus.dev);
 
        IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
        priv->cfg = cfg;
-       priv->pci_dev = pdev;
        priv->inta_mask = CSR_INI_SET_MASK;
 
        /* is antenna coupling more than 35dB ? */
@@ -3521,52 +3520,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (iwl_alloc_traffic_mem(priv))
                IWL_ERR(priv, "Not enough memory to generate traffic log\n");
 
-       /**************************
-        * 2. Initializing PCI bus
-        **************************/
-       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-                               PCIE_LINK_STATE_CLKPM);
-
-       if (pci_enable_device(pdev)) {
-               err = -ENODEV;
-               goto out_ieee80211_free_hw;
-       }
-
-       pci_set_master(pdev);
-
-       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (!err)
-               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
-       if (err) {
-               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-               if (!err)
-                       err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-               /* both attempts failed: */
-               if (err) {
-                       IWL_WARN(priv, "No suitable DMA available.\n");
-                       goto out_pci_disable_device;
-               }
-       }
-
-       err = pci_request_regions(pdev, DRV_NAME);
-       if (err)
-               goto out_pci_disable_device;
-
-       pci_set_drvdata(pdev, priv);
-
-
-       /***********************
-        * 3. Read REV register
-        ***********************/
-       priv->hw_base = pci_iomap(pdev, 0, 0);
-       if (!priv->hw_base) {
-               err = -ENODEV;
-               goto out_pci_release_regions;
-       }
-
-       IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-               (unsigned long long) pci_resource_len(pdev, 0));
-       IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
 
        /* these spin locks will be used in apm_ops.init and EEPROM access
         * we should init now
@@ -3581,17 +3534,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 
+       /***********************
+        * 3. Read REV register
+        ***********************/
        hw_rev = iwl_hw_detect(priv);
        IWL_INFO(priv, "Detected %s, REV=0x%X\n",
                priv->cfg->name, hw_rev);
 
-       /* We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state */
-       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
        if (iwl_prepare_card_hw(priv)) {
+               err = -EIO;
                IWL_WARN(priv, "Failed, HW not ready\n");
-               goto out_iounmap;
+               goto out_free_traffic_mem;
        }
 
        /*****************
@@ -3601,7 +3554,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        err = iwl_eeprom_init(priv, hw_rev);
        if (err) {
                IWL_ERR(priv, "Unable to init EEPROM\n");
-               goto out_iounmap;
+               goto out_free_traffic_mem;
        }
        err = iwl_eeprom_check_version(priv);
        if (err)
@@ -3624,10 +3577,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                priv->hw->wiphy->n_addresses++;
        }
 
+       /* initialize all valid contexts */
+       iwl_init_context(priv);
+
        /************************
         * 5. Setup HW constants
         ************************/
        if (iwl_set_hw_params(priv)) {
+               err = -ENOENT;
                IWL_ERR(priv, "failed to set hw parameters\n");
                goto out_free_eeprom;
        }
@@ -3644,19 +3601,13 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /********************
         * 7. Setup services
         ********************/
-       spin_lock_irqsave(&priv->lock, flags);
-       iwl_disable_interrupts(priv);
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       pci_enable_msi(priv->pci_dev);
-
        iwl_alloc_isr_ict(priv);
 
-       err = request_irq(priv->pci_dev->irq, iwl_isr_ict,
-                         IRQF_SHARED, DRV_NAME, priv);
+       err = request_irq(priv->bus.irq, iwl_isr_ict, IRQF_SHARED,
+                         DRV_NAME, priv);
        if (err) {
-               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-               goto out_disable_msi;
+               IWL_ERR(priv, "Error allocating IRQ %d\n", priv->bus.irq);
+               goto out_uninit_drv;
        }
 
        iwl_setup_deferred_work(priv);
@@ -3664,16 +3615,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        iwl_testmode_init(priv);
 
        /*********************************************
-        * 8. Enable interrupts and read RFKILL state
+        * 8. Enable interrupts
         *********************************************/
 
-       /* enable rfkill interrupt: hw bug w/a */
-       pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
-       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
-               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
-               pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
-       }
-
        iwl_enable_rfkill_int(priv);
 
        /* If platform's RF_KILL switch is NOT set to KILL */
@@ -3699,41 +3643,30 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  out_destroy_workqueue:
        destroy_workqueue(priv->workqueue);
        priv->workqueue = NULL;
-       free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
+       free_irq(priv->bus.irq, priv);
        iwl_free_isr_ict(priv);
-       pci_disable_msi(priv->pci_dev);
+ out_uninit_drv:
        iwl_uninit_drv(priv);
  out_free_eeprom:
        iwl_eeprom_free(priv);
- out_iounmap:
-       pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-       pci_set_drvdata(pdev, NULL);
-       pci_release_regions(pdev);
- out_pci_disable_device:
-       pci_disable_device(pdev);
- out_ieee80211_free_hw:
+ out_free_traffic_mem:
        iwl_free_traffic_mem(priv);
        ieee80211_free_hw(priv->hw);
  out:
        return err;
 }
 
-static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+void __devexit iwl_remove(struct iwl_priv * priv)
 {
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
        unsigned long flags;
 
-       if (!priv)
-               return;
-
        wait_for_completion(&priv->_agn.firmware_loading_complete);
 
        IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
 
        iwl_dbgfs_unregister(priv);
-       sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+       sysfs_remove_group(&priv->bus.dev->kobj,
+                          &iwl_attribute_group);
 
        /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
         * to be called and iwl_down since we are removing the device
@@ -3763,7 +3696,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
        iwl_synchronize_irq(priv);
 
-       iwl_dealloc_ucode_pci(priv);
+       iwl_dealloc_ucode(priv);
 
        if (priv->rxq.bd)
                iwlagn_rx_queue_free(priv, &priv->rxq);
@@ -3782,12 +3715,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
        priv->workqueue = NULL;
        iwl_free_traffic_mem(priv);
 
-       free_irq(priv->pci_dev->irq, priv);
-       pci_disable_msi(priv->pci_dev);
-       pci_iounmap(pdev, priv->hw_base);
-       pci_release_regions(pdev);
-       pci_disable_device(pdev);
-       pci_set_drvdata(pdev, NULL);
+       free_irq(priv->bus.irq, priv);
+       priv->bus.ops->set_drv_data(&priv->bus, NULL);
 
        iwl_uninit_drv(priv);
 
@@ -3804,206 +3733,6 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
  * driver and module entry point
  *
  *****************************************************************************/
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
-       {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
-
-/* 5300 Series WiFi */
-       {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
-
-/* 5350 Series WiFi/WiMax */
-       {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
-
-/* 5150 Series Wifi/WiMax */
-       {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
-
-       {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
-       {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
-       {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
-
-/* 6x00 Series */
-       {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
-       {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
-
-/* 6x05 Series */
-       {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
-
-/* 6x30 Series */
-       {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
-       {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
-       {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
-
-/* 6x50 WiFi/WiMax Series */
-       {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
-
-/* 6150 WiFi/WiMax Series */
-       {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
-
-/* 1000 Series WiFi */
-       {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
-
-/* 100 Series WiFi */
-       {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
-       {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
-       {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
-
-/* 130 Series WiFi */
-       {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
-
-/* 2x00 Series */
-       {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
-
-/* 2x30 Series */
-       {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
-
-/* 6x35 Series */
-       {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
-       {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
-
-/* 105 Series */
-       {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
-
-/* 135 Series */
-       {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
-       {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
-       {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
-
-       {0}
-};
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
-
-static struct pci_driver iwl_driver = {
-       .name = DRV_NAME,
-       .id_table = iwl_hw_card_ids,
-       .probe = iwl_pci_probe,
-       .remove = __devexit_p(iwl_pci_remove),
-       .driver.pm = IWL_PM_OPS,
-};
-
 static int __init iwl_init(void)
 {
 
@@ -4017,12 +3746,10 @@ static int __init iwl_init(void)
                return ret;
        }
 
-       ret = pci_register_driver(&iwl_driver);
-       if (ret) {
-               pr_err("Unable to initialize PCI module\n");
-               goto error_register;
-       }
+       ret = iwl_pci_register_driver();
 
+       if (ret)
+               goto error_register;
        return ret;
 
 error_register:
@@ -4032,7 +3759,7 @@ error_register:
 
 static void __exit iwl_exit(void)
 {
-       pci_unregister_driver(&iwl_driver);
+       iwl_pci_unregister_driver();
        iwlagn_rate_control_unregister();
 }
 
@@ -4074,3 +3801,47 @@ MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
 
 module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
 MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ *   Able to scan and finding all the available AP
+ *   Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+module_param_named(bt_coex_active, iwlagn_mod_params.bt_coex_active,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bt co-exist (default: enable)");
+
+module_param_named(led_mode, iwlagn_mod_params.led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+               "1=On(RF On)/Off(RF Off), 2=blinking (default: 0)");
+
+module_param_named(power_save, iwlagn_mod_params.power_save,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(power_save,
+                "enable WiFi power management (default: disable)");
+
+module_param_named(power_level, iwlagn_mod_params.power_level,
+               int, S_IRUGO);
+MODULE_PARM_DESC(power_level,
+                "default power save level (range from 1 - 5, default: 1)");
+
+/*
+ * For now, keep using power level 1 instead of automatically
+ * adjusting ...
+ */
+module_param_named(no_sleep_autoadjust, iwlagn_mod_params.no_sleep_autoadjust,
+               bool, S_IRUGO);
+MODULE_PARM_DESC(no_sleep_autoadjust,
+                "don't automatically adjust sleep level "
+                "according to maximum network latency (default: true)");
index d171684..6d5584a 100644 (file)
@@ -125,10 +125,18 @@ irqreturn_t iwl_isr_ict(int irq, void *data);
 static inline void iwl_synchronize_irq(struct iwl_priv *priv)
 {
        /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(priv->pci_dev->irq);
+       synchronize_irq(priv->bus.irq);
        tasklet_kill(&priv->irq_tasklet);
 }
 
+static inline void iwl_set_calib_hdr(struct iwl_calib_hdr *hdr, u8 cmd)
+{
+       hdr->op_code = cmd;
+       hdr->first_group = 0;
+       hdr->groups_num = 1;
+       hdr->data_valid = 1;
+}
+
 int iwl_prepare_card_hw(struct iwl_priv *priv);
 
 int iwlagn_start_device(struct iwl_priv *priv);
@@ -161,7 +169,7 @@ void iwlagn_send_prio_tbl(struct iwl_priv *priv);
 int iwlagn_run_init_ucode(struct iwl_priv *priv);
 int iwlagn_load_ucode_wait_alive(struct iwl_priv *priv,
                                 struct fw_img *image,
-                                int subtype, int alternate_subtype);
+                                enum iwlagn_ucode_type ucode_type);
 
 /* lib */
 void iwl_check_abort_status(struct iwl_priv *priv,
@@ -343,6 +351,9 @@ extern int iwl_alive_start(struct iwl_priv *priv);
 /* svtool */
 #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
 extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len);
+extern int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+                            struct netlink_callback *cb,
+                            void *data, int len);
 extern void iwl_testmode_init(struct iwl_priv *priv);
 extern void iwl_testmode_cleanup(struct iwl_priv *priv);
 #else
@@ -352,6 +363,13 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
        return -ENOSYS;
 }
 static inline
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+                     struct netlink_callback *cb,
+                     void *data, int len)
+{
+       return -ENOSYS;
+}
+static inline
 void iwl_testmode_init(struct iwl_priv *priv)
 {
 }
@@ -361,4 +379,8 @@ void iwl_testmode_cleanup(struct iwl_priv *priv)
 }
 #endif
 
+int iwl_probe(void *bus_specific, struct iwl_bus_ops *bus_ops,
+               struct iwl_cfg *cfg);
+void __devexit iwl_remove(struct iwl_priv * priv);
+
 #endif /* __iwl_agn_h__ */
index 6ee5f1a..8a2edf8 100644 (file)
@@ -384,18 +384,6 @@ struct iwl_tx_ant_config_cmd {
 
 #define UCODE_VALID_OK cpu_to_le32(0x1)
 
-enum iwlagn_ucode_subtype {
-       UCODE_SUBTYPE_REGULAR   = 0,
-       UCODE_SUBTYPE_REGULAR_NEW = 1,
-       UCODE_SUBTYPE_INIT      = 9,
-
-       /*
-        * Not a valid subtype, the ucode has just a u8, so
-        * we can use something > 0xff for this value.
-        */
-       UCODE_SUBTYPE_NONE_LOADED = 0x100,
-};
-
 /**
  * REPLY_ALIVE = 0x1 (response only, not a command)
  *
@@ -984,15 +972,26 @@ struct iwl_rem_sta_cmd {
        u8 reserved2[2];
 } __packed;
 
-#define IWL_TX_FIFO_BK_MSK             cpu_to_le32(BIT(0))
-#define IWL_TX_FIFO_BE_MSK             cpu_to_le32(BIT(1))
-#define IWL_TX_FIFO_VI_MSK             cpu_to_le32(BIT(2))
-#define IWL_TX_FIFO_VO_MSK             cpu_to_le32(BIT(3))
+
+/* WiFi queues mask */
+#define IWL_SCD_BK_MSK                 cpu_to_le32(BIT(0))
+#define IWL_SCD_BE_MSK                 cpu_to_le32(BIT(1))
+#define IWL_SCD_VI_MSK                 cpu_to_le32(BIT(2))
+#define IWL_SCD_VO_MSK                 cpu_to_le32(BIT(3))
+#define IWL_SCD_MGMT_MSK               cpu_to_le32(BIT(3))
+
+/* PAN queues mask */
+#define IWL_PAN_SCD_BK_MSK             cpu_to_le32(BIT(4))
+#define IWL_PAN_SCD_BE_MSK             cpu_to_le32(BIT(5))
+#define IWL_PAN_SCD_VI_MSK             cpu_to_le32(BIT(6))
+#define IWL_PAN_SCD_VO_MSK             cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MGMT_MSK           cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MULTICAST_MSK      cpu_to_le32(BIT(8))
+
 #define IWL_AGG_TX_QUEUE_MSK           cpu_to_le32(0xffc00)
 
 #define IWL_DROP_SINGLE                0
-#define IWL_DROP_SELECTED      1
-#define IWL_DROP_ALL           2
+#define IWL_DROP_ALL           (BIT(IWL_RXON_CTX_BSS) | BIT(IWL_RXON_CTX_PAN))
 
 /*
  * REPLY_TXFIFO_FLUSH = 0x1e(command and response)
index 5416b12..cde7253 100644 (file)
 #include "iwl-helpers.h"
 #include "iwl-agn.h"
 
-
-/*
- * set bt_coex_active to true, uCode will do kill/defer
- * every time the priority line is asserted (BT is sending signals on the
- * priority line in the PCIx).
- * set bt_coex_active to false, uCode will ignore the BT activity and
- * perform the normal operation
- *
- * User might experience transmit issue on some platform due to WiFi/BT
- * co-exist problem. The possible behaviors are:
- *   Able to scan and finding all the available AP
- *   Not able to associate with any AP
- * On those platforms, WiFi communication can be restored by set
- * "bt_coex_active" module parameter to "false"
- *
- * default: bt_coex_active = true (BT_COEX_ENABLE)
- */
-bool bt_coex_active = true;
-module_param(bt_coex_active, bool, S_IRUGO);
-MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
-
 u32 iwl_debug_level;
 
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
@@ -164,7 +143,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
        sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
        sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
 
-       if (priv->cfg->sku & IWL_SKU_N)
+       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
                iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
                                         IEEE80211_BAND_5GHZ);
 
@@ -174,7 +153,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
        sband->bitrates = rates;
        sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
 
-       if (priv->cfg->sku & IWL_SKU_N)
+       if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
                iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
                                         IEEE80211_BAND_2GHZ);
 
@@ -229,12 +208,12 @@ int iwlcore_init_geos(struct iwl_priv *priv)
        priv->tx_power_next = max_tx_power;
 
        if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
-            priv->cfg->sku & IWL_SKU_A) {
+            priv->cfg->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
+               char buf[32];
+               priv->bus.ops->get_hw_id(&priv->bus, buf, sizeof(buf));
                IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
-                       "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
-                          priv->pci_dev->device,
-                          priv->pci_dev->subsystem_device);
-               priv->cfg->sku &= ~IWL_SKU_A;
+                       "Please send your %s to maintainer.\n", buf);
+               priv->cfg->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
        }
 
        IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
@@ -1018,8 +997,6 @@ void iwl_apm_stop(struct iwl_priv *priv)
 int iwl_apm_init(struct iwl_priv *priv)
 {
        int ret = 0;
-       u16 lctl;
-
        IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
 
        /*
@@ -1048,27 +1025,7 @@ int iwl_apm_init(struct iwl_priv *priv)
        iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
                                    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
 
-       /*
-        * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
-        * Check if BIOS (or OS) enabled L1-ASPM on this device.
-        * If so (likely), disable L0S, so device moves directly L0->L1;
-        *    costs negligible amount of power savings.
-        * If not (unlikely), enable L0S, so there is at least some
-        *    power savings, even without L1.
-        */
-       lctl = iwl_pcie_link_ctl(priv);
-       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
-                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
-               /* L1-ASPM enabled; disable(!) L0S  */
-               iwl_set_bit(priv, CSR_GIO_REG,
-                               CSR_GIO_REG_VAL_L0S_ENABLED);
-               IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
-       } else {
-               /* L1-ASPM disabled; enable(!) L0S */
-               iwl_clear_bit(priv, CSR_GIO_REG,
-                               CSR_GIO_REG_VAL_L0S_ENABLED);
-               IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
-       }
+       priv->bus.ops->apm_config(&priv->bus);
 
        /* Configure analog phase-lock-loop before activating to D0A */
        if (priv->cfg->base_params->pll_cfg_val)
@@ -1179,7 +1136,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
                .kill_cts_mask = 0,
        };
 
-       if (!bt_coex_active)
+       if (!iwlagn_mod_params.bt_coex_active)
                bt_cmd.flags = BT_COEX_DISABLE;
        else
                bt_cmd.flags = BT_COEX_ENABLE;
@@ -1969,11 +1926,8 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
 
 #ifdef CONFIG_PM
 
-int iwl_pci_suspend(struct device *device)
+int iwl_suspend(struct iwl_priv *priv)
 {
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
-
        /*
         * This function is called when system goes into suspend state
         * mac80211 will call iwl_mac_stop() from the mac80211 suspend function
@@ -1986,18 +1940,10 @@ int iwl_pci_suspend(struct device *device)
        return 0;
 }
 
-int iwl_pci_resume(struct device *device)
+int iwl_resume(struct iwl_priv *priv)
 {
-       struct pci_dev *pdev = to_pci_dev(device);
-       struct iwl_priv *priv = pci_get_drvdata(pdev);
        bool hw_rfkill = false;
 
-       /*
-        * We disable the RETRY_TIMEOUT register (0x41) to keep
-        * PCI Tx retries from interfering with C3 CPU state.
-        */
-       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
-
        iwl_enable_interrupts(priv);
 
        if (!(iwl_read32(priv, CSR_GP_CNTRL) &
@@ -2014,13 +1960,4 @@ int iwl_pci_resume(struct device *device)
        return 0;
 }
 
-const struct dev_pm_ops iwl_pm_ops = {
-       .suspend = iwl_pci_suspend,
-       .resume = iwl_pci_resume,
-       .freeze = iwl_pci_suspend,
-       .thaw = iwl_pci_resume,
-       .poweroff = iwl_pci_suspend,
-       .restore = iwl_pci_resume,
-};
-
 #endif /* CONFIG_PM */
index 05ea88a..adf9f9b 100644 (file)
@@ -76,17 +76,8 @@ struct iwl_cmd;
 #define DRV_COPYRIGHT  "Copyright(c) 2003-2011 Intel Corporation"
 #define DRV_AUTHOR     "<ilw@linux.intel.com>"
 
-#define IWL_PCI_DEVICE(dev, subdev, cfg) \
-       .vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
-       .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
-       .driver_data = (kernel_ulong_t)&(cfg)
-
 #define TIME_UNIT              1024
 
-#define IWL_SKU_G       0x1
-#define IWL_SKU_A       0x2
-#define IWL_SKU_N       0x8
-
 #define IWL_CMD(x) case x: return #x
 
 struct iwl_hcmd_ops {
@@ -146,10 +137,6 @@ struct iwl_lib_ops {
 
        /* temperature */
        struct iwl_temp_ops temp_ops;
-
-       int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
-       void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
-
 };
 
 /* NIC specific ops */
@@ -173,6 +160,11 @@ struct iwl_mod_params {
        int restart_fw;         /* def: 1 = restart firmware */
        bool plcp_check;        /* def: true = enable plcp health check */
        bool ack_check;         /* def: false = disable ack health check */
+       bool bt_coex_active;    /* def: true = enable bt coex */
+       int led_mode;           /* def: 0 = system default */
+       bool no_sleep_autoadjust; /* def: true = disable autoadjust */
+       bool power_save;        /* def: false = disable power save */
+       int power_level;        /* def: 1 = power level */
 };
 
 /*
@@ -289,7 +281,7 @@ struct iwl_cfg {
        const unsigned int ucode_api_min;
        u8   valid_tx_ant;
        u8   valid_rx_ant;
-       unsigned int sku;
+       u16  sku;
        u16  eeprom_ver;
        u16  eeprom_calib_ver;
        const struct iwl_ops *ops;
@@ -480,36 +472,14 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
 
 int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
 
-
-/*****************************************************
- * PCI                                              *
- *****************************************************/
-
-static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
-{
-       int pos;
-       u16 pci_lnk_ctl;
-       pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
-       pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
-       return pci_lnk_ctl;
-}
-
 void iwl_bg_watchdog(unsigned long data);
 u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval);
 __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
                           u32 addon, u32 beacon_interval);
 
 #ifdef CONFIG_PM
-int iwl_pci_suspend(struct device *device);
-int iwl_pci_resume(struct device *device);
-extern const struct dev_pm_ops iwl_pm_ops;
-
-#define IWL_PM_OPS     (&iwl_pm_ops)
-
-#else /* !CONFIG_PM */
-
-#define IWL_PM_OPS     NULL
-
+int iwl_suspend(struct iwl_priv *priv);
+int iwl_resume(struct iwl_priv *priv);
 #endif /* !CONFIG_PM */
 
 /*****************************************************
@@ -624,7 +594,6 @@ static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
               priv->cfg->bt_params->advanced_bt_coexist;
 }
 
-extern bool bt_coex_active;
 extern bool bt_siso_mode;
 
 
index 2824ccb..eb95d1a 100644 (file)
 struct iwl_priv;
 extern u32 iwl_debug_level;
 
-#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
-#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
-#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
-#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+#define IWL_ERR(p, f, a...) dev_err(p->bus.ops->get_dev(&p->bus), f, ## a)
+#define IWL_WARN(p, f, a...) dev_warn(p->bus.ops->get_dev(&p->bus), f, ## a)
+#define IWL_INFO(p, f, a...) dev_info(p->bus.ops->get_dev(&p->bus), f, ## a)
+#define IWL_CRIT(p, f, a...) dev_crit(p->bus.ops->get_dev(&p->bus), f, ## a)
 
 #define iwl_print_hex_error(priv, p, len)                              \
 do {                                                                   \
@@ -125,13 +125,13 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
 /* 0x00000F00 - 0x00000100 */
 #define IWL_DL_POWER           (1 << 8)
 #define IWL_DL_TEMP            (1 << 9)
-#define IWL_DL_NOTIF           (1 << 10)
+/* reserved (1 << 10) */
 #define IWL_DL_SCAN            (1 << 11)
 /* 0x0000F000 - 0x00001000 */
 #define IWL_DL_ASSOC           (1 << 12)
 #define IWL_DL_DROP            (1 << 13)
-#define IWL_DL_TXPOWER         (1 << 14)
-#define IWL_DL_AP              (1 << 15)
+/* reserved (1 << 14) */
+#define IWL_DL_COEX            (1 << 15)
 /* 0x000F0000 - 0x00010000 */
 #define IWL_DL_FW              (1 << 16)
 #define IWL_DL_RF_KILL         (1 << 17)
@@ -171,12 +171,10 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
 #define IWL_DEBUG_DROP(p, f, a...)     IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
 #define IWL_DEBUG_DROP_LIMIT(p, f, a...)       \
                IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
-#define IWL_DEBUG_AP(p, f, a...)       IWL_DEBUG(p, IWL_DL_AP, f, ## a)
-#define IWL_DEBUG_TXPOWER(p, f, a...)  IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_COEX(p, f, a...)     IWL_DEBUG(p, IWL_DL_COEX, f, ## a)
 #define IWL_DEBUG_RATE(p, f, a...)     IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
 #define IWL_DEBUG_RATE_LIMIT(p, f, a...)       \
                IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
-#define IWL_DEBUG_NOTIF(p, f, a...)    IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
 #define IWL_DEBUG_ASSOC(p, f, a...)    \
                IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
 #define IWL_DEBUG_ASSOC_LIMIT(p, f, a...)      \
index 0e6a04b..6f9ebae 100644 (file)
@@ -227,7 +227,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
        /* default is to dump the entire data segment */
        if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
                priv->dbgfs_sram_offset = 0x800000;
-               if (priv->ucode_type == UCODE_SUBTYPE_INIT)
+               if (priv->ucode_type == IWL_UCODE_INIT)
                        priv->dbgfs_sram_len = priv->ucode_init.data.len;
                else
                        priv->dbgfs_sram_len = priv->ucode_rt.data.len;
@@ -2493,7 +2493,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
        if (iwl_is_rfkill(priv))
                return -EFAULT;
 
-       priv->cfg->ops->lib->dev_txfifo_flush(priv, IWL_DROP_ALL);
+       iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
 
        return count;
 }
@@ -2693,8 +2693,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
        DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
        DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
-       if (priv->cfg->ops->lib->dev_txfifo_flush)
-               DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
+       DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
        DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | S_IRUSR);
 
        DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
index 7ad98d8..f1b1128 100644 (file)
@@ -49,6 +49,8 @@
 #include "iwl-agn-rs.h"
 #include "iwl-agn-tt.h"
 
+#define DRV_NAME        "iwlagn"
+
 struct iwl_tx_queue;
 
 /* CT-KILL constants */
@@ -1169,14 +1171,63 @@ enum iwl_scan_type {
        IWL_SCAN_OFFCH_TX,
 };
 
+enum iwlagn_ucode_type {
+       IWL_UCODE_NONE,
+       IWL_UCODE_REGULAR,
+       IWL_UCODE_INIT,
+       IWL_UCODE_WOWLAN,
+};
+
 #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL
 struct iwl_testmode_trace {
+       u32 buff_size;
+       u32 total_size;
+       u32 num_chunks;
        u8 *cpu_addr;
        u8 *trace_addr;
        dma_addr_t dma_addr;
        bool trace_enabled;
 };
 #endif
+
+struct iwl_bus;
+
+/**
+ * struct iwl_bus_ops - bus specific operations
+
+ * @get_pm_support: must returns true if the bus can go to sleep
+ * @apm_config: will be called during the config of the APM configuration
+ * @set_drv_data: set the priv pointer to the bus layer
+ * @get_dev: returns the device struct
+ * @get_irq: returns the irq number
+ * @get_hw_id: prints the hw_id in the provided buffer
+ * @write8: write a byte to register at offset ofs
+ * @write32: write a dword to register at offset ofs
+ * @wread32: read a dword at register at offset ofs
+ */
+struct iwl_bus_ops {
+       bool (*get_pm_support)(struct iwl_bus *bus);
+       void (*apm_config)(struct iwl_bus *bus);
+       void (*set_drv_data)(struct iwl_bus *bus, void *priv);
+       struct device *(*get_dev)(const struct iwl_bus *bus);
+       unsigned int (*get_irq)(const struct iwl_bus *bus);
+       void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
+       void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
+       void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
+       u32 (*read32)(struct iwl_bus *bus, u32 ofs);
+};
+
+struct iwl_bus {
+       /* pointer to bus specific struct */
+       void *bus_specific;
+
+       /* Common data to all buses */
+       struct iwl_priv *priv; /* driver's context */
+       struct device *dev;
+       struct iwl_bus_ops *ops;
+       unsigned int irq;
+};
+
 struct iwl_priv {
 
        /* ieee device used by generic ieee processing code */
@@ -1244,17 +1295,14 @@ struct iwl_priv {
        spinlock_t reg_lock;    /* protect hw register access */
        struct mutex mutex;
 
-       /* basic pci-network driver stuff */
-       struct pci_dev *pci_dev;
-
-       /* pci hardware address support */
-       void __iomem *hw_base;
+       struct iwl_bus bus;     /* bus specific data */
 
        /* microcode/device supports multiple contexts */
        u8 valid_contexts;
 
        /* command queue number */
        u8 cmd_queue;
+       u8 last_sync_cmd_id;
 
        /* max number of station keys */
        u8 sta_key_max_num;
@@ -1271,7 +1319,7 @@ struct iwl_priv {
        struct fw_img ucode_rt;
        struct fw_img ucode_init;
 
-       enum iwlagn_ucode_subtype ucode_type;
+       enum iwlagn_ucode_type ucode_type;
        u8 ucode_write_complete;        /* the image write is complete */
        char firmware_name[25];
 
index 47a56bc..768d0ee 100644 (file)
@@ -834,3 +834,28 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
 
        return NULL;
 }
+
+void iwl_rf_config(struct iwl_priv *priv)
+{
+       u16 radio_cfg;
+
+       radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+       /* write radio config values to register */
+       if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX) {
+               iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+                           EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+                           EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+                           EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+               IWL_INFO(priv, "Radio type=0x%x-0x%x-0x%x\n",
+                        EEPROM_RF_CFG_TYPE_MSK(radio_cfg),
+                        EEPROM_RF_CFG_STEP_MSK(radio_cfg),
+                        EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+       } else
+               WARN_ON(1);
+
+       /* set CSR_HW_CONFIG_REG for uCode use */
+       iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+                   CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+                   CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+}
index c960c6f..804f910 100644 (file)
@@ -110,12 +110,10 @@ enum {
 };
 
 /* SKU Capabilities */
-/* 5000 and up */
-#define EEPROM_SKU_CAP_BAND_POS                                (4)
-#define EEPROM_SKU_CAP_BAND_SELECTION                  \
-               (3 << EEPROM_SKU_CAP_BAND_POS)
+#define EEPROM_SKU_CAP_BAND_24GHZ                      (1 << 4)
+#define EEPROM_SKU_CAP_BAND_52GHZ                      (1 << 5)
 #define EEPROM_SKU_CAP_11N_ENABLE                      (1 << 6)
-#define EEPROM_SKU_CAP_AMT_ENABLE                      (1 << 7)
+#define EEPROM_SKU_CAP_AMT_ENABLE                      (1 << 7)
 #define EEPROM_SKU_CAP_IPAN_ENABLE                     (1 << 8)
 
 /* *regulatory* channel data format in eeprom, one for each channel.
@@ -164,16 +162,12 @@ struct iwl_eeprom_enhanced_txpwr {
        s8 mimo3_max;
 } __packed;
 
-/* 5000 Specific */
-#define EEPROM_5000_TX_POWER_VERSION    (4)
-#define EEPROM_5000_EEPROM_VERSION     (0x11A)
-
-/* 5000 and up calibration */
+/* calibration */
 #define EEPROM_CALIB_ALL       (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
 #define EEPROM_XTAL            ((2*0x128) | EEPROM_CALIB_ALL)
 
-/* 5000 temperature */
-#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
+/* temperature */
+#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
 
 /* agn links */
 #define EEPROM_LINK_HOST             (2*0x64)
@@ -205,6 +199,10 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_6000_REG_BAND_24_HT40_CHANNELS  ((0x80)\
                | INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 14  bytes */
 
+/* 5000 Specific */
+#define EEPROM_5000_TX_POWER_VERSION    (4)
+#define EEPROM_5000_EEPROM_VERSION     (0x11A)
+
 /* 5050 Specific */
 #define EEPROM_5050_TX_POWER_VERSION    (4)
 #define EEPROM_5050_EEPROM_VERSION     (0x21E)
@@ -270,13 +268,13 @@ extern const u8 iwl_eeprom_band_1[14];
 
 /* General */
 #define EEPROM_DEVICE_ID                    (2*0x08)   /* 2 bytes */
+#define EEPROM_SUBSYSTEM_ID                (2*0x0A)    /* 2 bytes */
 #define EEPROM_MAC_ADDRESS                  (2*0x15)   /* 6  bytes */
 #define EEPROM_BOARD_REVISION               (2*0x35)   /* 2  bytes */
 #define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1) /* 9  bytes */
 #define EEPROM_VERSION                      (2*0x44)   /* 2  bytes */
 #define EEPROM_SKU_CAP                      (2*0x45)   /* 2  bytes */
 #define EEPROM_OEM_MODE                     (2*0x46)   /* 2  bytes */
-#define EEPROM_WOWLAN_MODE                  (2*0x47)   /* 2  bytes */
 #define EEPROM_RADIO_CONFIG                 (2*0x48)   /* 2  bytes */
 #define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)   /* 2  bytes */
 
@@ -311,5 +309,6 @@ void iwl_free_channel_map(struct iwl_priv *priv);
 const struct iwl_channel_info *iwl_get_channel_info(
                const struct iwl_priv *priv,
                enum ieee80211_band band, u16 channel);
+void iwl_rf_config(struct iwl_priv *priv);
 
 #endif  /* __iwl_eeprom_h__ */
index 76f9966..7cdb1ec 100644 (file)
@@ -181,7 +181,16 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
        IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
                        get_cmd_string(cmd->id));
 
-       set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+       if (test_and_set_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+               IWL_ERR(priv, "STATUS_HCMD_ACTIVE already set while sending %s"
+                             ". Previous SYNC cmdn is %s\n",
+                       get_cmd_string(cmd->id),
+                       get_cmd_string(priv->last_sync_cmd_id));
+               WARN_ON(1);
+       } else {
+               priv->last_sync_cmd_id = cmd->id;
+       }
+
        IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
                        get_cmd_string(cmd->id));
 
index 41207a3..9d91552 100644 (file)
@@ -120,7 +120,16 @@ static inline void iwl_wake_any_queue(struct iwl_priv *priv,
        }
 }
 
+#ifdef ieee80211_stop_queue
+#undef ieee80211_stop_queue
+#endif
+
 #define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+
+#ifdef ieee80211_wake_queue
+#undef ieee80211_wake_queue
+#endif
+
 #define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
 
 static inline void iwl_disable_interrupts(struct iwl_priv *priv)
index 869edc5..c56eae7 100644 (file)
 static inline void iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val)
 {
        trace_iwlwifi_dev_iowrite8(priv, ofs, val);
-       iowrite8(val, priv->hw_base + ofs);
+       priv->bus.ops->write8(&priv->bus, ofs, val);
 }
 
 static inline void iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val)
 {
        trace_iwlwifi_dev_iowrite32(priv, ofs, val);
-       iowrite32(val, priv->hw_base + ofs);
+       priv->bus.ops->write32(&priv->bus, ofs, val);
 }
 
 static inline u32 iwl_read32(struct iwl_priv *priv, u32 ofs)
 {
-       u32 val = ioread32(priv->hw_base + ofs);
+       u32 val = priv->bus.ops->read32(&priv->bus, ofs);
        trace_iwlwifi_dev_ioread32(priv, ofs, val);
        return val;
 }
index 7c23beb..ff08da0 100644 (file)
@@ -28,8 +28,6 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
+#include "iwl-agn.h"
 #include "iwl-io.h"
 
-/* default: IWL_LED_BLINK(0) using blinking index table */
-static int led_mode;
-module_param(led_mode, int, S_IRUGO);
-MODULE_PARM_DESC(led_mode, "0=system default, "
-               "1=On(RF On)/Off(RF Off), 2=blinking");
-
 /* Throughput          OFF time(ms)    ON time (ms)
  *     >300                    25              25
  *     >200 to 300             40              40
@@ -181,7 +174,7 @@ static int iwl_led_blink_set(struct led_classdev *led_cdev,
 
 void iwl_leds_init(struct iwl_priv *priv)
 {
-       int mode = led_mode;
+       int mode = iwlagn_mod_params.led_mode;
        int ret;
 
        if (mode == IWL_LED_DEFAULT)
@@ -209,7 +202,8 @@ void iwl_leds_init(struct iwl_priv *priv)
                break;
        }
 
-       ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+       ret = led_classdev_register(priv->bus.dev,
+                                   &priv->led);
        if (ret) {
                kfree(priv->led.name);
                return;
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c
new file mode 100644 (file)
index 0000000..7328fbf
--- /dev/null
@@ -0,0 +1,571 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+
+#include "iwl-pci.h"
+#include "iwl-agn.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT  0x041
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN   0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN    0x02
+
+struct iwl_pci_bus {
+       /* basic pci-network driver stuff */
+       struct pci_dev *pci_dev;
+
+       /* pci hardware address support */
+       void __iomem *hw_base;
+};
+
+#define IWL_BUS_GET_PCI_BUS(_iwl_bus) \
+                       ((struct iwl_pci_bus *) ((_iwl_bus)->bus_specific))
+
+#define IWL_BUS_GET_PCI_DEV(_iwl_bus) \
+                       ((IWL_BUS_GET_PCI_BUS(_iwl_bus))->pci_dev)
+
+static u16 iwl_pciexp_link_ctrl(struct iwl_bus *bus)
+{
+       int pos;
+       u16 pci_lnk_ctl;
+       struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+       pos = pci_find_capability(pci_dev, PCI_CAP_ID_EXP);
+       pci_read_config_word(pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+       return pci_lnk_ctl;
+}
+
+static bool iwl_pci_is_pm_supported(struct iwl_bus *bus)
+{
+       u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+       return !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+}
+
+static void iwl_pci_apm_config(struct iwl_bus *bus)
+{
+       /*
+        * HW bug W/A for instability in PCIe bus L0S->L1 transition.
+        * Check if BIOS (or OS) enabled L1-ASPM on this device.
+        * If so (likely), disable L0S, so device moves directly L0->L1;
+        *    costs negligible amount of power savings.
+        * If not (unlikely), enable L0S, so there is at least some
+        *    power savings, even without L1.
+        */
+       u16 lctl = iwl_pciexp_link_ctrl(bus);
+
+       if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+                               PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+               /* L1-ASPM enabled; disable(!) L0S */
+               iwl_set_bit(bus->priv, CSR_GIO_REG,
+                               CSR_GIO_REG_VAL_L0S_ENABLED);
+               IWL_DEBUG_POWER(bus->priv, "L1 Enabled; Disabling L0S\n");
+       } else {
+               /* L1-ASPM disabled; enable(!) L0S */
+               iwl_clear_bit(bus->priv, CSR_GIO_REG,
+                               CSR_GIO_REG_VAL_L0S_ENABLED);
+               IWL_DEBUG_POWER(bus->priv, "L1 Disabled; Enabling L0S\n");
+       }
+}
+
+static void iwl_pci_set_drv_data(struct iwl_bus *bus, void *drv_priv)
+{
+       pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), drv_priv);
+}
+
+static struct device *iwl_pci_get_dev(const struct iwl_bus *bus)
+{
+       return &(IWL_BUS_GET_PCI_DEV(bus)->dev);
+}
+
+static unsigned int iwl_pci_get_irq(const struct iwl_bus *bus)
+{
+       return IWL_BUS_GET_PCI_DEV(bus)->irq;
+}
+
+static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
+                             int buf_len)
+{
+       struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
+
+       snprintf(buf, buf_len, "PCI ID: 0x%04X:0x%04X", pci_dev->device,
+                pci_dev->subsystem_device);
+}
+
+static void iwl_pci_write8(struct iwl_bus *bus, u32 ofs, u8 val)
+{
+       iowrite8(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static void iwl_pci_write32(struct iwl_bus *bus, u32 ofs, u32 val)
+{
+       iowrite32(val, IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+}
+
+static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
+{
+       u32 val = ioread32(IWL_BUS_GET_PCI_BUS(bus)->hw_base + ofs);
+       return val;
+}
+
+static struct iwl_bus_ops pci_ops = {
+       .get_pm_support = iwl_pci_is_pm_supported,
+       .apm_config = iwl_pci_apm_config,
+       .set_drv_data = iwl_pci_set_drv_data,
+       .get_dev = iwl_pci_get_dev,
+       .get_irq = iwl_pci_get_irq,
+       .get_hw_id = iwl_pci_get_hw_id,
+       .write8 = iwl_pci_write8,
+       .write32 = iwl_pci_write32,
+       .read32 = iwl_pci_read32,
+};
+
+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
+       .vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
+       .subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+       .driver_data = (kernel_ulong_t)&(cfg)
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
+       {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */
+
+/* 5300 Series WiFi */
+       {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */
+
+/* 5350 Series WiFi/WiMax */
+       {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */
+
+/* 5150 Series Wifi/WiMax */
+       {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */
+
+       {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */
+       {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */
+
+/* 6x00 Series */
+       {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x422C, 0x1306, iwl6000i_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x422C, 0x1307, iwl6000i_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x422C, 0x1321, iwl6000i_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x422C, 0x1326, iwl6000i_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
+       {IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
+
+/* 6x05 Series */
+       {IWL_PCI_DEVICE(0x0082, 0x1301, iwl6005_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1306, iwl6005_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1307, iwl6005_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1321, iwl6005_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0082, 0x1326, iwl6005_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
+
+/* 6x30 Series */
+       {IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x008A, 0x5307, iwl1030_bg_cfg)},
+       {IWL_PCI_DEVICE(0x008A, 0x5325, iwl1030_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x008A, 0x5327, iwl1030_bg_cfg)},
+       {IWL_PCI_DEVICE(0x008B, 0x5315, iwl1030_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x008B, 0x5317, iwl1030_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0090, 0x5211, iwl6030_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0090, 0x5215, iwl6030_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0090, 0x5216, iwl6030_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5201, iwl6030_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5205, iwl6030_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5206, iwl6030_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5207, iwl6030_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5221, iwl6030_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5225, iwl6030_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0091, 0x5226, iwl6030_2abg_cfg)},
+
+/* 6x50 WiFi/WiMax Series */
+       {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)},
+
+/* 6150 WiFi/WiMax Series */
+       {IWL_PCI_DEVICE(0x0885, 0x1305, iwl6150_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0885, 0x1307, iwl6150_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0885, 0x1325, iwl6150_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0885, 0x1327, iwl6150_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0886, 0x1315, iwl6150_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0886, 0x1317, iwl6150_bg_cfg)},
+
+/* 1000 Series WiFi */
+       {IWL_PCI_DEVICE(0x0083, 0x1205, iwl1000_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1305, iwl1000_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1225, iwl1000_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1325, iwl1000_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0084, 0x1215, iwl1000_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0084, 0x1315, iwl1000_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1206, iwl1000_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1306, iwl1000_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1226, iwl1000_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0083, 0x1326, iwl1000_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0084, 0x1216, iwl1000_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0084, 0x1316, iwl1000_bg_cfg)},
+
+/* 100 Series WiFi */
+       {IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
+
+/* 130 Series WiFi */
+       {IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0896, 0x5007, iwl130_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0897, 0x5015, iwl130_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0897, 0x5017, iwl130_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
+
+/* 2x00 Series */
+       {IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+
+/* 2x30 Series */
+       {IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
+
+/* 6x35 Series */
+       {IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
+       {IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
+
+/* 105 Series */
+       {IWL_PCI_DEVICE(0x0894, 0x0022, iwl105_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0895, 0x0222, iwl105_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0894, 0x0422, iwl105_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0894, 0x0026, iwl105_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0895, 0x0226, iwl105_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0894, 0x0426, iwl105_bg_cfg)},
+
+/* 135 Series */
+       {IWL_PCI_DEVICE(0x0892, 0x0062, iwl135_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0893, 0x0262, iwl135_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0892, 0x0462, iwl135_bgn_cfg)},
+       {IWL_PCI_DEVICE(0x0892, 0x0066, iwl135_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0893, 0x0266, iwl135_bg_cfg)},
+       {IWL_PCI_DEVICE(0x0892, 0x0466, iwl135_bg_cfg)},
+
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
+
+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+       struct iwl_pci_bus *bus;
+       u8 rev_id;
+       u16 pci_cmd;
+       int err;
+
+       bus = kzalloc(sizeof(*bus), GFP_KERNEL);
+       if (!bus) {
+               pr_err("Couldn't allocate iwl_pci_bus");
+               err = -ENOMEM;
+               goto out_no_pci;
+       }
+
+       bus->pci_dev = pdev;
+
+       /* W/A - seems to solve weird behavior. We need to remove this if we
+        * don't want to stay in L1 all the time. This wastes a lot of power */
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                               PCIE_LINK_STATE_CLKPM);
+
+       if (pci_enable_device(pdev)) {
+               err = -ENODEV;
+               goto out_no_pci;
+       }
+
+       pci_set_master(pdev);
+
+       err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+       if (!err)
+               err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+       if (err) {
+               err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+               if (!err)
+                       err = pci_set_consistent_dma_mask(pdev,
+                                                       DMA_BIT_MASK(32));
+               /* both attempts failed: */
+               if (err) {
+                       pr_err("No suitable DMA available.\n");
+                       goto out_pci_disable_device;
+               }
+       }
+
+       err = pci_request_regions(pdev, DRV_NAME);
+       if (err) {
+               pr_err("pci_request_regions failed");
+               goto out_pci_disable_device;
+       }
+
+       bus->hw_base = pci_iomap(pdev, 0, 0);
+       if (!bus->hw_base) {
+               pr_err("pci_iomap failed");
+               err = -ENODEV;
+               goto out_pci_release_regions;
+       }
+
+       pr_info("pci_resource_len = 0x%08llx\n",
+               (unsigned long long) pci_resource_len(pdev, 0));
+       pr_info("pci_resource_base = %p\n", bus->hw_base);
+
+       pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id);
+       pr_info("HW Revision ID = 0x%X\n", rev_id);
+
+       /* We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state */
+       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+       err = pci_enable_msi(pdev);
+       if (err) {
+               pr_err("pci_enable_msi failed");
+               goto out_iounmap;
+       }
+
+       /* TODO: Move this away, not needed if not MSI */
+       /* enable rfkill interrupt: hw bug w/a */
+       pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
+       if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+               pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+               pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
+       }
+
+       err = iwl_probe((void *) bus, &pci_ops, cfg);
+       if (err)
+               goto out_disable_msi;
+       return 0;
+
+out_disable_msi:
+       pci_disable_msi(pdev);
+out_iounmap:
+       pci_iounmap(pdev, bus->hw_base);
+out_pci_release_regions:
+       pci_set_drvdata(pdev, NULL);
+       pci_release_regions(pdev);
+out_pci_disable_device:
+       pci_disable_device(pdev);
+out_no_pci:
+       kfree(bus);
+       return err;
+}
+
+static void iwl_pci_down(void *bus)
+{
+       struct iwl_pci_bus *pci_bus = (struct iwl_pci_bus *) bus;
+
+       pci_disable_msi(pci_bus->pci_dev);
+       pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
+       pci_release_regions(pci_bus->pci_dev);
+       pci_disable_device(pci_bus->pci_dev);
+       pci_set_drvdata(pci_bus->pci_dev, NULL);
+
+       kfree(pci_bus);
+}
+
+static void __devexit iwl_pci_remove(struct pci_dev *pdev)
+{
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+       /* This can happen if probe failed */
+       if (unlikely(!priv))
+               return;
+
+       iwl_remove(priv);
+
+       iwl_pci_down(IWL_BUS_GET_PCI_BUS(&priv->bus));
+}
+
+#ifdef CONFIG_PM
+
+static int iwl_pci_suspend(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+       return iwl_suspend(priv);
+}
+
+static int iwl_pci_resume(struct device *device)
+{
+       struct pci_dev *pdev = to_pci_dev(device);
+       struct iwl_priv *priv = pci_get_drvdata(pdev);
+
+       /*
+        * We disable the RETRY_TIMEOUT register (0x41) to keep
+        * PCI Tx retries from interfering with C3 CPU state.
+        */
+       pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+       return iwl_resume(priv);
+}
+
+static const struct dev_pm_ops iwl_dev_pm_ops = {
+       .suspend = iwl_pci_suspend,
+       .resume = iwl_pci_resume,
+       .freeze = iwl_pci_suspend,
+       .thaw = iwl_pci_resume,
+       .poweroff = iwl_pci_suspend,
+       .restore = iwl_pci_resume,
+};
+
+#define IWL_PM_OPS     (&iwl_dev_pm_ops)
+
+#else
+
+#define IWL_PM_OPS     NULL
+
+#endif
+
+static struct pci_driver iwl_pci_driver = {
+       .name = DRV_NAME,
+       .id_table = iwl_hw_card_ids,
+       .probe = iwl_pci_probe,
+       .remove = __devexit_p(iwl_pci_remove),
+       .driver.pm = IWL_PM_OPS,
+};
+
+int __must_check iwl_pci_register_driver(void)
+{
+       int ret;
+       ret = pci_register_driver(&iwl_pci_driver);
+       if (ret)
+               pr_err("Unable to initialize PCI module\n");
+
+       return ret;
+}
+
+void iwl_pci_unregister_driver(void)
+{
+       pci_unregister_driver(&iwl_pci_driver);
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.h b/drivers/net/wireless/iwlwifi/iwl-pci.h
new file mode 100644 (file)
index 0000000..9396c7c
--- /dev/null
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#ifndef __iwl_pci_h__
+#define __iwl_pci_h__
+
+int __must_check iwl_pci_register_driver(void);
+void iwl_pci_unregister_driver(void);
+
+#endif
index 595c930..565e57e 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
+#include "iwl-agn.h"
 #include "iwl-core.h"
 #include "iwl-io.h"
 #include "iwl-commands.h"
  * also use pre-defined power levels.
  */
 
-/*
- * For now, keep using power level 1 instead of automatically
- * adjusting ...
- */
-bool no_sleep_autoadjust = true;
-module_param(no_sleep_autoadjust, bool, S_IRUGO);
-MODULE_PARM_DESC(no_sleep_autoadjust,
-                "don't automatically adjust sleep level "
-                "according to maximum network latency");
-
 /*
  * This defines the old power levels. They are still used by default
  * (level 1) and for thermal throttle (levels 3 through 5)
@@ -254,7 +245,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
                }
        }
 
-       if (priv->power_data.pci_pm)
+       if (priv->power_data.bus_pm)
                cmd->flags |= IWL_POWER_PCI_PM_MSK;
        else
                cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
@@ -269,7 +260,7 @@ static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
 {
        memset(cmd, 0, sizeof(*cmd));
 
-       if (priv->power_data.pci_pm)
+       if (priv->power_data.bus_pm)
                cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
        IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
@@ -305,7 +296,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
        cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
                     IWL_POWER_FAST_PD; /* no use seeing frames for others */
 
-       if (priv->power_data.pci_pm)
+       if (priv->power_data.bus_pm)
                cmd->flags |= IWL_POWER_PCI_PM_MSK;
 
        if (priv->cfg->base_params->shadow_reg_enable)
@@ -367,9 +358,15 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
                iwl_static_sleep_cmd(priv, cmd,
                                     priv->power_data.debug_sleep_level_override,
                                     dtimper);
-       else if (no_sleep_autoadjust)
-               iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
-       else
+       else if (iwlagn_mod_params.no_sleep_autoadjust) {
+               if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 &&
+                   iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5)
+                       iwl_static_sleep_cmd(priv, cmd,
+                               iwlagn_mod_params.power_level, dtimper);
+               else
+                       iwl_static_sleep_cmd(priv, cmd,
+                               IWL_POWER_INDEX_1, dtimper);
+       } else
                iwl_power_fill_sleep_cmd(priv, cmd,
                                         priv->hw->conf.dynamic_ps_timeout,
                                         priv->hw->conf.max_sleep_period);
@@ -434,9 +431,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
 {
-       u16 lctl = iwl_pcie_link_ctl(priv);
-
-       priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+       priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus);
 
        priv->power_data.debug_sleep_level_override = -1;
 
index 59635d7..5f7b720 100644 (file)
@@ -43,7 +43,7 @@ struct iwl_power_mgr {
        struct iwl_powertable_cmd sleep_cmd;
        struct iwl_powertable_cmd sleep_cmd_next;
        int debug_sleep_level_override;
-       bool pci_pm;
+       bool bus_pm;
 };
 
 int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
index b774517..3efa706 100644 (file)
@@ -182,7 +182,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
 int iwl_rx_queue_alloc(struct iwl_priv *priv)
 {
        struct iwl_rx_queue *rxq = &priv->rxq;
-       struct device *dev = &priv->pci_dev->dev;
+       struct device *dev = priv->bus.dev;
        int i;
 
        spin_lock_init(&rxq->lock);
@@ -213,7 +213,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
        return 0;
 
 err_rb:
-       dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+       dma_free_coherent(dev, 4 * RX_QUEUE_SIZE, rxq->bd,
                          rxq->bd_dma);
 err_bd:
        return -ENOMEM;
index 69b7e6b..c00aa5a 100644 (file)
@@ -69,7 +69,6 @@
 #include <net/mac80211.h>
 #include <net/netlink.h>
 
-
 #include "iwl-dev.h"
 #include "iwl-core.h"
 #include "iwl-debug.h"
@@ -101,9 +100,11 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
        [IWL_TM_ATTR_EEPROM] = { .type = NLA_UNSPEC, },
 
        [IWL_TM_ATTR_TRACE_ADDR] = { .type = NLA_UNSPEC, },
-       [IWL_TM_ATTR_TRACE_DATA] = { .type = NLA_UNSPEC, },
+       [IWL_TM_ATTR_TRACE_DUMP] = { .type = NLA_UNSPEC, },
+       [IWL_TM_ATTR_TRACE_SIZE] = { .type = NLA_U32, },
 
        [IWL_TM_ATTR_FIXRATE] = { .type = NLA_U32, },
+
 };
 
 /*
@@ -179,19 +180,21 @@ void iwl_testmode_init(struct iwl_priv *priv)
 
 static void iwl_trace_cleanup(struct iwl_priv *priv)
 {
-       struct device *dev = &priv->pci_dev->dev;
+       struct device *dev = priv->bus.dev;
 
        if (priv->testmode_trace.trace_enabled) {
                if (priv->testmode_trace.cpu_addr &&
                    priv->testmode_trace.dma_addr)
                        dma_free_coherent(dev,
-                                       TRACE_TOTAL_SIZE,
+                                       priv->testmode_trace.total_size,
                                        priv->testmode_trace.cpu_addr,
                                        priv->testmode_trace.dma_addr);
                priv->testmode_trace.trace_enabled = false;
                priv->testmode_trace.cpu_addr = NULL;
                priv->testmode_trace.trace_addr = NULL;
                priv->testmode_trace.dma_addr = 0;
+               priv->testmode_trace.buff_size = 0;
+               priv->testmode_trace.total_size = 0;
        }
 }
 
@@ -394,7 +397,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
 
        case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
                status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init,
-                                          UCODE_SUBTYPE_INIT, -1);
+                                                     IWL_UCODE_INIT);
                if (status)
                        IWL_DEBUG_INFO(priv,
                                "Error loading init ucode: %d\n", status);
@@ -408,8 +411,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
        case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
                status = iwlagn_load_ucode_wait_alive(priv,
                                           &priv->ucode_rt,
-                                          UCODE_SUBTYPE_REGULAR,
-                                          UCODE_SUBTYPE_REGULAR_NEW);
+                                          IWL_UCODE_REGULAR);
                if (status) {
                        IWL_DEBUG_INFO(priv,
                                "Error loading runtime ucode: %d\n", status);
@@ -482,16 +484,29 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
        struct iwl_priv *priv = hw->priv;
        struct sk_buff *skb;
        int status = 0;
-       struct device *dev = &priv->pci_dev->dev;
+       struct device *dev = priv->bus.dev;
 
        switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
        case IWL_TM_CMD_APP2DEV_BEGIN_TRACE:
                if (priv->testmode_trace.trace_enabled)
                        return -EBUSY;
 
+               if (!tb[IWL_TM_ATTR_TRACE_SIZE])
+                       priv->testmode_trace.buff_size = TRACE_BUFF_SIZE_DEF;
+               else
+                       priv->testmode_trace.buff_size =
+                               nla_get_u32(tb[IWL_TM_ATTR_TRACE_SIZE]);
+               if (!priv->testmode_trace.buff_size)
+                       return -EINVAL;
+               if (priv->testmode_trace.buff_size < TRACE_BUFF_SIZE_MIN ||
+                   priv->testmode_trace.buff_size > TRACE_BUFF_SIZE_MAX)
+                       return -EINVAL;
+
+               priv->testmode_trace.total_size =
+                       priv->testmode_trace.buff_size + TRACE_BUFF_PADD;
                priv->testmode_trace.cpu_addr =
                        dma_alloc_coherent(dev,
-                                          TRACE_TOTAL_SIZE,
+                                          priv->testmode_trace.total_size,
                                           &priv->testmode_trace.dma_addr,
                                           GFP_KERNEL);
                if (!priv->testmode_trace.cpu_addr)
@@ -500,7 +515,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
                priv->testmode_trace.trace_addr = (u8 *)PTR_ALIGN(
                        priv->testmode_trace.cpu_addr, 0x100);
                memset(priv->testmode_trace.trace_addr, 0x03B,
-                       TRACE_BUFF_SIZE);
+                       priv->testmode_trace.buff_size);
                skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
                        sizeof(priv->testmode_trace.dma_addr) + 20);
                if (!skb) {
@@ -518,34 +533,14 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
                                       "Error sending msg : %d\n",
                                       status);
                }
+               priv->testmode_trace.num_chunks =
+                       DIV_ROUND_UP(priv->testmode_trace.buff_size,
+                                    TRACE_CHUNK_SIZE);
                break;
 
        case IWL_TM_CMD_APP2DEV_END_TRACE:
                iwl_trace_cleanup(priv);
                break;
-
-       case IWL_TM_CMD_APP2DEV_READ_TRACE:
-               if (priv->testmode_trace.trace_enabled &&
-                   priv->testmode_trace.trace_addr) {
-                       skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy,
-                               20 + TRACE_BUFF_SIZE);
-                       if (skb == NULL) {
-                               IWL_DEBUG_INFO(priv,
-                                       "Error allocating memory\n");
-                               return -ENOMEM;
-                       }
-                       NLA_PUT(skb, IWL_TM_ATTR_TRACE_DATA,
-                               TRACE_BUFF_SIZE,
-                               priv->testmode_trace.trace_addr);
-                       status = cfg80211_testmode_reply(skb);
-                       if (status < 0) {
-                               IWL_DEBUG_INFO(priv,
-                                      "Error sending msg : %d\n", status);
-                       }
-               } else
-                       return -EFAULT;
-               break;
-
        default:
                IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n");
                return -ENOSYS;
@@ -560,6 +555,37 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
+                                  struct sk_buff *skb,
+                                  struct netlink_callback *cb)
+{
+       struct iwl_priv *priv = hw->priv;
+       int idx, length;
+
+       if (priv->testmode_trace.trace_enabled &&
+           priv->testmode_trace.trace_addr) {
+               idx = cb->args[4];
+               if (idx >= priv->testmode_trace.num_chunks)
+                       return -ENOENT;
+               length = TRACE_CHUNK_SIZE;
+               if (((idx + 1) == priv->testmode_trace.num_chunks) &&
+                   (priv->testmode_trace.buff_size % TRACE_CHUNK_SIZE))
+                       length = priv->testmode_trace.buff_size %
+                               TRACE_CHUNK_SIZE;
+
+               NLA_PUT(skb, IWL_TM_ATTR_TRACE_DUMP, length,
+                       priv->testmode_trace.trace_addr +
+                       (TRACE_CHUNK_SIZE * idx));
+               idx++;
+               cb->args[4] = idx;
+               return 0;
+       } else
+               return -EFAULT;
+
+ nla_put_failure:
+       return -ENOBUFS;
+}
+
 /* The testmode gnl message handler that takes the gnl message from the
  * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
  * invoke the corresponding handlers.
@@ -638,3 +664,50 @@ int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
        mutex_unlock(&priv->mutex);
        return result;
 }
+
+int iwl_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
+                     struct netlink_callback *cb,
+                     void *data, int len)
+{
+       struct nlattr *tb[IWL_TM_ATTR_MAX];
+       struct iwl_priv *priv = hw->priv;
+       int result;
+       u32 cmd;
+
+       if (cb->args[3]) {
+               /* offset by 1 since commands start at 0 */
+               cmd = cb->args[3] - 1;
+       } else {
+               result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len,
+                               iwl_testmode_gnl_msg_policy);
+               if (result) {
+                       IWL_DEBUG_INFO(priv,
+                              "Error parsing the gnl message : %d\n", result);
+                       return result;
+               }
+
+               /* IWL_TM_ATTR_COMMAND is absolutely mandatory */
+               if (!tb[IWL_TM_ATTR_COMMAND]) {
+                       IWL_DEBUG_INFO(priv,
+                               "Error finding testmode command type\n");
+                       return -ENOMSG;
+               }
+               cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]);
+               cb->args[3] = cmd + 1;
+       }
+
+       /* in case multiple accesses to the device happens */
+       mutex_lock(&priv->mutex);
+       switch (cmd) {
+       case IWL_TM_CMD_APP2DEV_READ_TRACE:
+               IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
+               result = iwl_testmode_trace_dump(hw, tb, skb, cb);
+               break;
+       default:
+               result = -EINVAL;
+               break;
+       }
+
+       mutex_unlock(&priv->mutex);
+       return result;
+}
index a88085e..160911a 100644 (file)
@@ -166,7 +166,8 @@ enum iwl_tm_attr_t {
         * IWL_TM_ATTR_MEM_TRACE_ADDR for the trace address
         */
        IWL_TM_ATTR_TRACE_ADDR,
-       IWL_TM_ATTR_TRACE_DATA,
+       IWL_TM_ATTR_TRACE_SIZE,
+       IWL_TM_ATTR_TRACE_DUMP,
 
        /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_FIXRATE_REQ,
         * The mandatory fields are:
@@ -178,8 +179,10 @@ enum iwl_tm_attr_t {
 };
 
 /* uCode trace buffer */
-#define TRACE_BUFF_SIZE                0x20000
+#define TRACE_BUFF_SIZE_MAX    0x200000
+#define TRACE_BUFF_SIZE_MIN    0x20000
+#define TRACE_BUFF_SIZE_DEF    TRACE_BUFF_SIZE_MIN
 #define TRACE_BUFF_PADD                0x2000
-#define TRACE_TOTAL_SIZE       (TRACE_BUFF_SIZE + TRACE_BUFF_PADD)
+#define TRACE_CHUNK_SIZE       (PAGE_SIZE - 1024)
 
 #endif
index 1084fe0..fd8aee9 100644 (file)
@@ -128,7 +128,6 @@ static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
 static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
                             struct iwl_tfd *tfd)
 {
-       struct pci_dev *dev = priv->pci_dev;
        int i;
        int num_tbs;
 
@@ -143,15 +142,15 @@ static void iwlagn_unmap_tfd(struct iwl_priv *priv, struct iwl_cmd_meta *meta,
 
        /* Unmap tx_cmd */
        if (num_tbs)
-               pci_unmap_single(dev,
+               dma_unmap_single(priv->bus.dev,
                                dma_unmap_addr(meta, mapping),
                                dma_unmap_len(meta, len),
-                               PCI_DMA_BIDIRECTIONAL);
+                               DMA_BIDIRECTIONAL);
 
        /* Unmap chunks, if any. */
        for (i = 1; i < num_tbs; i++)
-               pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
-                               iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
+               dma_unmap_single(priv->bus.dev, iwl_tfd_tb_get_addr(tfd, i),
+                               iwl_tfd_tb_get_len(tfd, i), DMA_TO_DEVICE);
 }
 
 /**
@@ -266,7 +265,7 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
 {
        struct iwl_tx_queue *txq = &priv->txq[txq_id];
-       struct device *dev = &priv->pci_dev->dev;
+       struct device *dev = priv->bus.dev;
        int i;
 
        iwl_tx_queue_unmap(priv, txq_id);
@@ -310,10 +309,10 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
                i = get_cmd_index(q, q->read_ptr);
 
                if (txq->meta[i].flags & CMD_MAPPED) {
-                       pci_unmap_single(priv->pci_dev,
+                       dma_unmap_single(priv->bus.dev,
                                         dma_unmap_addr(&txq->meta[i], mapping),
                                         dma_unmap_len(&txq->meta[i], len),
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        DMA_BIDIRECTIONAL);
                        txq->meta[i].flags = 0;
                }
 
@@ -332,7 +331,7 @@ void iwl_cmd_queue_unmap(struct iwl_priv *priv)
 void iwl_cmd_queue_free(struct iwl_priv *priv)
 {
        struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
-       struct device *dev = &priv->pci_dev->dev;
+       struct device *dev = priv->bus.dev;
        int i;
 
        iwl_cmd_queue_unmap(priv);
@@ -434,7 +433,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
 static int iwl_tx_queue_alloc(struct iwl_priv *priv,
                              struct iwl_tx_queue *txq, u32 id)
 {
-       struct device *dev = &priv->pci_dev->dev;
+       struct device *dev = priv->bus.dev;
        size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
 
        /* Driver private data, only for Tx (not command) queues,
@@ -456,7 +455,7 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
        txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
                                       GFP_KERNEL);
        if (!txq->tfds) {
-               IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
+               IWL_ERR(priv, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
                goto error;
        }
        txq->q.id = id;
@@ -677,9 +676,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                        le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
                        q->write_ptr, idx, priv->cmd_queue);
 
-       phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-                                  copy_size, PCI_DMA_BIDIRECTIONAL);
-       if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) {
+       phys_addr = dma_map_single(priv->bus.dev, &out_cmd->hdr, copy_size,
+                               DMA_BIDIRECTIONAL);
+       if (unlikely(dma_mapping_error(priv->bus.dev, phys_addr))) {
                idx = -ENOMEM;
                goto out;
        }
@@ -699,9 +698,9 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                        continue;
                if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
                        continue;
-               phys_addr = pci_map_single(priv->pci_dev, (void *)cmd->data[i],
-                                          cmd->len[i], PCI_DMA_TODEVICE);
-               if (pci_dma_mapping_error(priv->pci_dev, phys_addr)) {
+               phys_addr = dma_map_single(priv->bus.dev, (void *)cmd->data[i],
+                                          cmd->len[i], DMA_TO_DEVICE);
+               if (dma_mapping_error(priv->bus.dev, phys_addr)) {
                        iwlagn_unmap_tfd(priv, out_meta,
                                         &txq->tfds[q->write_ptr]);
                        idx = -ENOMEM;
index 224e985..387786e 100644 (file)
@@ -892,6 +892,37 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
 
 }
 
+static struct mmc_host *reset_host;
+
+static void if_sdio_reset_card_worker(struct work_struct *work)
+{
+       /*
+        * The actual reset operation must be run outside of lbs_thread. This
+        * is because mmc_remove_host() will cause the device to be instantly
+        * destroyed, and the libertas driver then needs to end lbs_thread,
+        * leading to a deadlock.
+        *
+        * We run it in a workqueue totally independent from the if_sdio_card
+        * instance for that reason.
+        */
+
+       pr_info("Resetting card...");
+       mmc_remove_host(reset_host);
+       mmc_add_host(reset_host);
+}
+static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker);
+
+static void if_sdio_reset_card(struct lbs_private *priv)
+{
+       struct if_sdio_card *card = priv->card;
+
+       if (work_pending(&card_reset_work))
+               return;
+
+       reset_host = card->func->card->host;
+       schedule_work(&card_reset_work);
+}
+
 /*******************************************************************/
 /* SDIO callbacks                                                  */
 /*******************************************************************/
@@ -1065,6 +1096,7 @@ static int if_sdio_probe(struct sdio_func *func,
        priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
        priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
        priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
+       priv->reset_card = if_sdio_reset_card;
 
        sdio_claim_host(func);
 
@@ -1301,6 +1333,8 @@ static void __exit if_sdio_exit_module(void)
        /* Set the flag as user is removing this module. */
        user_rmmod = 1;
 
+       cancel_work_sync(&card_reset_work);
+
        sdio_unregister_driver(&if_sdio_driver);
 
        lbs_deb_leave(LBS_DEB_SDIO);
index 4fa0be9..e0286cf 100644 (file)
@@ -1034,7 +1034,6 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
 static int if_spi_init_card(struct if_spi_card *card)
 {
        struct lbs_private *priv = card->priv;
-       struct spi_device *spi = card->spi;
        int err, i;
        u32 scratch;
        const struct firmware *helper = NULL;
@@ -1082,8 +1081,9 @@ static int if_spi_init_card(struct if_spi_card *card)
                                "attached to SPI bus_num %d, chip_select %d. "
                                "spi->max_speed_hz=%d\n",
                                card->card_id, card->card_rev,
-                               spi->master->bus_num, spi->chip_select,
-                               spi->max_speed_hz);
+                               card->spi->master->bus_num,
+                               card->spi->chip_select,
+                               card->spi->max_speed_hz);
                err = if_spi_prog_helper_firmware(card, helper);
                if (err)
                        goto out;
index 916183d..34bba52 100644 (file)
@@ -185,13 +185,12 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
  *
  * Handling includes changing the header fields into CPU format.
  */
-int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
+int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
+                       struct mwifiex_ds_11n_tx_cfg *tx_cfg)
 {
-       struct mwifiex_ds_11n_tx_cfg *tx_cfg;
        struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg;
 
-       if (data_buf) {
-               tx_cfg = (struct mwifiex_ds_11n_tx_cfg *) data_buf;
+       if (tx_cfg) {
                tx_cfg->tx_htcap = le16_to_cpu(htcfg->ht_tx_cap);
                tx_cfg->tx_htinfo = le16_to_cpu(htcfg->ht_tx_info);
        }
@@ -208,11 +207,10 @@ int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf)
  */
 int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
                             struct host_cmd_ds_command *cmd, int cmd_action,
-                            void *data_buf)
+                            u16 *buf_size)
 {
        struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf;
        u16 action = (u16) cmd_action;
-       u16 buf_size = *((u16 *) data_buf);
 
        cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF);
        cmd->size =
@@ -220,8 +218,8 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
        tx_buf->action = cpu_to_le16(action);
        switch (action) {
        case HostCmd_ACT_GEN_SET:
-               dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", buf_size);
-               tx_buf->buff_size = cpu_to_le16(buf_size);
+               dev_dbg(priv->adapter->dev, "cmd: set tx_buf=%d\n", *buf_size);
+               tx_buf->buff_size = cpu_to_le16(*buf_size);
                break;
        case HostCmd_ACT_GEN_GET:
        default:
@@ -240,13 +238,12 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
-                               int cmd_action, void *data_buf)
+                               int cmd_action,
+                               struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl)
 {
        struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
                &cmd->params.amsdu_aggr_ctrl;
        u16 action = (u16) cmd_action;
-       struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl =
-               (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
 
        cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL);
        cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl)
@@ -272,15 +269,13 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
  * Handling includes changing the header fields into CPU format.
  */
 int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
-                               void *data_buf)
+                               struct mwifiex_ds_11n_amsdu_aggr_ctrl
+                               *amsdu_aggr_ctrl)
 {
-       struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl;
        struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl =
                &resp->params.amsdu_aggr_ctrl;
 
-       if (data_buf) {
-               amsdu_aggr_ctrl =
-                       (struct mwifiex_ds_11n_amsdu_aggr_ctrl *) data_buf;
+       if (amsdu_aggr_ctrl) {
                amsdu_aggr_ctrl->enable = le16_to_cpu(amsdu_ctrl->enable);
                amsdu_aggr_ctrl->curr_buf_size =
                        le16_to_cpu(amsdu_ctrl->curr_buf_size);
@@ -296,12 +291,10 @@ int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
  *      - Setting HT Tx capability and HT Tx information fields
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
-                       u16 cmd_action, void *data_buf)
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+                       struct mwifiex_ds_11n_tx_cfg *txcfg)
 {
        struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg;
-       struct mwifiex_ds_11n_tx_cfg *txcfg =
-               (struct mwifiex_ds_11n_tx_cfg *) data_buf;
 
        cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG);
        cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN);
index a4390a1..90b421e 100644 (file)
@@ -29,9 +29,9 @@ int mwifiex_ret_11n_delba(struct mwifiex_private *priv,
 int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv,
                              struct host_cmd_ds_command *resp);
 int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp,
-                       void *data_buf);
-int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd,
-                       u16 cmd_action, void *data_buf);
+                       struct mwifiex_ds_11n_tx_cfg *tx_cfg);
+int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action,
+                       struct mwifiex_ds_11n_tx_cfg *txcfg);
 
 int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv,
                               struct mwifiex_bssdescriptor *bss_desc,
@@ -62,12 +62,14 @@ int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv,
 int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
                               struct mwifiex_ds_tx_ba_stream_tbl *buf);
 int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp,
-                               void *data_buf);
+                               struct mwifiex_ds_11n_amsdu_aggr_ctrl
+                               *amsdu_aggr_ctrl);
 int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
                             struct host_cmd_ds_command *cmd,
-                            int cmd_action, void *data_buf);
+                            int cmd_action, u16 *buf_size);
 int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
-                               int cmd_action, void *data_buf);
+                               int cmd_action,
+                               struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
 
 /*
  * This function checks whether AMPDU is allowed or not for a particular TID.
index e5dfdc3..7aa9aa0 100644 (file)
@@ -328,13 +328,12 @@ int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf)
  */
 int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
                                  struct host_cmd_ds_command *cmd,
-                                 void *data_buf)
+                                 struct host_cmd_ds_11n_addba_req
+                                 *cmd_addba_req)
 {
        struct host_cmd_ds_11n_addba_rsp *add_ba_rsp =
                (struct host_cmd_ds_11n_addba_rsp *)
                &cmd->params.add_ba_rsp;
-       struct host_cmd_ds_11n_addba_req *cmd_addba_req =
-               (struct host_cmd_ds_11n_addba_req *) data_buf;
        u8 tid;
        int win_size;
        uint16_t block_ack_param_set;
index f3ca8c8..033c8ad 100644 (file)
@@ -52,8 +52,9 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv,
 int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd,
                          void *data_buf);
 int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv,
-                                 struct host_cmd_ds_command
-                                 *cmd, void *data_buf);
+                                 struct host_cmd_ds_command *cmd,
+                                 struct host_cmd_ds_11n_addba_req
+                                 *cmd_addba_req);
 int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd,
                              void *data_buf);
 void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv);
index cd89fed..b5352af 100644 (file)
@@ -104,13 +104,11 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
  * main thread.
  */
 static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd, void *data_buf)
+                               struct host_cmd_ds_command *cmd,
+                               struct mwifiex_ds_misc_cmd *pcmd_ptr)
 {
-       struct mwifiex_ds_misc_cmd *pcmd_ptr =
-               (struct mwifiex_ds_misc_cmd *) data_buf;
-
        /* Copy the HOST command to command buffer */
-       memcpy((void *) cmd, pcmd_ptr->cmd, pcmd_ptr->len);
+       memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len);
        dev_dbg(priv->adapter->dev, "cmd: host cmd size = %d\n", pcmd_ptr->len);
        return 0;
 }
@@ -707,15 +705,14 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
 
        if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) {
                /* Copy original response back to response buffer */
-               struct mwifiex_ds_misc_cmd *hostcmd = NULL;
+               struct mwifiex_ds_misc_cmd *hostcmd;
                uint16_t size = le16_to_cpu(resp->size);
                dev_dbg(adapter->dev, "info: host cmd resp size = %d\n", size);
                size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER);
                if (adapter->curr_cmd->data_buf) {
-                       hostcmd = (struct mwifiex_ds_misc_cmd *)
-                                               adapter->curr_cmd->data_buf;
+                       hostcmd = adapter->curr_cmd->data_buf;
                        hostcmd->len = size;
-                       memcpy(hostcmd->cmd, (void *) resp, size);
+                       memcpy(hostcmd->cmd, resp, size);
                }
        }
        orig_cmdresp_no = le16_to_cpu(resp->command);
@@ -1155,7 +1152,7 @@ EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp);
 int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *cmd,
                               u16 cmd_action, uint16_t ps_bitmap,
-                              void *data_buf)
+                              struct mwifiex_ds_auto_ds *auto_ds)
 {
        struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh =
                &cmd->params.psmode_enh;
@@ -1218,9 +1215,8 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
                                        sizeof(struct mwifiex_ie_types_header));
                        cmd_size += sizeof(*auto_ds_tlv);
                        tlv += sizeof(*auto_ds_tlv);
-                       if (data_buf)
-                               idletime = ((struct mwifiex_ds_auto_ds *)
-                                            data_buf)->idle_time;
+                       if (auto_ds)
+                               idletime = auto_ds->idle_time;
                        dev_dbg(priv->adapter->dev,
                                        "cmd: PS Command: Enter Auto Deep Sleep\n");
                        auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime);
@@ -1239,7 +1235,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
  */
 int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *resp,
-                              void *data_buf)
+                              struct mwifiex_ds_pm_cfg *pm_cfg)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_802_11_ps_mode_enh *ps_mode =
@@ -1282,10 +1278,8 @@ int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
 
                dev_dbg(adapter->dev, "cmd: ps_bitmap=%#x\n", ps_bitmap);
 
-               if (data_buf) {
+               if (pm_cfg) {
                        /* This section is for get power save mode */
-                       struct mwifiex_ds_pm_cfg *pm_cfg =
-                                       (struct mwifiex_ds_pm_cfg *)data_buf;
                        if (ps_bitmap & BITMAP_STA_PS)
                                pm_cfg->param.ps_mode = 1;
                        else
index 5eab3dc..644e2e4 100644 (file)
@@ -364,10 +364,9 @@ static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv,
  */
 int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
                                 struct host_cmd_ds_command *cmd,
-                                void *data_buf)
+                                struct mwifiex_bssdescriptor *bss_desc)
 {
        struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate;
-       struct mwifiex_bssdescriptor *bss_desc;
        struct mwifiex_ie_types_ssid_param_set *ssid_tlv;
        struct mwifiex_ie_types_phy_param_set *phy_tlv;
        struct mwifiex_ie_types_ss_param_set *ss_tlv;
@@ -380,7 +379,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
        u8 *pos;
        int rsn_ie_len = 0;
 
-       bss_desc = (struct mwifiex_bssdescriptor *) data_buf;
        pos = (u8 *) assoc;
 
        mwifiex_cfg_tx_buf(priv, bss_desc);
@@ -748,7 +746,8 @@ done:
  */
 int
 mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
-                               struct host_cmd_ds_command *cmd, void *data_buf)
+                               struct host_cmd_ds_command *cmd,
+                               struct mwifiex_802_11_ssid *req_ssid)
 {
        int rsn_ie_len = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
@@ -786,20 +785,15 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
 
        memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN);
 
-       memcpy(adhoc_start->ssid,
-              ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
-              ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+       memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len);
 
        dev_dbg(adapter->dev, "info: ADHOC_S_CMD: SSID = %s\n",
                                adhoc_start->ssid);
 
        memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN);
-       memcpy(bss_desc->ssid.ssid,
-              ((struct mwifiex_802_11_ssid *) data_buf)->ssid,
-              ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len);
+       memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len);
 
-       bss_desc->ssid.ssid_len =
-               ((struct mwifiex_802_11_ssid *) data_buf)->ssid_len;
+       bss_desc->ssid.ssid_len = req_ssid->ssid_len;
 
        /* Set the BSS mode */
        adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS;
@@ -1036,13 +1030,12 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
  */
 int
 mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
-                              struct host_cmd_ds_command *cmd, void *data_buf)
+                              struct host_cmd_ds_command *cmd,
+                              struct mwifiex_bssdescriptor *bss_desc)
 {
        int rsn_ie_len = 0;
        struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join =
                &cmd->params.adhoc_join;
-       struct mwifiex_bssdescriptor *bss_desc =
-               (struct mwifiex_bssdescriptor *) data_buf;
        struct mwifiex_ie_types_chan_list_param_set *chan_tlv;
        u32 cmd_append_size = 0;
        u16 tmp_cap;
index 4f43443..e5fc53d 100644 (file)
@@ -26,9 +26,6 @@
 
 const char driver_version[] = "mwifiex " VERSION " (%s) ";
 
-struct mwifiex_adapter *g_adapter;
-EXPORT_SYMBOL_GPL(g_adapter);
-
 static struct mwifiex_bss_attr mwifiex_bss_sta[] = {
        {MWIFIEX_BSS_TYPE_STA, MWIFIEX_DATA_FRAME_TYPE_ETH_II, true, 0, 0},
 };
@@ -60,7 +57,8 @@ static struct mwifiex_drv_mode mwifiex_drv_mode_tbl[] = {
  * proper cleanup before exiting.
  */
 static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
-                           struct mwifiex_drv_mode *drv_mode_ptr)
+                           struct mwifiex_drv_mode *drv_mode_ptr,
+                           void **padapter)
 {
        struct mwifiex_adapter *adapter;
        int i;
@@ -69,7 +67,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops,
        if (!adapter)
                return -ENOMEM;
 
-       g_adapter = adapter;
+       *padapter = adapter;
        adapter->card = card;
 
        /* Save interface specific operations in adapter */
@@ -324,7 +322,7 @@ exit_main_proc:
  * and initializing the private structures.
  */
 static int
-mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
+mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops, void **padapter)
 {
        int i;
        struct mwifiex_drv_mode *drv_mode_ptr;
@@ -343,7 +341,7 @@ mwifiex_init_sw(void *card, struct mwifiex_if_ops *if_ops)
                return -1;
        }
 
-       if (mwifiex_register(card, if_ops, drv_mode_ptr))
+       if (mwifiex_register(card, if_ops, drv_mode_ptr, padapter))
                return -1;
 
        return 0;
@@ -555,7 +553,7 @@ static int
 mwifiex_set_mac_address(struct net_device *dev, void *addr)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
-       struct sockaddr *hw_addr = (struct sockaddr *) addr;
+       struct sockaddr *hw_addr = addr;
        int ret;
 
        memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN);
@@ -855,13 +853,11 @@ mwifiex_add_card(void *card, struct semaphore *sem,
        if (down_interruptible(sem))
                goto exit_sem_err;
 
-       if (mwifiex_init_sw(card, if_ops)) {
+       if (mwifiex_init_sw(card, if_ops, (void **)&adapter)) {
                pr_err("%s: software init failed\n", __func__);
                goto err_init_sw;
        }
 
-       adapter = g_adapter;
-
        adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING;
        adapter->surprise_removed = false;
        init_waitqueue_head(&adapter->init_wait_q);
index 57b183a..03691c0 100644 (file)
@@ -39,7 +39,6 @@
 #include "fw.h"
 
 extern const char driver_version[];
-extern struct mwifiex_adapter *g_adapter;
 
 enum {
        MWIFIEX_ASYNC_CMD,
@@ -737,10 +736,10 @@ void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *,
 int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *cmd,
                               u16 cmd_action, uint16_t ps_bitmap,
-                              void *data_buf);
+                              struct mwifiex_ds_auto_ds *auto_ds);
 int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *resp,
-                              void *data_buf);
+                              struct mwifiex_ds_pm_cfg *pm_cfg);
 void mwifiex_process_hs_config(struct mwifiex_adapter *adapter);
 void mwifiex_hs_activated_event(struct mwifiex_private *priv,
                                        u8 activated);
@@ -752,7 +751,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
                            u16 cmd_action, u32 cmd_oid,
                            void *data_buf, void *cmd_buf);
 int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
-                               void *cmd_buf);
+                               struct host_cmd_ds_command *resp);
 int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
                                  struct sk_buff *skb);
 int mwifiex_process_sta_event(struct mwifiex_private *);
@@ -761,7 +760,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
 int mwifiex_scan_networks(struct mwifiex_private *priv,
                          const struct mwifiex_user_scan_cfg *user_scan_in);
 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
-                           void *data_buf);
+                           struct mwifiex_scan_cmd_config *scan_cfg);
 void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
                            struct cmd_ctrl_node *cmd_node);
 int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
@@ -778,8 +777,8 @@ s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
 int mwifiex_associate(struct mwifiex_private *priv,
                      struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
-                                struct host_cmd_ds_command
-                                *cmd, void *data_buf);
+                                struct host_cmd_ds_command *cmd,
+                                struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
                                 struct host_cmd_ds_command *resp);
 void mwifiex_reset_connect_state(struct mwifiex_private *priv);
@@ -792,10 +791,10 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv,
                       struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
                                    struct host_cmd_ds_command *cmd,
-                                   void *data_buf);
+                                   struct mwifiex_802_11_ssid *req_ssid);
 int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                                   struct host_cmd_ds_command *cmd,
-                                  void *data_buf);
+                                  struct mwifiex_bssdescriptor *bss_desc);
 int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
                              struct host_cmd_ds_command *resp);
 int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd);
index 5c22860..6f88c8a 100644 (file)
@@ -2357,12 +2357,10 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
  *      - Setting command ID, and proper size
  *      - Ensuring correct endian-ness
  */
-int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, void *data_buf)
+int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
+                           struct mwifiex_scan_cmd_config *scan_cfg)
 {
        struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
-       struct mwifiex_scan_cmd_config *scan_cfg;
-
-       scan_cfg = (struct mwifiex_scan_cmd_config *) data_buf;
 
        /* Set fixed field variables in scan command */
        scan_cmd->bss_mode = scan_cfg->bss_mode;
index 4327b6d..711fa68 100644 (file)
 
 #define SDIO_VERSION   "1.0"
 
+/* The mwifiex_sdio_remove() callback function is called when
+ * user removes this module from kernel space or ejects
+ * the card from the slot. The driver handles these 2 cases
+ * differently.
+ * If the user is removing the module, the few commands (FUNC_SHUTDOWN,
+ * HS_CANCEL etc.) are sent to the firmware.
+ * If the card is removed, there is no need to send these command.
+ *
+ * The variable 'user_rmmod' is used to distinguish these two
+ * scenarios. This flag is initialized as FALSE in case the card
+ * is removed, and will be set to TRUE for module removal when
+ * module_exit function is called.
+ */
+static u8 user_rmmod;
+
 static struct mwifiex_if_ops sdio_ops;
 
 static struct semaphore add_remove_card_sem;
 
+static int mwifiex_sdio_resume(struct device *dev);
+
 /*
  * SDIO probe.
  *
@@ -93,17 +110,36 @@ static void
 mwifiex_sdio_remove(struct sdio_func *func)
 {
        struct sdio_mmc_card *card;
+       struct mwifiex_adapter *adapter;
+       int i;
 
        pr_debug("info: SDIO func num=%d\n", func->num);
 
-       if (func) {
-               card = sdio_get_drvdata(func);
-               if (card) {
-                       mwifiex_remove_card(card->adapter,
-                                       &add_remove_card_sem);
-                       kfree(card);
-               }
+       card = sdio_get_drvdata(func);
+       if (!card)
+               return;
+
+       adapter = card->adapter;
+       if (!adapter || !adapter->priv_num)
+               return;
+
+       if (user_rmmod) {
+               if (adapter->is_suspended)
+                       mwifiex_sdio_resume(adapter->dev);
+
+               for (i = 0; i < adapter->priv_num; i++)
+                       if ((GET_BSS_ROLE(adapter->priv[i]) ==
+                                               MWIFIEX_BSS_ROLE_STA) &&
+                                       adapter->priv[i]->media_connected)
+                               mwifiex_deauthenticate(adapter->priv[i], NULL);
+
+               mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
+                                               MWIFIEX_BSS_ROLE_ANY),
+                                        MWIFIEX_FUNC_SHUTDOWN);
        }
+
+       mwifiex_remove_card(card->adapter, &add_remove_card_sem);
+       kfree(card);
 }
 
 /*
@@ -1696,6 +1732,9 @@ mwifiex_sdio_init_module(void)
 {
        sema_init(&add_remove_card_sem, 1);
 
+       /* Clear the flag in case user removes the card. */
+       user_rmmod = 0;
+
        return sdio_register_driver(&mwifiex_sdio);
 }
 
@@ -1711,32 +1750,12 @@ mwifiex_sdio_init_module(void)
 static void
 mwifiex_sdio_cleanup_module(void)
 {
-       struct mwifiex_adapter *adapter = g_adapter;
-       int i;
-
-       if (down_interruptible(&add_remove_card_sem))
-               goto exit_sem_err;
-
-       if (!adapter || !adapter->priv_num)
-               goto exit;
-
-       if (adapter->is_suspended)
-               mwifiex_sdio_resume(adapter->dev);
-
-       for (i = 0; i < adapter->priv_num; i++)
-               if ((GET_BSS_ROLE(adapter->priv[i]) == MWIFIEX_BSS_ROLE_STA) &&
-                   adapter->priv[i]->media_connected)
-                       mwifiex_deauthenticate(adapter->priv[i], NULL);
-
-       if (!adapter->surprise_removed)
-               mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter,
-                                                         MWIFIEX_BSS_ROLE_ANY),
-                                        MWIFIEX_FUNC_SHUTDOWN);
+       if (!down_interruptible(&add_remove_card_sem))
+               up(&add_remove_card_sem);
 
-exit:
-       up(&add_remove_card_sem);
+       /* Set the flag as user is removing this module. */
+       user_rmmod = 1;
 
-exit_sem_err:
        sdio_unregister_driver(&mwifiex_sdio);
 }
 
index 8af3a78..d85a0a6 100644 (file)
@@ -67,10 +67,9 @@ mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv,
  */
 static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
                                   struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, void *data_buf)
+                                  u16 cmd_action, u16 *action)
 {
        struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl;
-       u16 action = *((u16 *) data_buf);
 
        if (cmd_action != HostCmd_ACT_GEN_SET) {
                dev_err(priv->adapter->dev,
@@ -81,7 +80,7 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
        cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
        cmd->size =
                cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN);
-       mac_ctrl->action = cpu_to_le16(action);
+       mac_ctrl->action = cpu_to_le16(*action);
 
        return 0;
 }
@@ -104,10 +103,9 @@ static int mwifiex_cmd_mac_control(struct mwifiex_private *priv,
 static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
                                       struct host_cmd_ds_command *cmd,
                                       u16 cmd_action, u32 cmd_oid,
-                                      void *data_buf)
+                                      u32 *ul_temp)
 {
        struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib;
-       u32 ul_temp;
 
        dev_dbg(priv->adapter->dev, "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
@@ -127,9 +125,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
                if (cmd_action == HostCmd_ACT_GEN_SET) {
                        snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
                        snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-                       ul_temp = *((u32 *) data_buf);
                        *((__le16 *) (snmp_mib->value)) =
-                               cpu_to_le16((u16) ul_temp);
+                               cpu_to_le16((u16) *ul_temp);
                        cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
                                + sizeof(u16));
                }
@@ -139,9 +136,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
                if (cmd_action == HostCmd_ACT_GEN_SET) {
                        snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
                        snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-                       ul_temp = *((u32 *) data_buf);
                        *(__le16 *) (snmp_mib->value) =
-                               cpu_to_le16((u16) ul_temp);
+                               cpu_to_le16((u16) *ul_temp);
                        cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
                                + sizeof(u16));
                }
@@ -152,9 +148,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
                if (cmd_action == HostCmd_ACT_GEN_SET) {
                        snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
                        snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-                       ul_temp = (*(u32 *) data_buf);
                        *((__le16 *) (snmp_mib->value)) =
-                               cpu_to_le16((u16) ul_temp);
+                               cpu_to_le16((u16) *ul_temp);
                        cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
                                + sizeof(u16));
                }
@@ -164,9 +159,8 @@ static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv,
                if (cmd_action == HostCmd_ACT_GEN_SET) {
                        snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET);
                        snmp_mib->buf_size = cpu_to_le16(sizeof(u16));
-                       ul_temp = *(u32 *) data_buf;
                        *((__le16 *) (snmp_mib->value)) =
-                               cpu_to_le16((u16) ul_temp);
+                               cpu_to_le16((u16) *ul_temp);
                        cmd->size = cpu_to_le16(le16_to_cpu(cmd->size)
                                + sizeof(u16));
                }
@@ -209,13 +203,11 @@ mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd)
  */
 static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
                                   struct host_cmd_ds_command *cmd,
-                                  u16 cmd_action, void *data_buf)
+                                  u16 cmd_action, u16 *pbitmap_rates)
 {
        struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg;
        struct mwifiex_rate_scope *rate_scope;
        struct mwifiex_rate_drop_pattern *rate_drop;
-       u16 *pbitmap_rates = (u16 *) data_buf;
-
        u32 i;
 
        cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG);
@@ -272,10 +264,10 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
-                                   u16 cmd_action, void *data_buf)
+                                   u16 cmd_action,
+                                   struct host_cmd_ds_txpwr_cfg *txp)
 {
        struct mwifiex_types_power_group *pg_tlv;
-       struct host_cmd_ds_txpwr_cfg *txp;
        struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg;
 
        cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG);
@@ -283,12 +275,11 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
                cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg));
        switch (cmd_action) {
        case HostCmd_ACT_GEN_SET:
-               txp = (struct host_cmd_ds_txpwr_cfg *) data_buf;
                if (txp->mode) {
                        pg_tlv = (struct mwifiex_types_power_group
-                                 *) ((unsigned long) data_buf +
+                                 *) ((unsigned long) txp +
                                     sizeof(struct host_cmd_ds_txpwr_cfg));
-                       memmove(cmd_txp_cfg, data_buf,
+                       memmove(cmd_txp_cfg, txp,
                                sizeof(struct host_cmd_ds_txpwr_cfg) +
                                sizeof(struct mwifiex_types_power_group) +
                                pg_tlv->length);
@@ -300,8 +291,7 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
                                  sizeof(struct mwifiex_types_power_group) +
                                  pg_tlv->length);
                } else {
-                       memmove(cmd_txp_cfg, data_buf,
-                               sizeof(struct host_cmd_ds_txpwr_cfg));
+                       memmove(cmd_txp_cfg, txp, sizeof(*txp));
                }
                cmd_txp_cfg->action = cpu_to_le16(cmd_action);
                break;
@@ -322,22 +312,23 @@ static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd,
  *        (as required)
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
-                                    struct host_cmd_ds_command *cmd,
-                                    u16 cmd_action,
-                                    struct mwifiex_hs_config_param *data_buf)
+static int
+mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
+                         struct host_cmd_ds_command *cmd,
+                         u16 cmd_action,
+                         struct mwifiex_hs_config_param *hscfg_param)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg;
        u16 hs_activate = false;
 
-       if (data_buf == NULL)
+       if (!hscfg_param)
                /* New Activate command */
                hs_activate = true;
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH);
 
        if (!hs_activate &&
-           (data_buf->conditions
+           (hscfg_param->conditions
            != cpu_to_le32(HOST_SLEEP_CFG_CANCEL))
            && ((adapter->arp_filter_size > 0)
                && (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) {
@@ -359,9 +350,9 @@ static int mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv,
                hs_cfg->params.hs_activate.resp_ctrl = RESP_NEEDED;
        } else {
                hs_cfg->action = cpu_to_le16(HS_CONFIGURE);
-               hs_cfg->params.hs_config.conditions = data_buf->conditions;
-               hs_cfg->params.hs_config.gpio = data_buf->gpio;
-               hs_cfg->params.hs_config.gap = data_buf->gap;
+               hs_cfg->params.hs_config.conditions = hscfg_param->conditions;
+               hs_cfg->params.hs_config.gpio = hscfg_param->gpio;
+               hs_cfg->params.hs_config.gap = hscfg_param->gap;
                dev_dbg(adapter->dev,
                        "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n",
                       hs_cfg->params.hs_config.conditions,
@@ -405,11 +396,11 @@ static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv,
  *      - Setting MAC multicast address
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
-                                        u16 cmd_action, void *data_buf)
+static int
+mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
+                             u16 cmd_action,
+                             struct mwifiex_multicast_list *mcast_list)
 {
-       struct mwifiex_multicast_list *mcast_list =
-               (struct mwifiex_multicast_list *) data_buf;
        struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr;
 
        cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) +
@@ -435,7 +426,7 @@ static int mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd,
  */
 static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
                                             struct host_cmd_ds_command *cmd,
-                                            void *data_buf)
+                                            u8 *mac)
 {
        struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth;
 
@@ -444,7 +435,7 @@ static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv,
                                + S_DS_GEN);
 
        /* Set AP MAC address */
-       memcpy(deauth->mac_addr, (u8 *) data_buf, ETH_ALEN);
+       memcpy(deauth->mac_addr, mac, ETH_ALEN);
 
        dev_dbg(priv->adapter->dev, "cmd: Deauth: %pM\n", deauth->mac_addr);
 
@@ -543,15 +534,14 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv,
  *        encryption (TKIP, AES) (as required)
  *      - Ensuring correct endian-ness
  */
-static int mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
-                                          struct host_cmd_ds_command *cmd,
-                                          u16 cmd_action,
-                                          u32 cmd_oid, void *data_buf)
+static int
+mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
+                               struct host_cmd_ds_command *cmd,
+                               u16 cmd_action, u32 cmd_oid,
+                               struct mwifiex_ds_encrypt_key *enc_key)
 {
        struct host_cmd_ds_802_11_key_material *key_material =
                &cmd->params.key_material;
-       struct mwifiex_ds_encrypt_key *enc_key =
-               (struct mwifiex_ds_encrypt_key *) data_buf;
        u16 key_param_len = 0;
        int ret = 0;
        const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -741,7 +731,7 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
  */
 static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
                                         struct host_cmd_ds_command *cmd,
-                                        u16 cmd_action, void *data_buf)
+                                        u16 cmd_action, u16 *channel)
 {
        struct host_cmd_ds_802_11_rf_channel *rf_chan =
                &cmd->params.rf_channel;
@@ -759,7 +749,7 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
 
                rf_type = le16_to_cpu(rf_chan->rf_type);
                SET_SECONDARYCHAN(rf_type, priv->adapter->chan_offset);
-               rf_chan->current_channel = cpu_to_le16(*((u16 *) data_buf));
+               rf_chan->current_channel = cpu_to_le16(*channel);
        }
        rf_chan->action = cpu_to_le16(cmd_action);
        return 0;
@@ -774,11 +764,10 @@ static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
  *      - Ensuring correct endian-ness
  */
 static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
-                                             u16 cmd_action, void *data_buf)
+                                             u16 cmd_action, u16 *enable)
 {
        struct host_cmd_ds_802_11_ibss_status *ibss_coal =
                &(cmd->params.ibss_coalescing);
-       u16 enable = 0;
 
        cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS);
        cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) +
@@ -788,9 +777,8 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
 
        switch (cmd_action) {
        case HostCmd_ACT_GEN_SET:
-               if (data_buf != NULL)
-                       enable = *(u16 *) data_buf;
-               ibss_coal->enable = cpu_to_le16(enable);
+               if (enable)
+                       ibss_coal->enable = cpu_to_le16(*enable);
                break;
 
                /* In other case.. Nothing to do */
@@ -822,9 +810,8 @@ static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd,
 static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
                                  u16 cmd_action, void *data_buf)
 {
-       struct mwifiex_ds_reg_rw *reg_rw;
+       struct mwifiex_ds_reg_rw *reg_rw = data_buf;
 
-       reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
        switch (le16_to_cpu(cmd->command)) {
        case HostCmd_CMD_MAC_REG_ACCESS:
        {
@@ -893,8 +880,7 @@ static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd,
        }
        case HostCmd_CMD_802_11_EEPROM_ACCESS:
        {
-               struct mwifiex_ds_read_eeprom *rd_eeprom =
-                       (struct mwifiex_ds_read_eeprom *) data_buf;
+               struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf;
                struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom =
                        (struct host_cmd_ds_802_11_eeprom_access *)
                        &cmd->params.eeprom;
@@ -923,8 +909,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
                            u16 cmd_action, u32 cmd_oid,
                            void *data_buf, void *cmd_buf)
 {
-       struct host_cmd_ds_command *cmd_ptr =
-               (struct host_cmd_ds_command *) cmd_buf;
+       struct host_cmd_ds_command *cmd_ptr = cmd_buf;
        int ret = 0;
 
        /* Prepare command */
@@ -1181,7 +1166,7 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta)
        /* Send request to firmware */
        ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL,
                                     HostCmd_ACT_GEN_SET, 0,
-                                    (void *) &amsdu_aggr_ctrl);
+                                    &amsdu_aggr_ctrl);
        if (ret)
                return -1;
        /* MAC Control must be the last command in init_fw */
index d08f764..ad64c87 100644 (file)
@@ -120,11 +120,10 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
                                        struct host_cmd_ds_command *resp,
-                                       void *data_buf)
+                                       struct mwifiex_ds_get_signal *signal)
 {
        struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp =
                &resp->params.rssi_info_rsp;
-       struct mwifiex_ds_get_signal *signal;
 
        priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last);
        priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last);
@@ -139,9 +138,8 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
        priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg);
 
        /* Need to indicate IOCTL complete */
-       if (data_buf) {
-               signal = (struct mwifiex_ds_get_signal *) data_buf;
-               memset(signal, 0, sizeof(struct mwifiex_ds_get_signal));
+       if (signal) {
+               memset(signal, 0, sizeof(*signal));
 
                signal->selector = ALL_RSSI_INFO_MASK;
 
@@ -185,32 +183,30 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
                                       struct host_cmd_ds_command *resp,
-                                      void *data_buf)
+                                      u32 *ul_temp)
 {
        struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
        u16 oid = le16_to_cpu(smib->oid);
        u16 query_type = le16_to_cpu(smib->query_type);
-       u32 ul_temp;
 
        dev_dbg(priv->adapter->dev, "info: SNMP_RESP: oid value = %#x,"
                        " query_type = %#x, buf size = %#x\n",
                        oid, query_type, le16_to_cpu(smib->buf_size));
        if (query_type == HostCmd_ACT_GEN_GET) {
-               ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
-               if (data_buf)
-                       *(u32 *)data_buf = ul_temp;
+               if (ul_temp)
+                       *ul_temp = le16_to_cpu(*((__le16 *) (smib->value)));
                switch (oid) {
                case FRAG_THRESH_I:
                        dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: FragThsd =%u\n", ul_temp);
+                               "info: SNMP_RESP: FragThsd =%u\n", *ul_temp);
                        break;
                case RTS_THRESH_I:
                        dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: RTSThsd =%u\n", ul_temp);
+                               "info: SNMP_RESP: RTSThsd =%u\n", *ul_temp);
                        break;
                case SHORT_RETRY_LIM_I:
                        dev_dbg(priv->adapter->dev,
-                               "info: SNMP_RESP: TxRetryCount=%u\n", ul_temp);
+                               "info: SNMP_RESP: TxRetryCount=%u\n", *ul_temp);
                        break;
                default:
                        break;
@@ -228,14 +224,12 @@ static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_get_log(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *resp,
-                              void *data_buf)
+                              struct mwifiex_ds_get_stats *stats)
 {
        struct host_cmd_ds_802_11_get_log *get_log =
                (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log;
-       struct mwifiex_ds_get_stats *stats;
 
-       if (data_buf) {
-               stats = (struct mwifiex_ds_get_stats *) data_buf;
+       if (stats) {
                stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame);
                stats->failed = le32_to_cpu(get_log->failed);
                stats->retry = le32_to_cpu(get_log->retry);
@@ -278,9 +272,8 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
                                   struct host_cmd_ds_command *resp,
-                                  void *data_buf)
+                                  struct mwifiex_rate_cfg *ds_rate)
 {
-       struct mwifiex_rate_cfg *ds_rate;
        struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
        struct mwifiex_rate_scope *rate_scope;
        struct mwifiex_ie_types_header *head;
@@ -329,8 +322,7 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
                                          HostCmd_CMD_802_11_TX_RATE_QUERY,
                                          HostCmd_ACT_GEN_GET, 0, NULL);
 
-       if (data_buf) {
-               ds_rate = (struct mwifiex_rate_cfg *) data_buf;
+       if (ds_rate) {
                if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
                        if (priv->is_data_rate_auto) {
                                ds_rate->is_rate_auto = 1;
@@ -413,8 +405,7 @@ static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf)
  * and saving the current Tx power level in driver.
  */
 static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv,
-                                   struct host_cmd_ds_command *resp,
-                                   void *data_buf)
+                                   struct host_cmd_ds_command *resp)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
        struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg;
@@ -631,21 +622,21 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
                                         struct host_cmd_ds_command *resp,
-                                        void *data_buf)
+                                        u16 *new_channel)
 {
        struct host_cmd_ds_802_11_rf_channel *rf_channel =
                &resp->params.rf_channel;
-       u16 new_channel = le16_to_cpu(rf_channel->current_channel);
 
-       if (priv->curr_bss_params.bss_descriptor.channel != new_channel) {
+       if (new_channel)
+               *new_channel = le16_to_cpu(rf_channel->current_channel);
+
+       if (priv->curr_bss_params.bss_descriptor.channel != *new_channel) {
                dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n",
                       priv->curr_bss_params.bss_descriptor.channel,
-                      new_channel);
+                      *new_channel);
                /* Update the channel again */
-               priv->curr_bss_params.bss_descriptor.channel = new_channel;
+               priv->curr_bss_params.bss_descriptor.channel = *new_channel;
        }
-       if (data_buf)
-               *((u16 *)data_buf) = new_channel;
 
        return 0;
 }
@@ -658,13 +649,11 @@ static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
  */
 static int mwifiex_ret_ver_ext(struct mwifiex_private *priv,
                               struct host_cmd_ds_command *resp,
-                              void *data_buf)
+                              struct host_cmd_ds_version_ext *version_ext)
 {
        struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext;
-       struct host_cmd_ds_version_ext *version_ext;
 
-       if (data_buf) {
-               version_ext = (struct host_cmd_ds_version_ext *)data_buf;
+       if (version_ext) {
                version_ext->version_str_sel = ver_ext->version_str_sel;
                memcpy(version_ext->version_str, ver_ext->version_str,
                       sizeof(char) * 128);
@@ -686,8 +675,8 @@ static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp,
        struct mwifiex_ds_read_eeprom *eeprom;
 
        if (data_buf) {
-               reg_rw = (struct mwifiex_ds_reg_rw *) data_buf;
-               eeprom = (struct mwifiex_ds_read_eeprom *) data_buf;
+               reg_rw = data_buf;
+               eeprom = data_buf;
                switch (type) {
                case HostCmd_CMD_MAC_REG_ACCESS:
                        {
@@ -825,13 +814,11 @@ static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv,
  * This is a generic function, which calls command specific
  * response handlers based on the command ID.
  */
-int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
-                               u16 cmdresp_no, void *cmd_buf)
+int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
+                               struct host_cmd_ds_command *resp)
 {
        int ret = 0;
        struct mwifiex_adapter *adapter = priv->adapter;
-       struct host_cmd_ds_command *resp =
-               (struct host_cmd_ds_command *) cmd_buf;
        void *data_buf = adapter->curr_cmd->data_buf;
 
        /* If the command is not successful, cleanup and return failure */
@@ -865,7 +852,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv,
                        "info: CMD_RESP: BG_SCAN result is ready!\n");
                break;
        case HostCmd_CMD_TXPWR_CFG:
-               ret = mwifiex_ret_tx_power_cfg(priv, resp, data_buf);
+               ret = mwifiex_ret_tx_power_cfg(priv, resp);
                break;
        case HostCmd_CMD_802_11_PS_MODE_ENH:
                ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf);
index 1fdddec..2743051 100644 (file)
@@ -187,7 +187,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
        ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
                                             local_rx_pd->priority, ta,
                                             (u8) local_rx_pd->rx_pkt_type,
-                                               (void *) skb);
+                                            skb);
 
        if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
                if (priv && (ret == -1))
index aaa50c0..6190b2f 100644 (file)
@@ -71,7 +71,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb,
        u8 *head_ptr;
        struct txpd *local_tx_pd = NULL;
 
-       head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb);
+       head_ptr = mwifiex_process_sta_txpd(priv, skb);
        if (head_ptr) {
                if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)
                        local_tx_pd =
index 939821b..0955c94 100644 (file)
@@ -582,6 +582,18 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
        memset(&rxdesc, 0, sizeof(rxdesc));
        rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc);
 
+       /*
+        * Check for valid size in case we get corrupted descriptor from
+        * hardware.
+        */
+       if (unlikely(rxdesc.size == 0 ||
+                    rxdesc.size > entry->queue->data_size)) {
+               WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+                       rxdesc.size, entry->queue->data_size);
+               dev_kfree_skb(entry->skb);
+               goto renew_skb;
+       }
+
        /*
         * The data behind the ieee80211 header must be
         * aligned on a 4 byte boundary.
@@ -642,6 +654,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 
        ieee80211_rx_ni(rt2x00dev->hw, entry->skb);
 
+renew_skb:
        /*
         * Replace the skb with the freshly allocated one.
         */
index 8f90f62..b6b4542 100644 (file)
@@ -802,6 +802,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
        int retval;
 
        usb_dev = usb_get_dev(usb_dev);
+       usb_reset_device(usb_dev);
 
        hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
        if (!hw) {
index fb5e43b..bc13533 100644 (file)
@@ -523,7 +523,7 @@ static void _rtl_query_shortgi(struct ieee80211_hw *hw,
                mac->opmode == NL80211_IFTYPE_ADHOC)
                bw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 
-       if ((bw_40 == true) && sgi_40)
+       if (bw_40 && sgi_40)
                tcb_desc->use_shortgi = true;
        else if ((bw_40 == false) && sgi_20)
                tcb_desc->use_shortgi = true;
index d2ec253..03ce696 100644 (file)
@@ -335,8 +335,8 @@ static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
                 * before going offchannel, or dis-association or delete BA will
                 * happen by AP
                 */
-               if (rtlpriv->mac80211.offchan_deley) {
-                       rtlpriv->mac80211.offchan_deley = false;
+               if (rtlpriv->mac80211.offchan_delay) {
+                       rtlpriv->mac80211.offchan_delay = false;
                        mdelay(50);
                }
                rtlphy->current_channel = wide_chan;
@@ -443,11 +443,11 @@ static int rtl_op_sta_add(struct ieee80211_hw *hw,
                        sta_entry->wireless_mode = WIRELESS_MODE_G;
                        if (sta->supp_rates[0] <= 0xf)
                                sta_entry->wireless_mode = WIRELESS_MODE_B;
-                       if (sta->ht_cap.ht_supported == true)
+                       if (sta->ht_cap.ht_supported)
                                sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
                } else if (rtlhal->current_bandtype == BAND_ON_5G) {
                        sta_entry->wireless_mode = WIRELESS_MODE_A;
-                       if (sta->ht_cap.ht_supported == true)
+                       if (sta->ht_cap.ht_supported)
                                sta_entry->wireless_mode = WIRELESS_MODE_N_24G;
                }
 
@@ -650,7 +650,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
                RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
                         ("BSS_CHANGED_HT\n"));
                rcu_read_lock();
-               sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+               sta = get_sta(hw, vif, bss_conf->bssid);
                if (sta) {
                        if (sta->ht_cap.ampdu_density >
                            mac->current_ampdu_density)
@@ -685,7 +685,7 @@ static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
                rtlpriv->cfg->ops->set_network_type(hw, vif->type);
 
                rcu_read_lock();
-               sta = get_sta(hw, vif, (u8 *)bss_conf->bssid);
+               sta = get_sta(hw, vif, bss_conf->bssid);
                if (!sta) {
                        rcu_read_unlock();
                        goto out;
index 4b247db..f02824a 100644 (file)
@@ -30,6 +30,8 @@
 #ifndef __RTL_CORE_H__
 #define __RTL_CORE_H__
 
+#include <net/mac80211.h>
+
 #define RTL_SUPPORTED_FILTERS          \
        (FIF_PROMISC_IN_BSS | \
        FIF_ALLMULTI | FIF_CONTROL | \
index 0b56232..3fc21f6 100644 (file)
@@ -382,7 +382,7 @@ bool efuse_shadow_update_chk(struct ieee80211_hw *hw)
                        }
                }
 
-               if (wordchanged == true)
+               if (wordchanged)
                        hdr_num++;
        }
 
@@ -453,7 +453,7 @@ bool efuse_shadow_update(struct ieee80211_hw *hw)
                base = offset * 8;
 
                for (i = 0; i < 8; i++) {
-                       if (first_pg == true) {
+                       if (first_pg) {
 
                                word_en &= ~(BIT(i / 2));
 
@@ -505,7 +505,7 @@ void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 
-       if (rtlefuse->autoload_failflag == true)
+       if (rtlefuse->autoload_failflag)
                memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF,
                        rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
        else
@@ -690,7 +690,7 @@ static void efuse_read_data_case1(struct ieee80211_hw *hw, u16 *efuse_addr,
                        }
                }
 
-               if (dataempty == true) {
+               if (dataempty) {
                        *readstate = PG_STATE_DATA;
                } else {
                        *efuse_addr = *efuse_addr + (word_cnts * 2) + 1;
index e502db0..ad39af4 100644 (file)
@@ -581,7 +581,7 @@ static void _rtl_pci_tx_isr(struct ieee80211_hw *hw, int prio)
                fc = rtl_get_fc(skb);
                if (ieee80211_is_nullfunc(fc)) {
                        if (ieee80211_has_pm(fc)) {
-                               rtlpriv->mac80211.offchan_deley = true;
+                               rtlpriv->mac80211.offchan_delay = true;
                                rtlpriv->psc.state_inap = 1;
                        } else {
                                rtlpriv->psc.state_inap = 0;
@@ -626,6 +626,56 @@ tx_status_ok:
        }
 }
 
+static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb,
+                            struct ieee80211_rx_status rx_status)
+{
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
+       __le16 fc = rtl_get_fc(skb);
+       bool unicast = false;
+       struct sk_buff *uskb = NULL;
+       u8 *pdata;
+
+
+       memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+       if (is_broadcast_ether_addr(hdr->addr1)) {
+               ;/*TODO*/
+       } else if (is_multicast_ether_addr(hdr->addr1)) {
+               ;/*TODO*/
+       } else {
+               unicast = true;
+               rtlpriv->stats.rxbytesunicast += skb->len;
+       }
+
+       rtl_is_special_data(hw, skb, false);
+
+       if (ieee80211_is_data(fc)) {
+               rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+               if (unicast)
+                       rtlpriv->link_info.num_rx_inperiod++;
+       }
+
+       /* for sw lps */
+       rtl_swlps_beacon(hw, (void *)skb->data, skb->len);
+       rtl_recognize_peer(hw, (void *)skb->data, skb->len);
+       if ((rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) &&
+           (rtlpriv->rtlhal.current_bandtype == BAND_ON_2_4G) &&
+            (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)))
+               return;
+
+       if (unlikely(!rtl_action_proc(hw, skb, false)))
+               return;
+
+       uskb = dev_alloc_skb(skb->len + 128);
+       memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status));
+       pdata = (u8 *)skb_put(uskb, skb->len);
+       memcpy(pdata, skb->data, skb->len);
+
+       ieee80211_rx_irqsafe(hw, uskb);
+}
+
 static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -637,7 +687,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
        u8 own;
        u8 tmp_one;
        u32 bufferaddress;
-       bool unicast = false;
 
        struct rtl_stats stats = {
                .signal = 0,
@@ -654,128 +703,63 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
                /*rx pkt */
                struct sk_buff *skb = rtlpci->rx_ring[rx_queue_idx].rx_buf[
                                index];
+               struct sk_buff *new_skb = NULL;
 
                own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
                                                       false, HW_DESC_OWN);
 
-               if (own) {
-                       /*wait data to be filled by hardware */
+               /*wait data to be filled by hardware */
+               if (own)
                        break;
-               } else {
-                       struct ieee80211_hdr *hdr;
-                       __le16 fc;
-                       struct sk_buff *new_skb = NULL;
-
-                       rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
-                                                        &rx_status,
-                                                        (u8 *) pdesc, skb);
-
-                       new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
-                       if (unlikely(!new_skb)) {
-                               RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
-                                        DBG_DMESG,
-                                        ("can't alloc skb for rx\n"));
-                               goto done;
-                       }
 
-                       pci_unmap_single(rtlpci->pdev,
-                                        *((dma_addr_t *) skb->cb),
-                                        rtlpci->rxbuffersize,
-                                        PCI_DMA_FROMDEVICE);
+               rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
+                                                &rx_status,
+                                                (u8 *) pdesc, skb);
 
-                       skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
-                                                        false,
-                                                        HW_DESC_RXPKT_LEN));
-                       skb_reserve(skb,
-                                   stats.rx_drvinfo_size + stats.rx_bufshift);
+               if (stats.crc || stats.hwerror)
+                       goto done;
 
-                       /*
-                        *NOTICE This can not be use for mac80211,
-                        *this is done in mac80211 code,
-                        *if you done here sec DHCP will fail
-                        *skb_trim(skb, skb->len - 4);
-                        */
+               new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
+               if (unlikely(!new_skb)) {
+                       RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
+                                DBG_DMESG,
+                                ("can't alloc skb for rx\n"));
+                       goto done;
+               }
 
-                       hdr = rtl_get_hdr(skb);
-                       fc = rtl_get_fc(skb);
-
-                       if (!stats.crc && !stats.hwerror) {
-                               memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
-                                      sizeof(rx_status));
-
-                               if (is_broadcast_ether_addr(hdr->addr1)) {
-                                       ;/*TODO*/
-                               } else if (is_multicast_ether_addr(hdr->addr1)) {
-                                       ;/*TODO*/
-                               } else {
-                                       unicast = true;
-                                       rtlpriv->stats.rxbytesunicast +=
-                                           skb->len;
-                               }
-
-                               rtl_is_special_data(hw, skb, false);
-
-                               if (ieee80211_is_data(fc)) {
-                                       rtlpriv->cfg->ops->led_control(hw,
-                                                              LED_CTL_RX);
-
-                                       if (unicast)
-                                               rtlpriv->link_info.
-                                                   num_rx_inperiod++;
-                               }
-
-                               /* for sw lps */
-                               rtl_swlps_beacon(hw, (void *)skb->data,
-                                                skb->len);
-                               rtl_recognize_peer(hw, (void *)skb->data,
-                                                  skb->len);
-                               if ((rtlpriv->mac80211.opmode ==
-                                    NL80211_IFTYPE_AP) &&
-                                   (rtlpriv->rtlhal.current_bandtype ==
-                                    BAND_ON_2_4G) &&
-                                    (ieee80211_is_beacon(fc) ||
-                                    ieee80211_is_probe_resp(fc))) {
-                                       dev_kfree_skb_any(skb);
-                               } else {
-                                       if (unlikely(!rtl_action_proc(hw, skb,
-                                           false))) {
-                                               dev_kfree_skb_any(skb);
-                                       } else {
-                                               struct sk_buff *uskb = NULL;
-                                               u8 *pdata;
-                                               uskb = dev_alloc_skb(skb->len
-                                                                    + 128);
-                                               memcpy(IEEE80211_SKB_RXCB(uskb),
-                                                      &rx_status,
-                                                      sizeof(rx_status));
-                                               pdata = (u8 *)skb_put(uskb,
-                                                       skb->len);
-                                               memcpy(pdata, skb->data,
-                                                      skb->len);
-                                               dev_kfree_skb_any(skb);
-
-                                               ieee80211_rx_irqsafe(hw, uskb);
-                                       }
-                               }
-                       } else {
-                               dev_kfree_skb_any(skb);
-                       }
+               pci_unmap_single(rtlpci->pdev,
+                                *((dma_addr_t *) skb->cb),
+                                rtlpci->rxbuffersize,
+                                PCI_DMA_FROMDEVICE);
 
-                       if (((rtlpriv->link_info.num_rx_inperiod +
-                               rtlpriv->link_info.num_tx_inperiod) > 8) ||
-                               (rtlpriv->link_info.num_rx_inperiod > 2)) {
-                               tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
-                       }
+               skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc, false,
+                       HW_DESC_RXPKT_LEN));
+               skb_reserve(skb, stats.rx_drvinfo_size + stats.rx_bufshift);
 
-                       skb = new_skb;
+               /*
+                * NOTICE This can not be use for mac80211,
+                * this is done in mac80211 code,
+                * if you done here sec DHCP will fail
+                * skb_trim(skb, skb->len - 4);
+                */
 
-                       rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
-                       *((dma_addr_t *) skb->cb) =
+               _rtl_receive_one(hw, skb, rx_status);
+
+               if (((rtlpriv->link_info.num_rx_inperiod +
+                       rtlpriv->link_info.num_tx_inperiod) > 8) ||
+                       (rtlpriv->link_info.num_rx_inperiod > 2)) {
+                       tasklet_schedule(&rtlpriv->works.ips_leave_tasklet);
+               }
+
+               dev_kfree_skb_any(skb);
+               skb = new_skb;
+
+               rtlpci->rx_ring[rx_queue_idx].rx_buf[index] = skb;
+               *((dma_addr_t *) skb->cb) =
                            pci_map_single(rtlpci->pdev, skb_tail_pointer(skb),
                                           rtlpci->rxbuffersize,
                                           PCI_DMA_FROMDEVICE);
 
-               }
 done:
                bufferaddress = (*((dma_addr_t *)skb->cb));
                tmp_one = 1;
index d14c13d..a693fef 100644 (file)
@@ -79,59 +79,18 @@ EXPORT_SYMBOL(rtl_ps_disable_nic);
 
 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
                         enum rf_pwrstate state_toset,
-                        u32 changesource, bool protect_or_not)
+                        u32 changesource)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
        bool actionallowed = false;
-       u16 rfwait_cnt = 0;
 
-       /*protect_or_not = true; */
-
-       if (protect_or_not)
-               goto no_protect;
-
-       /*
-        *Only one thread can change
-        *the RF state at one time, and others
-        *should wait to be executed.
-        */
-       while (true) {
-               spin_lock(&rtlpriv->locks.rf_ps_lock);
-               if (ppsc->rfchange_inprogress) {
-                       spin_unlock(&rtlpriv->locks.rf_ps_lock);
-
-                       RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-                                ("RF Change in progress!"
-                                 "Wait to set..state_toset(%d).\n",
-                                 state_toset));
-
-                       /* Set RF after the previous action is done.  */
-                       while (ppsc->rfchange_inprogress) {
-                               rfwait_cnt++;
-                               mdelay(1);
-
-                               /*
-                                *Wait too long, return false to avoid
-                                *to be stuck here.
-                                */
-                               if (rfwait_cnt > 100)
-                                       return false;
-                       }
-               } else {
-                       ppsc->rfchange_inprogress = true;
-                       spin_unlock(&rtlpriv->locks.rf_ps_lock);
-                       break;
-               }
-       }
-
-no_protect:
        switch (state_toset) {
        case ERFON:
                ppsc->rfoff_reason &= (~changesource);
 
                if ((changesource == RF_CHANGE_BY_HW) &&
-                   (ppsc->hwradiooff == true)) {
+                   (ppsc->hwradiooff)) {
                        ppsc->hwradiooff = false;
                }
 
@@ -167,12 +126,6 @@ no_protect:
        if (actionallowed)
                rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
 
-       if (!protect_or_not) {
-               spin_lock(&rtlpriv->locks.rf_ps_lock);
-               ppsc->rfchange_inprogress = false;
-               spin_unlock(&rtlpriv->locks.rf_ps_lock);
-       }
-
        return actionallowed;
 }
 EXPORT_SYMBOL(rtl_ps_set_rf_state);
@@ -195,8 +148,7 @@ static void _rtl_ps_inactive_ps(struct ieee80211_hw *hw)
                }
        }
 
-       rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate,
-                           RF_CHANGE_BY_IPS, false);
+       rtl_ps_set_rf_state(hw, ppsc->inactive_pwrstate, RF_CHANGE_BY_IPS);
 
        if (ppsc->inactive_pwrstate == ERFOFF &&
            rtlhal->interface == INTF_PCI) {
@@ -587,7 +539,7 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
        }
 
        spin_lock(&rtlpriv->locks.lps_lock);
-       rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS, false);
+       rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
        spin_unlock(&rtlpriv->locks.lps_lock);
 }
 
@@ -621,15 +573,8 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
        if (rtlpriv->link_info.busytraffic)
                return;
 
-       spin_lock(&rtlpriv->locks.rf_ps_lock);
-       if (rtlpriv->psc.rfchange_inprogress) {
-               spin_unlock(&rtlpriv->locks.rf_ps_lock);
-               return;
-       }
-       spin_unlock(&rtlpriv->locks.rf_ps_lock);
-
        spin_lock(&rtlpriv->locks.lps_lock);
-       rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS, false);
+       rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
        spin_unlock(&rtlpriv->locks.lps_lock);
 
        if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
index e3bf898..84628e6 100644 (file)
@@ -33,8 +33,7 @@
 #define MAX_SW_LPS_SLEEP_INTV  5
 
 bool rtl_ps_set_rf_state(struct ieee80211_hw *hw,
-                        enum rf_pwrstate state_toset, u32 changesource,
-                        bool protect_or_not);
+                        enum rf_pwrstate state_toset, u32 changesource);
 bool rtl_ps_enable_nic(struct ieee80211_hw *hw);
 bool rtl_ps_disable_nic(struct ieee80211_hw *hw);
 void rtl_ips_nic_off(struct ieee80211_hw *hw);
index 30da68a..539df66 100644 (file)
@@ -200,7 +200,7 @@ static void rtl_tx_status(void *ppriv,
        if (sta) {
                /* Check if aggregation has to be enabled for this tid */
                sta_entry = (struct rtl_sta_info *) sta->drv_priv;
-               if ((sta->ht_cap.ht_supported == true) &&
+               if ((sta->ht_cap.ht_supported) &&
                                !(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
                        if (ieee80211_is_data_qos(fc)) {
                                u8 tid = rtl_get_tid(skb);
index 9718382..a00774e 100644 (file)
@@ -474,7 +474,7 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
 {
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-       if (mac->act_scanning == true)
+       if (mac->act_scanning)
                return;
 
        if (mac->link_state >= MAC80211_LINKED)
@@ -670,7 +670,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
        u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0;
        int i;
        bool is2t = IS_92C_SERIAL(rtlhal->version);
-       u8 txpwr_level[2] = {0, 0};
+       s8 txpwr_level[2] = {0, 0};
        u8 ofdm_min_index = 6, rf;
 
        rtlpriv->dm.txpower_trackinginit = true;
index 944f55e..bc6ae9d 100644 (file)
@@ -488,7 +488,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
        case HW_VAR_CORRECT_TSF:{
                        u8 btype_ibss = ((u8 *) (val))[0];
 
-                       if (btype_ibss == true)
+                       if (btype_ibss)
                                _rtl92ce_stop_tx_beacon(hw);
 
                        _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(3));
@@ -500,7 +500,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
 
                        _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
 
-                       if (btype_ibss == true)
+                       if (btype_ibss)
                                _rtl92ce_resume_tx_beacon(hw);
 
                        break;
@@ -1121,7 +1121,7 @@ void rtl92ce_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
        if (rtlpriv->psc.rfpwr_state != ERFON)
                return;
 
-       if (check_bssid == true) {
+       if (check_bssid) {
                reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
                                              (u8 *) (&reg_rcr));
@@ -1585,7 +1585,7 @@ static void _rtl92ce_read_adapter_info(struct ieee80211_hw *hw)
                rtlefuse->autoload_failflag = false;
        }
 
-       if (rtlefuse->autoload_failflag == true)
+       if (rtlefuse->autoload_failflag)
                return;
 
        for (i = 0; i < 6; i += 2) {
@@ -1994,7 +1994,7 @@ bool rtl92ce_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
        u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
        e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
 
-       if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+       if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
                RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
                         ("GPIOChangeRF  - HW Radio ON, RF ON\n"));
 
index 9dd1ed7..28a1a70 100644 (file)
@@ -84,7 +84,7 @@ void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
                break;
        case LED_PIN_LED0:
                ledcfg &= 0xf0;
-               if (pcipriv->ledctl.led_opendrain == true)
+               if (pcipriv->ledctl.led_opendrain)
                        rtl_write_byte(rtlpriv, REG_LEDCFG2,
                                       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
                else
index 90d0f2c..d3b01e6 100644 (file)
@@ -76,7 +76,7 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
        if (rtlefuse->eeprom_regulatory != 0)
                turbo_scanoff = true;
 
-       if (mac->act_scanning == true) {
+       if (mac->act_scanning) {
                tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
                tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
 
index 2492cc2..230bbe9 100644 (file)
@@ -225,7 +225,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct phy_sts_cck_8192s_t *cck_buf;
-       s8 rx_pwr_all, rx_pwr[4];
+       s8 rx_pwr_all = 0, rx_pwr[4];
        u8 evm, pwdb_all, rf_rx_num = 0;
        u8 i, max_spatial_stream;
        u32 rssi, total_rssi = 0;
@@ -678,7 +678,7 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
                                                    GET_RX_DESC_PAGGR(pdesc));
 
        rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
-       if (phystatus == true) {
+       if (phystatus) {
                p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
                                                     stats->rx_bufshift);
 
@@ -927,7 +927,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
 
 void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 {
-       if (istx == true) {
+       if (istx) {
                switch (desc_name) {
                case HW_DESC_OWN:
                        wmb();
@@ -968,7 +968,7 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
 {
        u32 ret = 0;
 
-       if (istx == true) {
+       if (istx) {
                switch (desc_name) {
                case HW_DESC_OWN:
                        ret = GET_TX_DESC_OWN(p_desc);
index 52e2af5..2b34764 100644 (file)
@@ -520,7 +520,7 @@ static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
                RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
                rtlefuse->autoload_failflag = false;
        }
-       if (rtlefuse->autoload_failflag == true)
+       if (rtlefuse->autoload_failflag)
                return;
        for (i = 0; i < 6; i += 2) {
                usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
@@ -1594,7 +1594,7 @@ static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
        default:
                break;
        }
-       if (filterout_non_associated_bssid == true) {
+       if (filterout_non_associated_bssid) {
                if (IS_NORMAL_CHIP(rtlhal->version)) {
                        switch (rtlphy->current_io_type) {
                        case IO_CMD_RESUME_DM_BY_SCAN:
@@ -2155,7 +2155,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
        case HW_VAR_CORRECT_TSF:{
                        u8 btype_ibss = ((u8 *) (val))[0];
 
-                       if (btype_ibss == true)
+                       if (btype_ibss)
                                _rtl92cu_stop_tx_beacon(hw);
                        _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
                        rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf &
@@ -2163,7 +2163,7 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
                        rtl_write_dword(rtlpriv, REG_TSFTR + 4,
                                        (u32)((mac->tsf >> 32) & 0xffffffff));
                        _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
-                       if (btype_ibss == true)
+                       if (btype_ibss)
                                _rtl92cu_resume_tx_beacon(hw);
                        break;
                }
index 332c743..2ff9d83 100644 (file)
@@ -82,7 +82,7 @@ void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
                break;
        case LED_PIN_LED0:
                ledcfg &= 0xf0;
-               if (usbpriv->ledctl.led_opendrain == true)
+               if (usbpriv->ledctl.led_opendrain)
                        rtl_write_byte(rtlpriv, REG_LEDCFG2,
                                       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
                else
index c7576ec..1e851aa 100644 (file)
@@ -82,7 +82,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
                    (rtlefuse->external_pa))
                        turbo_scanoff = true;
        }
-       if (mac->act_scanning == true) {
+       if (mac->act_scanning) {
                tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
                tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
                if (turbo_scanoff) {
index 3a92ba3..906e7aa 100644 (file)
@@ -342,7 +342,7 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
                                                (u8)GET_RX_DESC_RX_MCS(pdesc),
                                                (bool)GET_RX_DESC_PAGGR(pdesc));
        rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
-       if (phystatus == true) {
+       if (phystatus) {
                p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
                rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
                                                 p_drvinfo);
index 609c7ec..4203a85 100644 (file)
@@ -452,7 +452,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw)
                        if (rtlpriv->psc.rfpwr_state != ERFON)
                                return;
 
-                       if (digtable.backoff_enable_flag == true)
+                       if (digtable.backoff_enable_flag)
                                rtl92s_backoff_enable_flag(hw);
                        else
                                digtable.backoff_val = DM_DIG_BACKOFF;
index 35dd12d..13da7b3 100644 (file)
@@ -516,7 +516,7 @@ static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw)
        mdelay(10);
 
        /* check GPIO3 */
-       u1tmp = rtl_read_byte(rtlpriv, GPIO_IN);
+       u1tmp = rtl_read_byte(rtlpriv, GPIO_IN_SE);
        retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF;
 
        return retval;
@@ -994,7 +994,8 @@ int rtl92se_hw_init(struct ieee80211_hw *hw)
 
                rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT;
                rtlpriv->psc.rfpwr_state = ERFON;
-               rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true);
+               /* FIXME: check spinlocks if this block is uncommented */
+               rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason);
        } else {
                /* gpio radio on/off is out of adapter start */
                if (rtlpriv->psc.hwradiooff == false) {
@@ -1105,7 +1106,7 @@ void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
        if (rtlpriv->psc.rfpwr_state != ERFON)
                return;
 
-       if (check_bssid == true) {
+       if (check_bssid) {
                reg_rcr |= (RCR_CBSSID);
                rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(&reg_rcr));
        } else if (check_bssid == false) {
@@ -1651,7 +1652,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw)
                rtlefuse->autoload_failflag = false;
        }
 
-       if (rtlefuse->autoload_failflag == true)
+       if (rtlefuse->autoload_failflag)
                return;
 
        _rtl8192se_get_IC_Inferiority(hw);
@@ -2301,7 +2302,7 @@ bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid)
 
        rfpwr_toset = _rtl92se_rf_onoff_detect(hw);
 
-       if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) {
+       if ((ppsc->hwradiooff) && (rfpwr_toset == ERFON)) {
                RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
                         ("RFKILL-HW Radio ON, RF ON\n"));
 
index 6d4f666..e3fe7c9 100644 (file)
@@ -90,7 +90,7 @@ void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
                break;
        case LED_PIN_LED0:
                ledcfg &= 0xf0;
-               if (pcipriv->ledctl.led_opendrain == true)
+               if (pcipriv->ledctl.led_opendrain)
                        rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1)));
                else
                        rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3)));
index 7ee2dac..81a5aa4 100644 (file)
@@ -1416,7 +1416,7 @@ static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw)
                break;
        case FW_CMD_HIGH_PWR_ENABLE:
                if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
-                       (rtlpriv->dm.dynamic_txpower_enable == true))
+                       rtlpriv->dm.dynamic_txpower_enable)
                        break;
 
                /* CCA threshold */
@@ -1608,7 +1608,7 @@ bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio)
                                fw_cmdmap &= ~FW_DIG_ENABLE_CTL;
 
                        if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) ||
-                           (rtlpriv->dm.dynamic_txpower_enable == true))
+                           rtlpriv->dm.dynamic_txpower_enable)
                                fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL;
 
                        if ((digtable.dig_ext_port_stage ==
index 0116ead..ea32ef2 100644 (file)
 #define        PSTIME                                  0x02E0
 #define        TIMER0                                  0x02E4
 #define        TIMER1                                  0x02E8
-#define        GPIO_CTRL                               0x02EC
-#define        GPIO_IN                                 0x02EC
-#define        GPIO_OUT                                0x02ED
+#define        GPIO_IN_SE                              0x02EC
 #define        GPIO_IO_SEL                             0x02EE
-#define        GPIO_MOD                                0x02EF
-#define        GPIO_INTCTRL                            0x02F0
 #define        MAC_PINMUX_CFG                          0x02F1
 #define        LEDCFG                                  0x02F2
 #define        PHY_REG                                 0x02F3
index 1d3a483..c6e3a4c 100644 (file)
@@ -410,7 +410,7 @@ void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel)
              (rtlefuse->eeprom_regulatory != 0)))
                dont_inc_cck_or_turboscanoff = true;
 
-       if (mac->act_scanning == true) {
+       if (mac->act_scanning) {
                txagc = 0x3f;
                if (dont_inc_cck_or_turboscanoff)
                        txagc = pwrlevel;
index d509cf6..cffe308 100644 (file)
@@ -661,7 +661,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
 
 
        rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
-       if (phystatus == true) {
+       if (phystatus) {
                p_drvinfo = (struct rx_fwinfo *)(skb->data +
                                                 stats->rx_bufshift);
                _rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
@@ -900,7 +900,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 
 void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
 {
-       if (istx == true) {
+       if (istx) {
                switch (desc_name) {
                case HW_DESC_OWN:
                        wmb();
@@ -941,7 +941,7 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
 {
        u32 ret = 0;
 
-       if (istx == true) {
+       if (istx) {
                switch (desc_name) {
                case HW_DESC_OWN:
                        ret = GET_TX_DESC_OWN(desc);
index 9d003e0..c54cda5 100644 (file)
@@ -938,7 +938,7 @@ struct rtl_mac {
        int n_channels;
        int n_bitrates;
 
-       bool offchan_deley;
+       bool offchan_delay;
 
        /*filters */
        u32 rx_conf;
@@ -1983,7 +1983,7 @@ static inline u16 rtl_get_tid(struct sk_buff *skb)
 
 static inline struct ieee80211_sta *get_sta(struct ieee80211_hw *hw,
                                            struct ieee80211_vif *vif,
-                                           u8 *bssid)
+                                           const u8 *bssid)
 {
        return ieee80211_find_sta(vif, bssid);
 }
index 4be7c3b..117c412 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef _ZD_CHIP_H
 #define _ZD_CHIP_H
 
+#include <net/mac80211.h>
+
 #include "zd_rf.h"
 #include "zd_usb.h"
 
index 5463ca9..9a1b013 100644 (file)
@@ -37,9 +37,15 @@ typedef u16 __nocast zd_addr_t;
        if (net_ratelimit()) \
                dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
 } while (0)
+#  define dev_dbg_f_cond(dev, cond, fmt, args...) ({ \
+       bool __cond = !!(cond); \
+       if (unlikely(__cond)) \
+               dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
+})
 #else
 #  define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
 #  define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0)
+#  define dev_dbg_f_cond(dev, cond, fmt, args...) do { (void)(dev); } while (0)
 #endif /* DEBUG */
 
 #ifdef DEBUG
index 5037c8b..cabfae1 100644 (file)
@@ -143,7 +143,7 @@ static void beacon_enable(struct zd_mac *mac);
 static void beacon_disable(struct zd_mac *mac);
 static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
 static int zd_mac_config_beacon(struct ieee80211_hw *hw,
-                               struct sk_buff *beacon);
+                               struct sk_buff *beacon, bool in_intr);
 
 static int zd_reg2alpha2(u8 regdomain, char *alpha2)
 {
@@ -160,6 +160,22 @@ static int zd_reg2alpha2(u8 regdomain, char *alpha2)
        return 1;
 }
 
+static int zd_check_signal(struct ieee80211_hw *hw, int signal)
+{
+       struct zd_mac *mac = zd_hw_mac(hw);
+
+       dev_dbg_f_cond(zd_mac_dev(mac), signal < 0 || signal > 100,
+                       "%s: signal value from device not in range 0..100, "
+                       "but %d.\n", __func__, signal);
+
+       if (signal < 0)
+               signal = 0;
+       else if (signal > 100)
+               signal = 100;
+
+       return signal;
+}
+
 int zd_mac_preinit_hw(struct ieee80211_hw *hw)
 {
        int r;
@@ -387,10 +403,8 @@ int zd_restore_settings(struct zd_mac *mac)
            mac->type == NL80211_IFTYPE_AP) {
                if (mac->vif != NULL) {
                        beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-                       if (beacon) {
-                               zd_mac_config_beacon(mac->hw, beacon);
-                               kfree_skb(beacon);
-                       }
+                       if (beacon)
+                               zd_mac_config_beacon(mac->hw, beacon, false);
                }
 
                zd_set_beacon_interval(&mac->chip, beacon_interval,
@@ -461,7 +475,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
        if (i<IEEE80211_TX_MAX_RATES)
                info->status.rates[i].idx = -1; /* terminate */
 
-       info->status.ack_signal = ackssi;
+       info->status.ack_signal = zd_check_signal(hw, ackssi);
        ieee80211_tx_status_irqsafe(hw, skb);
 }
 
@@ -664,7 +678,34 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
        /* FIXME: Management frame? */
 }
 
-static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
+static bool zd_mac_match_cur_beacon(struct zd_mac *mac, struct sk_buff *beacon)
+{
+       if (!mac->beacon.cur_beacon)
+               return false;
+
+       if (mac->beacon.cur_beacon->len != beacon->len)
+               return false;
+
+       return !memcmp(beacon->data, mac->beacon.cur_beacon->data, beacon->len);
+}
+
+static void zd_mac_free_cur_beacon_locked(struct zd_mac *mac)
+{
+       ZD_ASSERT(mutex_is_locked(&mac->chip.mutex));
+
+       kfree_skb(mac->beacon.cur_beacon);
+       mac->beacon.cur_beacon = NULL;
+}
+
+static void zd_mac_free_cur_beacon(struct zd_mac *mac)
+{
+       mutex_lock(&mac->chip.mutex);
+       zd_mac_free_cur_beacon_locked(mac);
+       mutex_unlock(&mac->chip.mutex);
+}
+
+static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
+                               bool in_intr)
 {
        struct zd_mac *mac = zd_hw_mac(hw);
        int r, ret, num_cmds, req_pos = 0;
@@ -674,13 +715,21 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
        unsigned long end_jiffies, message_jiffies;
        struct zd_ioreq32 *ioreqs;
 
+       mutex_lock(&mac->chip.mutex);
+
+       /* Check if hw already has this beacon. */
+       if (zd_mac_match_cur_beacon(mac, beacon)) {
+               r = 0;
+               goto out_nofree;
+       }
+
        /* Alloc memory for full beacon write at once. */
        num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
        ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
-       if (!ioreqs)
-               return -ENOMEM;
-
-       mutex_lock(&mac->chip.mutex);
+       if (!ioreqs) {
+               r = -ENOMEM;
+               goto out_nofree;
+       }
 
        r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
        if (r < 0)
@@ -688,6 +737,10 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
        r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
        if (r < 0)
                goto release_sema;
+       if (in_intr && tmp & 0x2) {
+               r = -EBUSY;
+               goto release_sema;
+       }
 
        end_jiffies = jiffies + HZ / 2; /*~500ms*/
        message_jiffies = jiffies + HZ / 10; /*~100ms*/
@@ -742,7 +795,7 @@ release_sema:
        end_jiffies = jiffies + HZ / 2; /*~500ms*/
        ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
        while (ret < 0) {
-               if (time_is_before_eq_jiffies(end_jiffies)) {
+               if (in_intr || time_is_before_eq_jiffies(end_jiffies)) {
                        ret = -ETIMEDOUT;
                        break;
                }
@@ -757,9 +810,19 @@ release_sema:
        if (r < 0 || ret < 0) {
                if (r >= 0)
                        r = ret;
+
+               /* We don't know if beacon was written successfully or not,
+                * so clear current. */
+               zd_mac_free_cur_beacon_locked(mac);
+
                goto out;
        }
 
+       /* Beacon has now been written successfully, update current. */
+       zd_mac_free_cur_beacon_locked(mac);
+       mac->beacon.cur_beacon = beacon;
+       beacon = NULL;
+
        /* 802.11b/g 2.4G CCK 1Mb
         * 802.11a, not yet implemented, uses different values (see GPL vendor
         * driver)
@@ -767,11 +830,17 @@ release_sema:
        r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
                                CR_BCN_PLCP_CFG);
 out:
-       mutex_unlock(&mac->chip.mutex);
        kfree(ioreqs);
+out_nofree:
+       kfree_skb(beacon);
+       mutex_unlock(&mac->chip.mutex);
+
        return r;
 
 reset_device:
+       zd_mac_free_cur_beacon_locked(mac);
+       kfree_skb(beacon);
+
        mutex_unlock(&mac->chip.mutex);
        kfree(ioreqs);
 
@@ -982,7 +1051,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
 
        stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq;
        stats.band = IEEE80211_BAND_2GHZ;
-       stats.signal = status->signal_strength;
+       stats.signal = zd_check_signal(hw, status->signal_strength);
 
        rate = zd_rx_rate(buffer, status);
 
@@ -1057,6 +1126,8 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
        mac->vif = NULL;
        zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
        zd_write_mac_addr(&mac->chip, NULL);
+
+       zd_mac_free_cur_beacon(mac);
 }
 
 static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
@@ -1094,10 +1165,8 @@ static void zd_beacon_done(struct zd_mac *mac)
         * Fetch next beacon so that tim_count is updated.
         */
        beacon = ieee80211_beacon_get(mac->hw, mac->vif);
-       if (beacon) {
-               zd_mac_config_beacon(mac->hw, beacon);
-               kfree_skb(beacon);
-       }
+       if (beacon)
+               zd_mac_config_beacon(mac->hw, beacon, true);
 
        spin_lock_irq(&mac->lock);
        mac->beacon.last_update = jiffies;
@@ -1222,9 +1291,8 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
 
                        if (beacon) {
                                zd_chip_disable_hwint(&mac->chip);
-                               zd_mac_config_beacon(hw, beacon);
+                               zd_mac_config_beacon(hw, beacon, false);
                                zd_chip_enable_hwint(&mac->chip);
-                               kfree_skb(beacon);
                        }
                }
 
@@ -1361,7 +1429,8 @@ static void beacon_watchdog_handler(struct work_struct *work)
        spin_lock_irq(&mac->lock);
        interval = mac->beacon.interval;
        period = mac->beacon.period;
-       timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+       timeout = mac->beacon.last_update +
+                       msecs_to_jiffies(interval * 1024 / 1000) * 3;
        spin_unlock_irq(&mac->lock);
 
        if (interval > 0 && time_is_before_jiffies(timeout)) {
@@ -1374,8 +1443,9 @@ static void beacon_watchdog_handler(struct work_struct *work)
 
                beacon = ieee80211_beacon_get(mac->hw, mac->vif);
                if (beacon) {
-                       zd_mac_config_beacon(mac->hw, beacon);
-                       kfree_skb(beacon);
+                       zd_mac_free_cur_beacon(mac);
+
+                       zd_mac_config_beacon(mac->hw, beacon, false);
                }
 
                zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
@@ -1410,6 +1480,8 @@ static void beacon_disable(struct zd_mac *mac)
 {
        dev_dbg_f(zd_mac_dev(mac), "\n");
        cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+
+       zd_mac_free_cur_beacon(mac);
 }
 
 #define LINK_LED_WORK_DELAY HZ
index f8c93c3..c01eca8 100644 (file)
@@ -165,6 +165,7 @@ struct housekeeping {
 
 struct beacon {
        struct delayed_work watchdog_work;
+       struct sk_buff *cur_beacon;
        unsigned long last_update;
        u16 interval;
        u8 period;
index 631194d..cf0d69d 100644 (file)
@@ -111,6 +111,9 @@ MODULE_DEVICE_TABLE(usb, usb_ids);
 #define FW_ZD1211_PREFIX       "zd1211/zd1211_"
 #define FW_ZD1211B_PREFIX      "zd1211/zd1211b_"
 
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+                           unsigned int count);
+
 /* USB device initialization */
 static void int_urb_complete(struct urb *urb);
 
@@ -365,6 +368,20 @@ exit:
 
 #define urb_dev(urb) (&(urb)->dev->dev)
 
+static inline void handle_regs_int_override(struct urb *urb)
+{
+       struct zd_usb *usb = urb->context;
+       struct zd_usb_interrupt *intr = &usb->intr;
+
+       spin_lock(&intr->lock);
+       if (atomic_read(&intr->read_regs_enabled)) {
+               atomic_set(&intr->read_regs_enabled, 0);
+               intr->read_regs_int_overridden = 1;
+               complete(&intr->read_regs.completion);
+       }
+       spin_unlock(&intr->lock);
+}
+
 static inline void handle_regs_int(struct urb *urb)
 {
        struct zd_usb *usb = urb->context;
@@ -383,25 +400,45 @@ static inline void handle_regs_int(struct urb *urb)
                                USB_MAX_EP_INT_BUFFER);
                spin_unlock(&mac->lock);
                schedule_work(&mac->process_intr);
-       } else if (intr->read_regs_enabled) {
-               intr->read_regs.length = len = urb->actual_length;
-
+       } else if (atomic_read(&intr->read_regs_enabled)) {
+               len = urb->actual_length;
+               intr->read_regs.length = urb->actual_length;
                if (len > sizeof(intr->read_regs.buffer))
                        len = sizeof(intr->read_regs.buffer);
+
                memcpy(intr->read_regs.buffer, urb->transfer_buffer, len);
-               intr->read_regs_enabled = 0;
+
+               /* Sometimes USB_INT_ID_REGS is not overridden, but comes after
+                * USB_INT_ID_RETRY_FAILED. Read-reg retry then gets this
+                * delayed USB_INT_ID_REGS, but leaves USB_INT_ID_REGS of
+                * retry unhandled. Next read-reg command then might catch
+                * this wrong USB_INT_ID_REGS. Fix by ignoring wrong reads.
+                */
+               if (!check_read_regs(usb, intr->read_regs.req,
+                                               intr->read_regs.req_count))
+                       goto out;
+
+               atomic_set(&intr->read_regs_enabled, 0);
+               intr->read_regs_int_overridden = 0;
                complete(&intr->read_regs.completion);
+
                goto out;
        }
 
 out:
        spin_unlock(&intr->lock);
+
+       /* CR_INTERRUPT might override read_reg too. */
+       if (int_num == CR_INTERRUPT && atomic_read(&intr->read_regs_enabled))
+               handle_regs_int_override(urb);
 }
 
 static void int_urb_complete(struct urb *urb)
 {
        int r;
        struct usb_int_header *hdr;
+       struct zd_usb *usb;
+       struct zd_usb_interrupt *intr;
 
        switch (urb->status) {
        case 0:
@@ -430,6 +467,14 @@ static void int_urb_complete(struct urb *urb)
                goto resubmit;
        }
 
+       /* USB_INT_ID_RETRY_FAILED triggered by tx-urb submit can override
+        * pending USB_INT_ID_REGS causing read command timeout.
+        */
+       usb = urb->context;
+       intr = &usb->intr;
+       if (hdr->id != USB_INT_ID_REGS && atomic_read(&intr->read_regs_enabled))
+               handle_regs_int_override(urb);
+
        switch (hdr->id) {
        case USB_INT_ID_REGS:
                handle_regs_int(urb);
@@ -579,8 +624,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
 
        if (length < sizeof(struct rx_length_info)) {
                /* It's not a complete packet anyhow. */
-               printk("%s: invalid, small RX packet : %d\n",
-                      __func__, length);
+               dev_dbg_f(zd_usb_dev(usb), "invalid, small RX packet : %d\n",
+                                          length);
                return;
        }
        length_info = (struct rx_length_info *)
@@ -1129,6 +1174,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
        spin_lock_init(&intr->lock);
        intr->interval = int_urb_interval(zd_usb_to_usbdev(usb));
        init_completion(&intr->read_regs.completion);
+       atomic_set(&intr->read_regs_enabled, 0);
        intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT);
 }
 
@@ -1563,12 +1609,16 @@ static int usb_int_regs_length(unsigned int count)
        return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
 }
 
-static void prepare_read_regs_int(struct zd_usb *usb)
+static void prepare_read_regs_int(struct zd_usb *usb,
+                                 struct usb_req_read_regs *req,
+                                 unsigned int count)
 {
        struct zd_usb_interrupt *intr = &usb->intr;
 
        spin_lock_irq(&intr->lock);
-       intr->read_regs_enabled = 1;
+       atomic_set(&intr->read_regs_enabled, 1);
+       intr->read_regs.req = req;
+       intr->read_regs.req_count = count;
        INIT_COMPLETION(intr->read_regs.completion);
        spin_unlock_irq(&intr->lock);
 }
@@ -1578,22 +1628,18 @@ static void disable_read_regs_int(struct zd_usb *usb)
        struct zd_usb_interrupt *intr = &usb->intr;
 
        spin_lock_irq(&intr->lock);
-       intr->read_regs_enabled = 0;
+       atomic_set(&intr->read_regs_enabled, 0);
        spin_unlock_irq(&intr->lock);
 }
 
-static int get_results(struct zd_usb *usb, u16 *values,
-                      struct usb_req_read_regs *req, unsigned int count)
+static bool check_read_regs(struct zd_usb *usb, struct usb_req_read_regs *req,
+                           unsigned int count)
 {
-       int r;
        int i;
        struct zd_usb_interrupt *intr = &usb->intr;
        struct read_regs_int *rr = &intr->read_regs;
        struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
 
-       spin_lock_irq(&intr->lock);
-
-       r = -EIO;
        /* The created block size seems to be larger than expected.
         * However results appear to be correct.
         */
@@ -1601,13 +1647,14 @@ static int get_results(struct zd_usb *usb, u16 *values,
                dev_dbg_f(zd_usb_dev(usb),
                         "error: actual length %d less than expected %d\n",
                         rr->length, usb_int_regs_length(count));
-               goto error_unlock;
+               return false;
        }
+
        if (rr->length > sizeof(rr->buffer)) {
                dev_dbg_f(zd_usb_dev(usb),
                         "error: actual length %d exceeds buffer size %zu\n",
                         rr->length, sizeof(rr->buffer));
-               goto error_unlock;
+               return false;
        }
 
        for (i = 0; i < count; i++) {
@@ -1617,8 +1664,39 @@ static int get_results(struct zd_usb *usb, u16 *values,
                                 "rd[%d] addr %#06hx expected %#06hx\n", i,
                                 le16_to_cpu(rd->addr),
                                 le16_to_cpu(req->addr[i]));
-                       goto error_unlock;
+                       return false;
                }
+       }
+
+       return true;
+}
+
+static int get_results(struct zd_usb *usb, u16 *values,
+                      struct usb_req_read_regs *req, unsigned int count,
+                      bool *retry)
+{
+       int r;
+       int i;
+       struct zd_usb_interrupt *intr = &usb->intr;
+       struct read_regs_int *rr = &intr->read_regs;
+       struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer;
+
+       spin_lock_irq(&intr->lock);
+
+       r = -EIO;
+
+       /* Read failed because firmware bug? */
+       *retry = !!intr->read_regs_int_overridden;
+       if (*retry)
+               goto error_unlock;
+
+       if (!check_read_regs(usb, req, count)) {
+               dev_dbg_f(zd_usb_dev(usb), "error: invalid read regs\n");
+               goto error_unlock;
+       }
+
+       for (i = 0; i < count; i++) {
+               struct reg_data *rd = &regs->regs[i];
                values[i] = le16_to_cpu(rd->value);
        }
 
@@ -1631,11 +1709,11 @@ error_unlock:
 int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
                     const zd_addr_t *addresses, unsigned int count)
 {
-       int r;
-       int i, req_len, actual_req_len;
+       int r, i, req_len, actual_req_len, try_count = 0;
        struct usb_device *udev;
        struct usb_req_read_regs *req = NULL;
        unsigned long timeout;
+       bool retry = false;
 
        if (count < 1) {
                dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n");
@@ -1671,8 +1749,10 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
        for (i = 0; i < count; i++)
                req->addr[i] = cpu_to_le16((u16)addresses[i]);
 
+retry_read:
+       try_count++;
        udev = zd_usb_to_usbdev(usb);
-       prepare_read_regs_int(usb);
+       prepare_read_regs_int(usb, req, count);
        r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
        if (r) {
                dev_dbg_f(zd_usb_dev(usb),
@@ -1696,7 +1776,12 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
                goto error;
        }
 
-       r = get_results(usb, values, req, count);
+       r = get_results(usb, values, req, count, &retry);
+       if (retry && try_count < 20) {
+               dev_dbg_f(zd_usb_dev(usb), "read retry, tries so far: %d\n",
+                               try_count);
+               goto retry_read;
+       }
 error:
        return r;
 }
index bf94284..99193b4 100644 (file)
@@ -144,6 +144,8 @@ struct usb_int_retry_fail {
 
 struct read_regs_int {
        struct completion completion;
+       struct usb_req_read_regs *req;
+       unsigned int req_count;
        /* Stores the USB int structure and contains the USB address of the
         * first requested register before request.
         */
@@ -169,7 +171,8 @@ struct zd_usb_interrupt {
        void *buffer;
        dma_addr_t buffer_dma;
        int interval;
-       u8 read_regs_enabled:1;
+       atomic_t read_regs_enabled;
+       u8 read_regs_int_overridden:1;
 };
 
 static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
index 305ade7..a7aef47 100644 (file)
@@ -417,9 +417,9 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
        u32 min_msk = 0, max_msk = 0;
        unsigned int i;
        const struct pmu_res_updown_tab_entry *updown_tab = NULL;
-       unsigned int updown_tab_size;
+       unsigned int updown_tab_size = 0;
        const struct pmu_res_depend_tab_entry *depend_tab = NULL;
-       unsigned int depend_tab_size;
+       unsigned int depend_tab_size = 0;
 
        switch (bus->chip_id) {
        case 0x4312:
index 5ba92a2..d758909 100644 (file)
@@ -106,8 +106,9 @@ void gige_pcicfg_write32(struct ssb_gige *dev,
        gige_write32(dev, SSB_GIGE_PCICFG + offset, value);
 }
 
-static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
-                                   int reg, int size, u32 *val)
+static int __devinit ssb_gige_pci_read_config(struct pci_bus *bus,
+                                             unsigned int devfn, int reg,
+                                             int size, u32 *val)
 {
        struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
        unsigned long flags;
@@ -136,8 +137,9 @@ static int ssb_gige_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
-                                    int reg, int size, u32 val)
+static int __devinit ssb_gige_pci_write_config(struct pci_bus *bus,
+                                              unsigned int devfn, int reg,
+                                              int size, u32 val)
 {
        struct ssb_gige *dev = container_of(bus->ops, struct ssb_gige, pci_ops);
        unsigned long flags;
@@ -166,7 +168,8 @@ static int ssb_gige_pci_write_config(struct pci_bus *bus, unsigned int devfn,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static int ssb_gige_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
+static int __devinit ssb_gige_probe(struct ssb_device *sdev,
+                                   const struct ssb_device_id *id)
 {
        struct ssb_gige *dev;
        u32 base, tmslow, tmshigh;
index 2a20dab..21b9465 100644 (file)
@@ -314,7 +314,7 @@ int ssb_pcicore_pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return ssb_mips_irq(extpci_core->dev) + 2;
 }
 
-static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
 {
        u32 val;
 
@@ -379,7 +379,7 @@ static void ssb_pcicore_init_hostmode(struct ssb_pcicore *pc)
        register_pci_controller(&ssb_pcicore_controller);
 }
 
-static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
+static int __devinit pcicore_is_in_hostmode(struct ssb_pcicore *pc)
 {
        struct ssb_bus *bus = pc->dev->bus;
        u16 chipid_top;
@@ -412,7 +412,7 @@ static int pcicore_is_in_hostmode(struct ssb_pcicore *pc)
  * Workarounds.
  **************************************************/
 
-static void ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_fix_sprom_core_index(struct ssb_pcicore *pc)
 {
        u16 tmp = pcicore_read16(pc, SSB_PCICORE_SPROM(0));
        if (((tmp & 0xF000) >> 12) != pc->dev->core_index) {
@@ -514,13 +514,13 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
  * Generic and Clientmode operation code.
  **************************************************/
 
-static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
+static void __devinit ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
 {
        /* Disable PCI interrupts. */
        ssb_write32(pc->dev, SSB_INTVEC, 0);
 }
 
-void ssb_pcicore_init(struct ssb_pcicore *pc)
+void __devinit ssb_pcicore_init(struct ssb_pcicore *pc)
 {
        struct ssb_device *dev = pc->dev;
 
index f8a13f8..e568664 100644 (file)
@@ -557,7 +557,7 @@ error:
 }
 
 /* Needs ssb_buses_lock() */
-static int ssb_attach_queued_buses(void)
+static int __devinit ssb_attach_queued_buses(void)
 {
        struct ssb_bus *bus, *n;
        int err = 0;
@@ -768,9 +768,9 @@ out:
        return err;
 }
 
-static int ssb_bus_register(struct ssb_bus *bus,
-                           ssb_invariants_func_t get_invariants,
-                           unsigned long baseaddr)
+static int __devinit ssb_bus_register(struct ssb_bus *bus,
+                                     ssb_invariants_func_t get_invariants,
+                                     unsigned long baseaddr)
 {
        int err;
 
@@ -851,8 +851,8 @@ err_disable_xtal:
 }
 
 #ifdef CONFIG_SSB_PCIHOST
-int ssb_bus_pcibus_register(struct ssb_bus *bus,
-                           struct pci_dev *host_pci)
+int __devinit ssb_bus_pcibus_register(struct ssb_bus *bus,
+                                     struct pci_dev *host_pci)
 {
        int err;
 
@@ -875,9 +875,9 @@ EXPORT_SYMBOL(ssb_bus_pcibus_register);
 #endif /* CONFIG_SSB_PCIHOST */
 
 #ifdef CONFIG_SSB_PCMCIAHOST
-int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
-                              struct pcmcia_device *pcmcia_dev,
-                              unsigned long baseaddr)
+int __devinit ssb_bus_pcmciabus_register(struct ssb_bus *bus,
+                                        struct pcmcia_device *pcmcia_dev,
+                                        unsigned long baseaddr)
 {
        int err;
 
@@ -897,8 +897,9 @@ EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
 #endif /* CONFIG_SSB_PCMCIAHOST */
 
 #ifdef CONFIG_SSB_SDIOHOST
-int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
-                            unsigned int quirks)
+int __devinit ssb_bus_sdiobus_register(struct ssb_bus *bus,
+                                      struct sdio_func *func,
+                                      unsigned int quirks)
 {
        int err;
 
@@ -918,9 +919,9 @@ int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
 EXPORT_SYMBOL(ssb_bus_sdiobus_register);
 #endif /* CONFIG_SSB_PCMCIAHOST */
 
-int ssb_bus_ssbbus_register(struct ssb_bus *bus,
-                           unsigned long baseaddr,
-                           ssb_invariants_func_t get_invariants)
+int __devinit ssb_bus_ssbbus_register(struct ssb_bus *bus,
+                                     unsigned long baseaddr,
+                                     ssb_invariants_func_t get_invariants)
 {
        int err;
 
index f6c8c81..d7a9813 100644 (file)
@@ -53,8 +53,8 @@ static int ssb_pcihost_resume(struct pci_dev *dev)
 # define ssb_pcihost_resume    NULL
 #endif /* CONFIG_PM */
 
-static int ssb_pcihost_probe(struct pci_dev *dev,
-                            const struct pci_device_id *id)
+static int __devinit ssb_pcihost_probe(struct pci_dev *dev,
+                                      const struct pci_device_id *id)
 {
        struct ssb_bus *ssb;
        int err = -ENOMEM;
@@ -110,7 +110,7 @@ static void ssb_pcihost_remove(struct pci_dev *dev)
        pci_set_drvdata(dev, NULL);
 }
 
-int ssb_pcihost_register(struct pci_driver *driver)
+int __devinit ssb_pcihost_register(struct pci_driver *driver)
 {
        driver->probe = ssb_pcihost_probe;
        driver->remove = ssb_pcihost_remove;
index 60a7c49..6e3f54f 100644 (file)
@@ -30,6 +30,8 @@ struct ath9k_platform_data {
        u32 gpio_val;
 
        bool is_clk_25mhz;
+       int (*get_mac_revision)(void);
+       int (*external_reset)(void);
 };
 
 #endif /* _LINUX_ATH9K_PLATFORM_H */
index 6ff080e..3895aeb 100644 (file)
@@ -244,6 +244,7 @@ void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value)
 }
 
 extern bool bcma_core_is_enabled(struct bcma_device *core);
+extern void bcma_core_disable(struct bcma_device *core, u32 flags);
 extern int bcma_core_enable(struct bcma_device *core, u32 flags);
 
 #endif /* LINUX_BCMA_H_ */
index b7e191c..3871b66 100644 (file)
@@ -85,5 +85,7 @@ struct bcma_drv_pci {
 #define pcicore_write32(pc, offset, val)       bcma_write32((pc)->core, offset, val)
 
 extern void bcma_core_pci_init(struct bcma_drv_pci *pc);
+extern int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc,
+                                struct bcma_device *core, bool enable);
 
 #endif /* LINUX_BCMA_DRIVER_PCI_H_ */
index fdd0188..2e17c5d 100644 (file)
@@ -49,6 +49,7 @@ struct nlmsghdr {
 #define NLM_F_MULTI            2       /* Multipart message, terminated by NLMSG_DONE */
 #define NLM_F_ACK              4       /* Reply with ack, with zero or error code */
 #define NLM_F_ECHO             8       /* Echo this request            */
+#define NLM_F_DUMP_INTR                16      /* Dump was inconsistent due to sequence change */
 
 /* Modifiers to GET request */
 #define NLM_F_ROOT     0x100   /* specify tree root    */
@@ -223,6 +224,7 @@ struct netlink_callback {
        int                     (*done)(struct netlink_callback *cb);
        u16                     family;
        u16                     min_dump_alloc;
+       unsigned int            prev_seq, seq;
        long                    args[6];
 };
 
index 4375043..7bccaf9 100644 (file)
@@ -69,6 +69,13 @@ struct bt_security {
 #define BT_FLUSHABLE_OFF       0
 #define BT_FLUSHABLE_ON                1
 
+#define BT_POWER       9
+struct bt_power {
+       __u8 force_active;
+};
+#define BT_POWER_FORCE_ACTIVE_OFF 0
+#define BT_POWER_FORCE_ACTIVE_ON  1
+
 #define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
 #define BT_ERR(fmt, arg...)  printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
 #define BT_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -130,7 +137,8 @@ int  bt_sock_register(int proto, const struct net_proto_family *ops);
 int  bt_sock_unregister(int proto);
 void bt_sock_link(struct bt_sock_list *l, struct sock *s);
 void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
-int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags);
+int  bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
+                               struct msghdr *msg, size_t len, int flags);
 int  bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                        struct msghdr *msg, size_t len, int flags);
 uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
@@ -150,6 +158,7 @@ struct bt_skb_cb {
        __u8 retries;
        __u8 sar;
        unsigned short channel;
+       __u8 force_active;
 };
 #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
 
@@ -164,8 +173,8 @@ static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how)
        return skb;
 }
 
-static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, unsigned long len, 
-                                                       int nb, int *err)
+static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk,
+                                       unsigned long len, int nb, int *err)
 {
        struct sk_buff *skb;
 
index 0c20227..65345cd 100644 (file)
@@ -710,6 +710,12 @@ struct hci_rp_le_read_buffer_size {
        __u8     le_max_pkt;
 } __packed;
 
+#define HCI_OP_LE_SET_SCAN_ENABLE      0x200c
+struct hci_cp_le_set_scan_enable {
+       __u8     enable;
+       __u8     filter_dup;
+} __packed;
+
 #define HCI_OP_LE_CREATE_CONN          0x200d
 struct hci_cp_le_create_conn {
        __le16   scan_interval;
@@ -739,6 +745,33 @@ struct hci_cp_le_conn_update {
        __le16   max_ce_len;
 } __packed;
 
+#define HCI_OP_LE_START_ENC            0x2019
+struct hci_cp_le_start_enc {
+       __le16  handle;
+       __u8    rand[8];
+       __le16  ediv;
+       __u8    ltk[16];
+} __packed;
+
+#define HCI_OP_LE_LTK_REPLY            0x201a
+struct hci_cp_le_ltk_reply {
+       __le16  handle;
+       __u8    ltk[16];
+} __packed;
+struct hci_rp_le_ltk_reply {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
+#define HCI_OP_LE_LTK_NEG_REPLY                0x201b
+struct hci_cp_le_ltk_neg_reply {
+       __le16  handle;
+} __packed;
+struct hci_rp_le_ltk_neg_reply {
+       __u8    status;
+       __le16  handle;
+} __packed;
+
 /* ---- HCI Events ---- */
 #define HCI_EV_INQUIRY_COMPLETE                0x01
 
@@ -1029,6 +1062,32 @@ struct hci_ev_le_conn_complete {
        __u8     clk_accurancy;
 } __packed;
 
+#define HCI_EV_LE_LTK_REQ              0x05
+struct hci_ev_le_ltk_req {
+       __le16  handle;
+       __u8    random[8];
+       __le16  ediv;
+} __packed;
+
+/* Advertising report event types */
+#define ADV_IND                0x00
+#define ADV_DIRECT_IND 0x01
+#define ADV_SCAN_IND   0x02
+#define ADV_NONCONN_IND        0x03
+#define ADV_SCAN_RSP   0x04
+
+#define ADDR_LE_DEV_PUBLIC     0x00
+#define ADDR_LE_DEV_RANDOM     0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT   0x02
+struct hci_ev_le_advertising_info {
+       __u8     evt_type;
+       __u8     bdaddr_type;
+       bdaddr_t bdaddr;
+       __u8     length;
+       __u8     data[0];
+} __packed;
+
 /* Internal events generated by Bluetooth stack */
 #define HCI_EV_STACK_INTERNAL  0xfd
 struct hci_ev_stack_internal {
index 7851c05..19639df 100644 (file)
@@ -90,6 +90,12 @@ struct oob_data {
        u8 randomizer[16];
 };
 
+struct adv_entry {
+       struct list_head list;
+       bdaddr_t bdaddr;
+       u8 bdaddr_type;
+};
+
 #define NUM_REASSEMBLY 4
 struct hci_dev {
        struct list_head list;
@@ -172,6 +178,8 @@ struct hci_dev {
 
        __u16                   init_last_cmd;
 
+       struct crypto_blkcipher *tfm;
+
        struct inquiry_cache    inq_cache;
        struct hci_conn_hash    conn_hash;
        struct list_head        blacklist;
@@ -182,6 +190,9 @@ struct hci_dev {
 
        struct list_head        remote_oob_data;
 
+       struct list_head        adv_entries;
+       struct timer_list       adv_timer;
+
        struct hci_dev_stats    stat;
 
        struct sk_buff_head     driver_init;
@@ -216,6 +227,7 @@ struct hci_conn {
        spinlock_t      lock;
 
        bdaddr_t        dst;
+       __u8            dst_type;
        __u16           handle;
        __u16           state;
        __u8            mode;
@@ -238,6 +250,7 @@ struct hci_conn {
        __u8            power_save;
        __u16           disc_timeout;
        unsigned long   pend;
+       __u8            ltk[16];
 
        __u8            remote_cap;
        __u8            remote_oob;
@@ -308,12 +321,14 @@ static inline long inquiry_entry_age(struct inquiry_entry *e)
        return jiffies - e->timestamp;
 }
 
-struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
+                                                       bdaddr_t *bdaddr);
 void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
 
 /* ----- HCI Connections ----- */
 enum {
        HCI_CONN_AUTH_PEND,
+       HCI_CONN_REAUTH_PEND,
        HCI_CONN_ENCRYPT_PEND,
        HCI_CONN_RSWITCH_PEND,
        HCI_CONN_MODE_CHANGE_PEND,
@@ -421,14 +436,15 @@ int hci_conn_del(struct hci_conn *conn);
 void hci_conn_hash_flush(struct hci_dev *hdev);
 void hci_conn_check_pending(struct hci_dev *hdev);
 
-struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
+                                               __u8 sec_level, __u8 auth_type);
 int hci_conn_check_link_mode(struct hci_conn *conn);
 int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
 int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
 int hci_conn_change_link_key(struct hci_conn *conn);
 int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
 
-void hci_conn_enter_active_mode(struct hci_conn *conn);
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
 void hci_conn_enter_sniff_mode(struct hci_conn *conn);
 
 void hci_conn_hold_device(struct hci_conn *conn);
@@ -450,10 +466,12 @@ static inline void hci_conn_put(struct hci_conn *conn)
                                timeo = msecs_to_jiffies(conn->disc_timeout);
                                if (!conn->out)
                                        timeo *= 2;
-                       } else
+                       } else {
                                timeo = msecs_to_jiffies(10);
-               } else
+                       }
+               } else {
                        timeo = msecs_to_jiffies(10);
+               }
                mod_timer(&conn->disc_timer, jiffies + timeo);
        }
 }
@@ -512,6 +530,8 @@ int hci_inquiry(void __user *arg);
 
 struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
 int hci_blacklist_clear(struct hci_dev *hdev);
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
 int hci_uuids_clear(struct hci_dev *hdev);
 
@@ -528,6 +548,12 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
                                                                u8 *randomizer);
 int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
 
+#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
+int hci_adv_entries_clear(struct hci_dev *hdev);
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_add_adv_entry(struct hci_dev *hdev,
+                                       struct hci_ev_le_advertising_info *ev);
+
 void hci_del_off_timer(struct hci_dev *hdev);
 
 void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -562,16 +588,20 @@ struct hci_proto {
 
        void            *priv;
 
-       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
+       int (*connect_ind)      (struct hci_dev *hdev, bdaddr_t *bdaddr,
+                                                               __u8 type);
        int (*connect_cfm)      (struct hci_conn *conn, __u8 status);
        int (*disconn_ind)      (struct hci_conn *conn);
        int (*disconn_cfm)      (struct hci_conn *conn, __u8 reason);
-       int (*recv_acldata)     (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+       int (*recv_acldata)     (struct hci_conn *conn, struct sk_buff *skb,
+                                                               __u16 flags);
        int (*recv_scodata)     (struct hci_conn *conn, struct sk_buff *skb);
-       int (*security_cfm)     (struct hci_conn *conn, __u8 status, __u8 encrypt);
+       int (*security_cfm)     (struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt);
 };
 
-static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
+static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
+                                                               __u8 type)
 {
        register struct hci_proto *hp;
        int mask = 0;
@@ -657,7 +687,8 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
                conn->security_cfm_cb(conn, status);
 }
 
-static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt)
 {
        register struct hci_proto *hp;
 
@@ -682,7 +713,8 @@ struct hci_cb {
 
        char *name;
 
-       void (*security_cfm)    (struct hci_conn *conn, __u8 status, __u8 encrypt);
+       void (*security_cfm)    (struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt);
        void (*key_change_cfm)  (struct hci_conn *conn, __u8 status);
        void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
 };
@@ -708,13 +740,17 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
        read_unlock_bh(&hci_cb_list_lock);
 }
 
-static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
+static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
+                                                               __u8 encrypt)
 {
        struct list_head *p;
 
        if (conn->sec_level == BT_SECURITY_SDP)
                conn->sec_level = BT_SECURITY_LOW;
 
+       if (conn->pending_sec_level > conn->sec_level)
+               conn->sec_level = conn->pending_sec_level;
+
        hci_proto_encrypt_cfm(conn, status, encrypt);
 
        read_lock_bh(&hci_cb_list_lock);
@@ -739,7 +775,8 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
        read_unlock_bh(&hci_cb_list_lock);
 }
 
-static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
+                                                               __u8 role)
 {
        struct list_head *p;
 
@@ -831,4 +868,9 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
 
 void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
                                        u16 latency, u16 to_multiplier);
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+                                                       __u8 ltk[16]);
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
+void hci_le_ltk_neg_reply(struct hci_conn *conn);
+
 #endif /* __HCI_CORE_H */
index d09c9b1..9c18e55 100644 (file)
@@ -287,6 +287,10 @@ struct l2cap_chan {
 
        struct l2cap_conn       *conn;
 
+       __u8            state;
+
+       atomic_t        refcnt;
+
        __le16          psm;
        __u16           dcid;
        __u16           scid;
@@ -295,6 +299,7 @@ struct l2cap_chan {
        __u16           omtu;
        __u16           flush_to;
        __u8            mode;
+       __u8            chan_type;
 
        __le16          sport;
 
@@ -302,6 +307,7 @@ struct l2cap_chan {
        __u8            role_switch;
        __u8            force_reliable;
        __u8            flushable;
+       __u8            force_active;
 
        __u8            ident;
 
@@ -318,8 +324,8 @@ struct l2cap_chan {
        __u16           monitor_timeout;
        __u16           mps;
 
-       __u8            conf_state;
-       __u16           conn_state;
+       unsigned long   conf_state;
+       unsigned long   conn_state;
 
        __u8            next_tx_seq;
        __u8            expected_ack_seq;
@@ -339,6 +345,7 @@ struct l2cap_chan {
        __u8            remote_max_tx;
        __u16           remote_mps;
 
+       struct timer_list       chan_timer;
        struct timer_list       retrans_timer;
        struct timer_list       monitor_timer;
        struct timer_list       ack_timer;
@@ -351,6 +358,18 @@ struct l2cap_chan {
 
        struct list_head list;
        struct list_head global_l;
+
+       void            *data;
+       struct l2cap_ops *ops;
+};
+
+struct l2cap_ops {
+       char            *name;
+
+       struct l2cap_chan       *(*new_connection) (void *data);
+       int                     (*recv) (void *data, struct sk_buff *skb);
+       void                    (*close) (void *data);
+       void                    (*state_change) (void *data, int state);
 };
 
 struct l2cap_conn {
@@ -376,6 +395,15 @@ struct l2cap_conn {
 
        __u8            disc_reason;
 
+       __u8            preq[7]; /* SMP Pairing Request */
+       __u8            prsp[7]; /* SMP Pairing Response */
+       __u8            prnd[16]; /* SMP Pairing Random */
+       __u8            pcnf[16]; /* SMP Pairing Confirm */
+       __u8            tk[16]; /* SMP Temporary Key */
+       __u8            smp_key_size;
+
+       struct timer_list security_timer;
+
        struct list_head chan_l;
        rwlock_t        chan_lock;
 };
@@ -384,6 +412,10 @@ struct l2cap_conn {
 #define L2CAP_INFO_FEAT_MASK_REQ_SENT  0x04
 #define L2CAP_INFO_FEAT_MASK_REQ_DONE  0x08
 
+#define L2CAP_CHAN_RAW                 1
+#define L2CAP_CHAN_CONN_LESS           2
+#define L2CAP_CHAN_CONN_ORIENTED       3
+
 /* ----- L2CAP socket info ----- */
 #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
 
@@ -392,36 +424,45 @@ struct l2cap_pinfo {
        struct l2cap_chan       *chan;
 };
 
-#define L2CAP_CONF_REQ_SENT       0x01
-#define L2CAP_CONF_INPUT_DONE     0x02
-#define L2CAP_CONF_OUTPUT_DONE    0x04
-#define L2CAP_CONF_MTU_DONE       0x08
-#define L2CAP_CONF_MODE_DONE      0x10
-#define L2CAP_CONF_CONNECT_PEND   0x20
-#define L2CAP_CONF_NO_FCS_RECV    0x40
-#define L2CAP_CONF_STATE2_DEVICE  0x80
+enum {
+       CONF_REQ_SENT,
+       CONF_INPUT_DONE,
+       CONF_OUTPUT_DONE,
+       CONF_MTU_DONE,
+       CONF_MODE_DONE,
+       CONF_CONNECT_PEND,
+       CONF_NO_FCS_RECV,
+       CONF_STATE2_DEVICE,
+};
 
 #define L2CAP_CONF_MAX_CONF_REQ 2
 #define L2CAP_CONF_MAX_CONF_RSP 2
 
-#define L2CAP_CONN_SAR_SDU         0x0001
-#define L2CAP_CONN_SREJ_SENT       0x0002
-#define L2CAP_CONN_WAIT_F          0x0004
-#define L2CAP_CONN_SREJ_ACT        0x0008
-#define L2CAP_CONN_SEND_PBIT       0x0010
-#define L2CAP_CONN_REMOTE_BUSY     0x0020
-#define L2CAP_CONN_LOCAL_BUSY      0x0040
-#define L2CAP_CONN_REJ_ACT         0x0080
-#define L2CAP_CONN_SEND_FBIT       0x0100
-#define L2CAP_CONN_RNR_SENT        0x0200
-#define L2CAP_CONN_SAR_RETRY       0x0400
-
-#define __mod_retrans_timer() mod_timer(&chan->retrans_timer, \
-               jiffies +  msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO));
-#define __mod_monitor_timer() mod_timer(&chan->monitor_timer, \
-               jiffies + msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO));
-#define __mod_ack_timer() mod_timer(&chan->ack_timer, \
-               jiffies + msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO));
+enum {
+       CONN_SAR_SDU,
+       CONN_SREJ_SENT,
+       CONN_WAIT_F,
+       CONN_SREJ_ACT,
+       CONN_SEND_PBIT,
+       CONN_REMOTE_BUSY,
+       CONN_LOCAL_BUSY,
+       CONN_REJ_ACT,
+       CONN_SEND_FBIT,
+       CONN_RNR_SENT,
+       CONN_SAR_RETRY,
+};
+
+#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
+#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
+#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
+               L2CAP_DEFAULT_RETRANS_TO);
+#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
+#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
+               L2CAP_DEFAULT_MONITOR_TO);
+#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
+#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
+               L2CAP_DEFAULT_ACK_TO);
+#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
 
 static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
 {
@@ -446,32 +487,16 @@ extern int disable_ertm;
 int l2cap_init_sockets(void);
 void l2cap_cleanup_sockets(void);
 
-void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
 void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
 int __l2cap_wait_ack(struct sock *sk);
 
-struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u16 control, u16 sdulen);
-int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb);
-void l2cap_streaming_send(struct l2cap_chan *chan);
-int l2cap_ertm_send(struct l2cap_chan *chan);
-
 int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
 int l2cap_add_scid(struct l2cap_chan *chan,  __u16 scid);
 
-void l2cap_sock_set_timer(struct sock *sk, long timeout);
-void l2cap_sock_clear_timer(struct sock *sk);
-void __l2cap_sock_close(struct sock *sk, int reason);
-void l2cap_sock_kill(struct sock *sk);
-void l2cap_sock_init(struct sock *sk, struct sock *parent);
-struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
-                                                       int proto, gfp_t prio);
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err);
 struct l2cap_chan *l2cap_chan_create(struct sock *sk);
-void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_chan_close(struct l2cap_chan *chan, int reason);
 void l2cap_chan_destroy(struct l2cap_chan *chan);
 int l2cap_chan_connect(struct l2cap_chan *chan);
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
 
 #endif /* __L2CAP_H */
index 4899286..45bea25 100644 (file)
@@ -199,6 +199,16 @@ struct mgmt_cp_remove_remote_oob_data {
 
 #define MGMT_OP_STOP_DISCOVERY         0x001C
 
+#define MGMT_OP_BLOCK_DEVICE           0x001D
+struct mgmt_cp_block_device {
+       bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_UNBLOCK_DEVICE         0x001E
+struct mgmt_cp_unblock_device {
+       bdaddr_t bdaddr;
+} __packed;
+
 #define MGMT_EV_CMD_COMPLETE           0x0001
 struct mgmt_ev_cmd_complete {
        __le16 opcode;
index 6eac4a7..d5eee20 100644 (file)
@@ -234,7 +234,8 @@ int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
 /* ---- RFCOMM DLCs (channels) ---- */
 struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
 void rfcomm_dlc_free(struct rfcomm_dlc *d);
-int  rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel);
+int  rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
+                                                               u8 channel);
 int  rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
 int  rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
 int  rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
@@ -271,7 +272,8 @@ static inline void rfcomm_dlc_unthrottle(struct rfcomm_dlc *d)
 }
 
 /* ---- RFCOMM sessions ---- */
-void   rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
+void   rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
+                                                               bdaddr_t *dst);
 
 static inline void rfcomm_session_hold(struct rfcomm_session *s)
 {
@@ -312,7 +314,8 @@ struct rfcomm_pinfo {
 int  rfcomm_init_sockets(void);
 void rfcomm_cleanup_sockets(void);
 
-int  rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d);
+int  rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
+                                                       struct rfcomm_dlc **d);
 
 /* ---- RFCOMM TTY ---- */
 #define RFCOMM_MAX_DEV  256
index 8f2edbf..4fb7d19 100644 (file)
@@ -1,3 +1,25 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL 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.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
 #ifndef __SMP_H
 #define __SMP_H
 
@@ -16,6 +38,23 @@ struct smp_cmd_pairing {
        __u8    resp_key_dist;
 } __packed;
 
+#define SMP_IO_DISPLAY_ONLY    0x00
+#define SMP_IO_DISPLAY_YESNO   0x01
+#define SMP_IO_KEYBOARD_ONLY   0x02
+#define SMP_IO_NO_INPUT_OUTPUT 0x03
+#define SMP_IO_KEYBOARD_DISPLAY        0x04
+
+#define SMP_OOB_NOT_PRESENT    0x00
+#define SMP_OOB_PRESENT                0x01
+
+#define SMP_DIST_ENC_KEY       0x01
+#define SMP_DIST_ID_KEY                0x02
+#define SMP_DIST_SIGN          0x04
+
+#define SMP_AUTH_NONE          0x00
+#define SMP_AUTH_BONDING       0x01
+#define SMP_AUTH_MITM          0x04
+
 #define SMP_CMD_PAIRING_CONFIRM        0x03
 struct smp_cmd_pairing_confirm {
        __u8    confirm_val[16];
@@ -73,4 +112,11 @@ struct smp_cmd_security_req {
 #define SMP_UNSPECIFIED                0x08
 #define SMP_REPEATED_ATTEMPTS          0x09
 
+#define SMP_MIN_ENC_KEY_SIZE           7
+#define SMP_MAX_ENC_KEY_SIZE           16
+
+/* SMP Commands */
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
+
 #endif /* __SMP_H */
index d420f28..82d8d09 100644 (file)
@@ -159,6 +159,38 @@ static inline void *genlmsg_put(struct sk_buff *skb, u32 pid, u32 seq,
        return (char *) hdr + GENL_HDRLEN;
 }
 
+/**
+ * genlmsg_nlhdr - Obtain netlink header from user specified header
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Returns pointer to netlink header.
+ */
+static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
+                                            struct genl_family *family)
+{
+       return (struct nlmsghdr *)((char *)user_hdr -
+                                  family->hdrsize -
+                                  GENL_HDRLEN -
+                                  NLMSG_HDRLEN);
+}
+
+/**
+ * genl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @user_hdr: user header as returned from genlmsg_put()
+ * @family: generic netlink family
+ *
+ * Cf. nl_dump_check_consistent(), this just provides a wrapper to make it
+ * simpler to use with generic netlink.
+ */
+static inline void genl_dump_check_consistent(struct netlink_callback *cb,
+                                             void *user_hdr,
+                                             struct genl_family *family)
+{
+       nl_dump_check_consistent(cb, genlmsg_nlhdr(user_hdr, family));
+}
+
 /**
  * genlmsg_put_reply - Add generic netlink header to a reply message
  * @skb: socket buffer holding the message
index 3b31ec9..120f102 100644 (file)
@@ -1708,6 +1708,14 @@ enum ieee80211_ampdu_mlme_action {
  *     any error unless this callback returned a negative error code.
  *     The callback can sleep.
  *
+ * @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
+ *     The driver should ask the hardware to cancel the scan (if possible),
+ *     but the scan will be completed only after the driver will call
+ *     ieee80211_scan_completed().
+ *     This callback is needed for wowlan, to prevent enqueueing a new
+ *     scan_work after the low-level driver was already suspended.
+ *     The callback can sleep.
+ *
  * @sched_scan_start: Ask the hardware to start scanning repeatedly at
  *     specific intervals.  The driver must call the
  *     ieee80211_sched_scan_results() function whenever it finds results.
@@ -1900,6 +1908,8 @@ struct ieee80211_ops {
                                u32 iv32, u16 *phase1key);
        int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                       struct cfg80211_scan_request *req);
+       void (*cancel_hw_scan)(struct ieee80211_hw *hw,
+                              struct ieee80211_vif *vif);
        int (*sched_scan_start)(struct ieee80211_hw *hw,
                                struct ieee80211_vif *vif,
                                struct cfg80211_sched_scan_request *req,
@@ -2919,6 +2929,16 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
                               enum nl80211_cqm_rssi_threshold_event rssi_event,
                               gfp_t gfp);
 
+/**
+ * ieee80211_get_operstate - get the operstate of the vif
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * The driver might need to know the operstate of the net_device
+ * (specifically, whether the link is IF_OPER_UP after resume)
+ */
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif);
+
 /**
  * ieee80211_chswitch_done - Complete channel switch process
  * @vif: &struct ieee80211_vif pointer from the add_interface callback.
index 02740a9..98c1854 100644 (file)
@@ -638,6 +638,30 @@ static inline int nlmsg_unicast(struct sock *sk, struct sk_buff *skb, u32 pid)
             nlmsg_ok(pos, rem); \
             pos = nlmsg_next(pos, &(rem)))
 
+/**
+ * nl_dump_check_consistent - check if sequence is consistent and advertise if not
+ * @cb: netlink callback structure that stores the sequence number
+ * @nlh: netlink message header to write the flag to
+ *
+ * This function checks if the sequence (generation) number changed during dump
+ * and if it did, advertises it in the netlink message header.
+ *
+ * The correct way to use it is to set cb->seq to the generation counter when
+ * all locks for dumping have been acquired, and then call this function for
+ * each message that is generated.
+ *
+ * Note that due to initialisation concerns, 0 is an invalid sequence number
+ * and must not be used by code that uses this functionality.
+ */
+static inline void
+nl_dump_check_consistent(struct netlink_callback *cb,
+                        struct nlmsghdr *nlh)
+{
+       if (cb->prev_seq && cb->seq != cb->prev_seq)
+               nlh->nlmsg_flags |= NLM_F_DUMP_INTR;
+       cb->prev_seq = cb->seq;
+}
+
 /**************************************************************************
  * Netlink Attributes
  **************************************************************************/
index 6ae5ec5..f495dea 100644 (file)
@@ -22,6 +22,7 @@ menuconfig BT
             BNEP Module (Bluetooth Network Encapsulation Protocol)
             CMTP Module (CAPI Message Transport Protocol)
             HIDP Module (Human Interface Device Protocol)
+            SMP Module (Security Manager Protocol)
 
          Say Y here to compile Bluetooth support into the kernel or say M to
          compile it as module (bluetooth).
@@ -36,11 +37,18 @@ if BT != n
 config BT_L2CAP
        bool "L2CAP protocol support"
        select CRC16
+       select CRYPTO
+       select CRYPTO_BLKCIPHER
+       select CRYPTO_AES
+       select CRYPTO_ECB
        help
          L2CAP (Logical Link Control and Adaptation Protocol) provides
          connection oriented and connection-less data transport.  L2CAP
          support is required for most Bluetooth applications.
 
+         Also included is support for SMP (Security Manager Protocol) which
+         is the security layer on top of LE (Low Energy) links.
+
 config BT_SCO
        bool "SCO links support"
        help
index f04fe9a..9b67f3d 100644 (file)
@@ -9,5 +9,5 @@ obj-$(CONFIG_BT_CMTP)   += cmtp/
 obj-$(CONFIG_BT_HIDP)  += hidp/
 
 bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o hci_sock.o hci_sysfs.o lib.o
-bluetooth-$(CONFIG_BT_L2CAP)   += l2cap_core.o l2cap_sock.o
+bluetooth-$(CONFIG_BT_L2CAP)   += l2cap_core.o l2cap_sock.o smp.o
 bluetooth-$(CONFIG_BT_SCO)     += sco.o
index 744233c..040f67b 100644 (file)
@@ -326,7 +326,7 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
 {
        struct capi_ctr *ctrl = &session->ctrl;
        struct cmtp_application *application;
-       __u16 cmd, appl;
+       __u16 appl;
        __u32 contr;
 
        BT_DBG("session %p skb %p len %d", session, skb, skb->len);
@@ -344,7 +344,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
                return;
        }
 
-       cmd = CAPICMD(CAPIMSG_COMMAND(skb->data), CAPIMSG_SUBCOMMAND(skb->data));
        appl = CAPIMSG_APPID(skb->data);
        contr = CAPIMSG_CONTROL(skb->data);
 
index 3163330..fa48c0b 100644 (file)
@@ -53,11 +53,13 @@ static void hci_le_connect(struct hci_conn *conn)
        conn->state = BT_CONNECT;
        conn->out = 1;
        conn->link_mode |= HCI_LM_MASTER;
+       conn->sec_level = BT_SECURITY_LOW;
 
        memset(&cp, 0, sizeof(cp));
        cp.scan_interval = cpu_to_le16(0x0004);
        cp.scan_window = cpu_to_le16(0x0004);
        bacpy(&cp.peer_addr, &conn->dst);
+       cp.peer_addr_type = conn->dst_type;
        cp.conn_interval_min = cpu_to_le16(0x0008);
        cp.conn_interval_max = cpu_to_le16(0x0100);
        cp.supervision_timeout = cpu_to_le16(0x0064);
@@ -203,6 +205,55 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
 }
 EXPORT_SYMBOL(hci_le_conn_update);
 
+void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
+                                                       __u8 ltk[16])
+{
+       struct hci_dev *hdev = conn->hdev;
+       struct hci_cp_le_start_enc cp;
+
+       BT_DBG("%p", conn);
+
+       memset(&cp, 0, sizeof(cp));
+
+       cp.handle = cpu_to_le16(conn->handle);
+       memcpy(cp.ltk, ltk, sizeof(cp.ltk));
+       cp.ediv = ediv;
+       memcpy(cp.rand, rand, sizeof(rand));
+
+       hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_start_enc);
+
+void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16])
+{
+       struct hci_dev *hdev = conn->hdev;
+       struct hci_cp_le_ltk_reply cp;
+
+       BT_DBG("%p", conn);
+
+       memset(&cp, 0, sizeof(cp));
+
+       cp.handle = cpu_to_le16(conn->handle);
+       memcpy(cp.ltk, ltk, sizeof(ltk));
+
+       hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_ltk_reply);
+
+void hci_le_ltk_neg_reply(struct hci_conn *conn)
+{
+       struct hci_dev *hdev = conn->hdev;
+       struct hci_cp_le_ltk_neg_reply cp;
+
+       BT_DBG("%p", conn);
+
+       memset(&cp, 0, sizeof(cp));
+
+       cp.handle = cpu_to_le16(conn->handle);
+
+       hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(cp), &cp);
+}
+
 /* Device _must_ be locked */
 void hci_sco_setup(struct hci_conn *conn, __u8 status)
 {
@@ -447,14 +498,23 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
        BT_DBG("%s dst %s", hdev->name, batostr(dst));
 
        if (type == LE_LINK) {
+               struct adv_entry *entry;
+
                le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
                if (le)
                        return ERR_PTR(-EBUSY);
+
+               entry = hci_find_adv_entry(hdev, dst);
+               if (!entry)
+                       return ERR_PTR(-EHOSTUNREACH);
+
                le = hci_conn_add(hdev, LE_LINK, dst);
                if (!le)
                        return ERR_PTR(-ENOMEM);
-               if (le->state == BT_OPEN)
-                       hci_le_connect(le);
+
+               le->dst_type = entry->bdaddr_type;
+
+               hci_le_connect(le);
 
                hci_conn_hold(le);
 
@@ -497,7 +557,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
        if (acl->state == BT_CONNECTED &&
                        (sco->state == BT_OPEN || sco->state == BT_CLOSED)) {
                acl->power_save = 1;
-               hci_conn_enter_active_mode(acl);
+               hci_conn_enter_active_mode(acl, BT_POWER_FORCE_ACTIVE_ON);
 
                if (test_bit(HCI_CONN_MODE_CHANGE_PEND, &acl->pend)) {
                        /* defer SCO setup until mode change completed */
@@ -548,6 +608,8 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
                cp.handle = cpu_to_le16(conn->handle);
                hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED,
                                                        sizeof(cp), &cp);
+               if (conn->key_type != 0xff)
+                       set_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
        }
 
        return 0;
@@ -608,11 +670,11 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
                goto encrypt;
 
 auth:
-       if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
                return 0;
 
-       hci_conn_auth(conn, sec_level, auth_type);
-       return 0;
+       if (!hci_conn_auth(conn, sec_level, auth_type))
+               return 0;
 
 encrypt:
        if (conn->link_mode & HCI_LM_ENCRYPT)
@@ -631,9 +693,7 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level)
        if (sec_level != BT_SECURITY_HIGH)
                return 1; /* Accept if non-secure is required */
 
-       if (conn->key_type == HCI_LK_AUTH_COMBINATION ||
-                       (conn->key_type == HCI_LK_COMBINATION &&
-                       conn->pin_length == 16))
+       if (conn->sec_level == BT_SECURITY_HIGH)
                return 1;
 
        return 0; /* Reject not secure link */
@@ -676,7 +736,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role)
 EXPORT_SYMBOL(hci_conn_switch_role);
 
 /* Enter active mode */
-void hci_conn_enter_active_mode(struct hci_conn *conn)
+void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
 {
        struct hci_dev *hdev = conn->hdev;
 
@@ -685,7 +745,10 @@ void hci_conn_enter_active_mode(struct hci_conn *conn)
        if (test_bit(HCI_RAW, &hdev->flags))
                return;
 
-       if (conn->mode != HCI_CM_SNIFF || !conn->power_save)
+       if (conn->mode != HCI_CM_SNIFF)
+               goto timer;
+
+       if (!conn->power_save && !force_active)
                goto timer;
 
        if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) {
index e937ada..b18db56 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/notifier.h>
 #include <linux/rfkill.h>
 #include <linux/timer.h>
+#include <linux/crypto.h>
 #include <net/sock.h>
 
 #include <asm/system.h>
@@ -59,6 +60,8 @@ static void hci_tx_task(unsigned long arg);
 
 static DEFINE_RWLOCK(hci_task_lock);
 
+static int enable_smp;
+
 /* HCI device list */
 LIST_HEAD(hci_dev_list);
 DEFINE_RWLOCK(hci_dev_list_lock);
@@ -1202,6 +1205,177 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
        return 0;
 }
 
+struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
+                                               bdaddr_t *bdaddr)
+{
+       struct list_head *p;
+
+       list_for_each(p, &hdev->blacklist) {
+               struct bdaddr_list *b;
+
+               b = list_entry(p, struct bdaddr_list, list);
+
+               if (bacmp(bdaddr, &b->bdaddr) == 0)
+                       return b;
+       }
+
+       return NULL;
+}
+
+int hci_blacklist_clear(struct hci_dev *hdev)
+{
+       struct list_head *p, *n;
+
+       list_for_each_safe(p, n, &hdev->blacklist) {
+               struct bdaddr_list *b;
+
+               b = list_entry(p, struct bdaddr_list, list);
+
+               list_del(p);
+               kfree(b);
+       }
+
+       return 0;
+}
+
+int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+       struct bdaddr_list *entry;
+       int err;
+
+       if (bacmp(bdaddr, BDADDR_ANY) == 0)
+               return -EBADF;
+
+       hci_dev_lock(hdev);
+
+       if (hci_blacklist_lookup(hdev, bdaddr)) {
+               err = -EEXIST;
+               goto err;
+       }
+
+       entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
+       if (!entry) {
+               return -ENOMEM;
+               goto err;
+       }
+
+       bacpy(&entry->bdaddr, bdaddr);
+
+       list_add(&entry->list, &hdev->blacklist);
+
+       err = 0;
+
+err:
+       hci_dev_unlock(hdev);
+       return err;
+}
+
+int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+       struct bdaddr_list *entry;
+       int err = 0;
+
+       hci_dev_lock(hdev);
+
+       if (bacmp(bdaddr, BDADDR_ANY) == 0) {
+               hci_blacklist_clear(hdev);
+               goto done;
+       }
+
+       entry = hci_blacklist_lookup(hdev, bdaddr);
+       if (!entry) {
+               err = -ENOENT;
+               goto done;
+       }
+
+       list_del(&entry->list);
+       kfree(entry);
+
+done:
+       hci_dev_unlock(hdev);
+       return err;
+}
+
+static void hci_clear_adv_cache(unsigned long arg)
+{
+       struct hci_dev *hdev = (void *) arg;
+
+       hci_dev_lock(hdev);
+
+       hci_adv_entries_clear(hdev);
+
+       hci_dev_unlock(hdev);
+}
+
+int hci_adv_entries_clear(struct hci_dev *hdev)
+{
+       struct adv_entry *entry, *tmp;
+
+       list_for_each_entry_safe(entry, tmp, &hdev->adv_entries, list) {
+               list_del(&entry->list);
+               kfree(entry);
+       }
+
+       BT_DBG("%s adv cache cleared", hdev->name);
+
+       return 0;
+}
+
+struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr)
+{
+       struct adv_entry *entry;
+
+       list_for_each_entry(entry, &hdev->adv_entries, list)
+               if (bacmp(bdaddr, &entry->bdaddr) == 0)
+                       return entry;
+
+       return NULL;
+}
+
+static inline int is_connectable_adv(u8 evt_type)
+{
+       if (evt_type == ADV_IND || evt_type == ADV_DIRECT_IND)
+               return 1;
+
+       return 0;
+}
+
+int hci_add_adv_entry(struct hci_dev *hdev,
+                                       struct hci_ev_le_advertising_info *ev)
+{
+       struct adv_entry *entry;
+
+       if (!is_connectable_adv(ev->evt_type))
+               return -EINVAL;
+
+       /* Only new entries should be added to adv_entries. So, if
+        * bdaddr was found, don't add it. */
+       if (hci_find_adv_entry(hdev, &ev->bdaddr))
+               return 0;
+
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
+       if (!entry)
+               return -ENOMEM;
+
+       bacpy(&entry->bdaddr, &ev->bdaddr);
+       entry->bdaddr_type = ev->bdaddr_type;
+
+       list_add(&entry->list, &hdev->adv_entries);
+
+       BT_DBG("%s adv entry added: address %s type %u", hdev->name,
+                               batostr(&entry->bdaddr), entry->bdaddr_type);
+
+       return 0;
+}
+
+static struct crypto_blkcipher *alloc_cypher(void)
+{
+       if (enable_smp)
+               return crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+
+       return ERR_PTR(-ENOTSUPP);
+}
+
 /* Register HCI device */
 int hci_register_dev(struct hci_dev *hdev)
 {
@@ -1268,6 +1442,10 @@ int hci_register_dev(struct hci_dev *hdev)
 
        INIT_LIST_HEAD(&hdev->remote_oob_data);
 
+       INIT_LIST_HEAD(&hdev->adv_entries);
+       setup_timer(&hdev->adv_timer, hci_clear_adv_cache,
+                                               (unsigned long) hdev);
+
        INIT_WORK(&hdev->power_on, hci_power_on);
        INIT_WORK(&hdev->power_off, hci_power_off);
        setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
@@ -1282,6 +1460,11 @@ int hci_register_dev(struct hci_dev *hdev)
        if (!hdev->workqueue)
                goto nomem;
 
+       hdev->tfm = alloc_cypher();
+       if (IS_ERR(hdev->tfm))
+               BT_INFO("Failed to load transform for ecb(aes): %ld",
+                                                       PTR_ERR(hdev->tfm));
+
        hci_register_sysfs(hdev);
 
        hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
@@ -1330,6 +1513,9 @@ int hci_unregister_dev(struct hci_dev *hdev)
                                        !test_bit(HCI_SETUP, &hdev->flags))
                mgmt_index_removed(hdev->id);
 
+       if (!IS_ERR(hdev->tfm))
+               crypto_free_blkcipher(hdev->tfm);
+
        hci_notify(hdev, HCI_DEV_UNREG);
 
        if (hdev->rfkill) {
@@ -1340,6 +1526,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
        hci_unregister_sysfs(hdev);
 
        hci_del_off_timer(hdev);
+       del_timer(&hdev->adv_timer);
 
        destroy_workqueue(hdev->workqueue);
 
@@ -1348,6 +1535,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
        hci_uuids_clear(hdev);
        hci_link_keys_clear(hdev);
        hci_remote_oob_data_clear(hdev);
+       hci_adv_entries_clear(hdev);
        hci_dev_unlock_bh(hdev);
 
        __hci_dev_put(hdev);
@@ -1891,7 +2079,7 @@ static inline void hci_sched_acl(struct hci_dev *hdev)
                while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
                        BT_DBG("skb %p len %d", skb, skb->len);
 
-                       hci_conn_enter_active_mode(conn);
+                       hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
 
                        hci_send_frame(skb);
                        hdev->acl_last_tx = jiffies;
@@ -2030,7 +2218,7 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
        if (conn) {
                register struct hci_proto *hp;
 
-               hci_conn_enter_active_mode(conn);
+               hci_conn_enter_active_mode(conn, bt_cb(skb)->force_active);
 
                /* Send to upper protocol */
                hp = hci_proto[HCI_PROTO_L2CAP];
@@ -2164,3 +2352,6 @@ static void hci_cmd_task(unsigned long arg)
                }
        }
 }
+
+module_param(enable_smp, bool, 0644);
+MODULE_PARM_DESC(enable_smp, "Enable SMP support (LE only)");
index 77930aa..ac2c5e8 100644 (file)
@@ -841,6 +841,57 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
                                                rp->randomizer, rp->status);
 }
 
+static void hci_cc_le_set_scan_enable(struct hci_dev *hdev,
+                                       struct sk_buff *skb)
+{
+       struct hci_cp_le_set_scan_enable *cp;
+       __u8 status = *((__u8 *) skb->data);
+
+       BT_DBG("%s status 0x%x", hdev->name, status);
+
+       if (status)
+               return;
+
+       cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
+       if (!cp)
+               return;
+
+       hci_dev_lock(hdev);
+
+       if (cp->enable == 0x01) {
+               del_timer(&hdev->adv_timer);
+               hci_adv_entries_clear(hdev);
+       } else if (cp->enable == 0x00) {
+               mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT);
+       }
+
+       hci_dev_unlock(hdev);
+}
+
+static void hci_cc_le_ltk_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_rp_le_ltk_reply *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+       if (rp->status)
+               return;
+
+       hci_req_complete(hdev, HCI_OP_LE_LTK_REPLY, rp->status);
+}
+
+static void hci_cc_le_ltk_neg_reply(struct hci_dev *hdev, struct sk_buff *skb)
+{
+       struct hci_rp_le_ltk_neg_reply *rp = (void *) skb->data;
+
+       BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+       if (rp->status)
+               return;
+
+       hci_req_complete(hdev, HCI_OP_LE_LTK_NEG_REPLY, rp->status);
+}
+
 static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
 {
        BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1209,16 +1260,23 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status)
        } else {
                if (!conn) {
                        conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr);
-                       if (conn)
+                       if (conn) {
+                               conn->dst_type = cp->peer_addr_type;
                                conn->out = 1;
-                       else
+                       } else {
                                BT_ERR("No memory for new connection");
+                       }
                }
        }
 
        hci_dev_unlock(hdev);
 }
 
+static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
+{
+       BT_DBG("%s status 0x%x", hdev->name, status);
+}
+
 static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        __u8 status = *((__u8 *) skb->data);
@@ -1462,51 +1520,58 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
        hci_dev_lock(hdev);
 
        conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
-       if (conn) {
-               if (!ev->status) {
+       if (!conn)
+               goto unlock;
+
+       if (!ev->status) {
+               if (!(conn->ssp_mode > 0 && hdev->ssp_mode > 0) &&
+                               test_bit(HCI_CONN_REAUTH_PEND,  &conn->pend)) {
+                       BT_INFO("re-auth of legacy device is not possible.");
+               } else {
                        conn->link_mode |= HCI_LM_AUTH;
                        conn->sec_level = conn->pending_sec_level;
-               } else {
-                       mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
                }
+       } else {
+               mgmt_auth_failed(hdev->id, &conn->dst, ev->status);
+       }
 
-               clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+       clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+       clear_bit(HCI_CONN_REAUTH_PEND, &conn->pend);
 
-               if (conn->state == BT_CONFIG) {
-                       if (!ev->status && hdev->ssp_mode > 0 &&
-                                                       conn->ssp_mode > 0) {
-                               struct hci_cp_set_conn_encrypt cp;
-                               cp.handle  = ev->handle;
-                               cp.encrypt = 0x01;
-                               hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
-                                                       sizeof(cp), &cp);
-                       } else {
-                               conn->state = BT_CONNECTED;
-                               hci_proto_connect_cfm(conn, ev->status);
-                               hci_conn_put(conn);
-                       }
+       if (conn->state == BT_CONFIG) {
+               if (!ev->status && hdev->ssp_mode > 0 && conn->ssp_mode > 0) {
+                       struct hci_cp_set_conn_encrypt cp;
+                       cp.handle  = ev->handle;
+                       cp.encrypt = 0x01;
+                       hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+                                                                       &cp);
                } else {
-                       hci_auth_cfm(conn, ev->status);
-
-                       hci_conn_hold(conn);
-                       conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+                       conn->state = BT_CONNECTED;
+                       hci_proto_connect_cfm(conn, ev->status);
                        hci_conn_put(conn);
                }
+       } else {
+               hci_auth_cfm(conn, ev->status);
 
-               if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
-                       if (!ev->status) {
-                               struct hci_cp_set_conn_encrypt cp;
-                               cp.handle  = ev->handle;
-                               cp.encrypt = 0x01;
-                               hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT,
-                                                       sizeof(cp), &cp);
-                       } else {
-                               clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
-                               hci_encrypt_cfm(conn, ev->status, 0x00);
-                       }
+               hci_conn_hold(conn);
+               conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+               hci_conn_put(conn);
+       }
+
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) {
+               if (!ev->status) {
+                       struct hci_cp_set_conn_encrypt cp;
+                       cp.handle  = ev->handle;
+                       cp.encrypt = 0x01;
+                       hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
+                                                                       &cp);
+               } else {
+                       clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
+                       hci_encrypt_cfm(conn, ev->status, 0x00);
                }
        }
 
+unlock:
        hci_dev_unlock(hdev);
 }
 
@@ -1557,6 +1622,7 @@ static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *
                                /* Encryption implies authentication */
                                conn->link_mode |= HCI_LM_AUTH;
                                conn->link_mode |= HCI_LM_ENCRYPT;
+                               conn->sec_level = conn->pending_sec_level;
                        } else
                                conn->link_mode &= ~HCI_LM_ENCRYPT;
                }
@@ -1816,6 +1882,18 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
                hci_cc_user_confirm_neg_reply(hdev, skb);
                break;
 
+       case HCI_OP_LE_SET_SCAN_ENABLE:
+               hci_cc_le_set_scan_enable(hdev, skb);
+               break;
+
+       case HCI_OP_LE_LTK_REPLY:
+               hci_cc_le_ltk_reply(hdev, skb);
+               break;
+
+       case HCI_OP_LE_LTK_NEG_REPLY:
+               hci_cc_le_ltk_neg_reply(hdev, skb);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%x", hdev->name, opcode);
                break;
@@ -1894,6 +1972,10 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_cs_le_create_conn(hdev, ev->status);
                break;
 
+       case HCI_OP_LE_START_ENC:
+               hci_cs_le_start_enc(hdev, ev->status);
+               break;
+
        default:
                BT_DBG("%s opcode 0x%x", hdev->name, opcode);
                break;
@@ -2658,6 +2740,8 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
                        hci_dev_unlock(hdev);
                        return;
                }
+
+               conn->dst_type = ev->bdaddr_type;
        }
 
        if (ev->status) {
@@ -2670,6 +2754,7 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff
 
        mgmt_connected(hdev->id, &ev->bdaddr);
 
+       conn->sec_level = BT_SECURITY_LOW;
        conn->handle = __le16_to_cpu(ev->handle);
        conn->state = BT_CONNECTED;
 
@@ -2682,6 +2767,49 @@ unlock:
        hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_adv_report_evt(struct hci_dev *hdev,
+                                               struct sk_buff *skb)
+{
+       struct hci_ev_le_advertising_info *ev;
+       u8 num_reports;
+
+       num_reports = skb->data[0];
+       ev = (void *) &skb->data[1];
+
+       hci_dev_lock(hdev);
+
+       hci_add_adv_entry(hdev, ev);
+
+       while (--num_reports) {
+               ev = (void *) (ev->data + ev->length + 1);
+               hci_add_adv_entry(hdev, ev);
+       }
+
+       hci_dev_unlock(hdev);
+}
+
+static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
+                                               struct sk_buff *skb)
+{
+       struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+       struct hci_cp_le_ltk_reply cp;
+       struct hci_conn *conn;
+
+       BT_DBG("%s handle %d", hdev->name, cpu_to_le16(ev->handle));
+
+       hci_dev_lock(hdev);
+
+       conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+
+       memset(&cp, 0, sizeof(cp));
+       cp.handle = cpu_to_le16(conn->handle);
+       memcpy(cp.ltk, conn->ltk, sizeof(conn->ltk));
+
+       hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
+
+       hci_dev_unlock(hdev);
+}
+
 static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -2693,6 +2821,14 @@ static inline void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
                hci_le_conn_complete_evt(hdev, skb);
                break;
 
+       case HCI_EV_LE_ADVERTISING_REPORT:
+               hci_le_adv_report_evt(hdev, skb);
+               break;
+
+       case HCI_EV_LE_LTK_REQ:
+               hci_le_ltk_request_evt(hdev, skb);
+               break;
+
        default:
                break;
        }
index 295e4a8..ff02cf5 100644 (file)
@@ -180,82 +180,24 @@ static int hci_sock_release(struct socket *sock)
        return 0;
 }
 
-struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr)
-{
-       struct list_head *p;
-
-       list_for_each(p, &hdev->blacklist) {
-               struct bdaddr_list *b;
-
-               b = list_entry(p, struct bdaddr_list, list);
-
-               if (bacmp(bdaddr, &b->bdaddr) == 0)
-                       return b;
-       }
-
-       return NULL;
-}
-
-static int hci_blacklist_add(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
-       struct bdaddr_list *entry;
 
        if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
                return -EFAULT;
 
-       if (bacmp(&bdaddr, BDADDR_ANY) == 0)
-               return -EBADF;
-
-       if (hci_blacklist_lookup(hdev, &bdaddr))
-               return -EEXIST;
-
-       entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
-       if (!entry)
-               return -ENOMEM;
-
-       bacpy(&entry->bdaddr, &bdaddr);
-
-       list_add(&entry->list, &hdev->blacklist);
-
-       return 0;
-}
-
-int hci_blacklist_clear(struct hci_dev *hdev)
-{
-       struct list_head *p, *n;
-
-       list_for_each_safe(p, n, &hdev->blacklist) {
-               struct bdaddr_list *b;
-
-               b = list_entry(p, struct bdaddr_list, list);
-
-               list_del(p);
-               kfree(b);
-       }
-
-       return 0;
+       return hci_blacklist_add(hdev, &bdaddr);
 }
 
-static int hci_blacklist_del(struct hci_dev *hdev, void __user *arg)
+static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
 {
        bdaddr_t bdaddr;
-       struct bdaddr_list *entry;
 
        if (copy_from_user(&bdaddr, arg, sizeof(bdaddr)))
                return -EFAULT;
 
-       if (bacmp(&bdaddr, BDADDR_ANY) == 0)
-               return hci_blacklist_clear(hdev);
-
-       entry = hci_blacklist_lookup(hdev, &bdaddr);
-       if (!entry)
-               return -ENOENT;
-
-       list_del(&entry->list);
-       kfree(entry);
-
-       return 0;
+       return hci_blacklist_del(hdev, &bdaddr);
 }
 
 /* Ioctls that require bound socket */
@@ -290,12 +232,12 @@ static inline int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, unsign
        case HCIBLOCKADDR:
                if (!capable(CAP_NET_ADMIN))
                        return -EACCES;
-               return hci_blacklist_add(hdev, (void __user *) arg);
+               return hci_sock_blacklist_add(hdev, (void __user *) arg);
 
        case HCIUNBLOCKADDR:
                if (!capable(CAP_NET_ADMIN))
                        return -EACCES;
-               return hci_blacklist_del(hdev, (void __user *) arg);
+               return hci_sock_blacklist_del(hdev, (void __user *) arg);
 
        default:
                if (hdev->ioctl)
index e64a1c2..9ec9c8c 100644 (file)
@@ -54,6 +54,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
 
 int disable_ertm;
 
@@ -62,18 +63,34 @@ static u8 l2cap_fixed_chan[8] = { 0x02, };
 
 static struct workqueue_struct *_busy_wq;
 
-LIST_HEAD(chan_list);
-DEFINE_RWLOCK(chan_list_lock);
+static LIST_HEAD(chan_list);
+static DEFINE_RWLOCK(chan_list_lock);
 
 static void l2cap_busy_work(struct work_struct *work);
 
 static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
                                u8 code, u8 ident, u16 dlen, void *data);
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
+                                                               void *data);
 static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
+static void l2cap_send_disconn_req(struct l2cap_conn *conn,
+                               struct l2cap_chan *chan, int err);
 
 static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
 
 /* ---- L2CAP channels ---- */
+
+static inline void chan_hold(struct l2cap_chan *c)
+{
+       atomic_inc(&c->refcnt);
+}
+
+static inline void chan_put(struct l2cap_chan *c)
+{
+       if (atomic_dec_and_test(&c->refcnt))
+               kfree(c);
+}
+
 static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid)
 {
        struct l2cap_chan *c;
@@ -204,6 +221,62 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
        return 0;
 }
 
+static void l2cap_set_timer(struct l2cap_chan *chan, struct timer_list *timer, long timeout)
+{
+       BT_DBG("chan %p state %d timeout %ld", chan->sk, chan->state, timeout);
+
+       if (!mod_timer(timer, jiffies + timeout))
+              chan_hold(chan);
+}
+
+static void l2cap_clear_timer(struct l2cap_chan *chan, struct timer_list *timer)
+{
+       BT_DBG("chan %p state %d", chan, chan->state);
+
+       if (timer_pending(timer) && del_timer(timer))
+              chan_put(chan);
+}
+
+static void l2cap_state_change(struct l2cap_chan *chan, int state)
+{
+       chan->state = state;
+       chan->ops->state_change(chan->data, state);
+}
+
+static void l2cap_chan_timeout(unsigned long arg)
+{
+       struct l2cap_chan *chan = (struct l2cap_chan *) arg;
+       struct sock *sk = chan->sk;
+       int reason;
+
+       BT_DBG("chan %p state %d", chan, chan->state);
+
+       bh_lock_sock(sk);
+
+       if (sock_owned_by_user(sk)) {
+               /* sk is owned by user. Try again later */
+               __set_chan_timer(chan, HZ / 5);
+               bh_unlock_sock(sk);
+               chan_put(chan);
+               return;
+       }
+
+       if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)
+               reason = ECONNREFUSED;
+       else if (chan->state == BT_CONNECT &&
+                                       chan->sec_level != BT_SECURITY_SDP)
+               reason = ECONNREFUSED;
+       else
+               reason = ETIMEDOUT;
+
+       l2cap_chan_close(chan, reason);
+
+       bh_unlock_sock(sk);
+
+       chan->ops->close(chan->data);
+       chan_put(chan);
+}
+
 struct l2cap_chan *l2cap_chan_create(struct sock *sk)
 {
        struct l2cap_chan *chan;
@@ -218,6 +291,12 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk)
        list_add(&chan->global_l, &chan_list);
        write_unlock_bh(&chan_list_lock);
 
+       setup_timer(&chan->chan_timer, l2cap_chan_timeout, (unsigned long) chan);
+
+       chan->state = BT_OPEN;
+
+       atomic_set(&chan->refcnt, 1);
+
        return chan;
 }
 
@@ -227,13 +306,11 @@ void l2cap_chan_destroy(struct l2cap_chan *chan)
        list_del(&chan->global_l);
        write_unlock_bh(&chan_list_lock);
 
-       kfree(chan);
+       chan_put(chan);
 }
 
 static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
-       struct sock *sk = chan->sk;
-
        BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
                        chan->psm, chan->dcid);
 
@@ -241,7 +318,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 
        chan->conn = conn;
 
-       if (sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM) {
+       if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) {
                if (conn->hcon->type == LE_LINK) {
                        /* LE connection */
                        chan->omtu = L2CAP_LE_DEFAULT_MTU;
@@ -252,7 +329,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
                        chan->scid = l2cap_alloc_cid(conn);
                        chan->omtu = L2CAP_DEFAULT_MTU;
                }
-       } else if (sk->sk_type == SOCK_DGRAM) {
+       } else if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
                /* Connectionless socket */
                chan->scid = L2CAP_CID_CONN_LESS;
                chan->dcid = L2CAP_CID_CONN_LESS;
@@ -264,20 +341,20 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
                chan->omtu = L2CAP_DEFAULT_MTU;
        }
 
-       sock_hold(sk);
+       chan_hold(chan);
 
        list_add(&chan->list, &conn->chan_l);
 }
 
 /* Delete channel.
  * Must be called on the locked socket. */
-void l2cap_chan_del(struct l2cap_chan *chan, int err)
+static void l2cap_chan_del(struct l2cap_chan *chan, int err)
 {
        struct sock *sk = chan->sk;
        struct l2cap_conn *conn = chan->conn;
        struct sock *parent = bt_sk(sk)->parent;
 
-       l2cap_sock_clear_timer(sk);
+       __clear_chan_timer(chan);
 
        BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
 
@@ -286,13 +363,13 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
                write_lock_bh(&conn->chan_lock);
                list_del(&chan->list);
                write_unlock_bh(&conn->chan_lock);
-               __sock_put(sk);
+               chan_put(chan);
 
                chan->conn = NULL;
                hci_conn_put(conn->hcon);
        }
 
-       sk->sk_state = BT_CLOSED;
+       l2cap_state_change(chan, BT_CLOSED);
        sock_set_flag(sk, SOCK_ZAPPED);
 
        if (err)
@@ -304,8 +381,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        } else
                sk->sk_state_change(sk);
 
-       if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE &&
-                       chan->conf_state & L2CAP_CONF_INPUT_DONE))
+       if (!(test_bit(CONF_OUTPUT_DONE, &chan->conf_state) &&
+                       test_bit(CONF_INPUT_DONE, &chan->conf_state)))
                return;
 
        skb_queue_purge(&chan->tx_q);
@@ -313,9 +390,9 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        if (chan->mode == L2CAP_MODE_ERTM) {
                struct srej_list *l, *tmp;
 
-               del_timer(&chan->retrans_timer);
-               del_timer(&chan->monitor_timer);
-               del_timer(&chan->ack_timer);
+               __clear_retrans_timer(chan);
+               __clear_monitor_timer(chan);
+               __clear_ack_timer(chan);
 
                skb_queue_purge(&chan->srej_q);
                skb_queue_purge(&chan->busy_q);
@@ -327,11 +404,86 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
        }
 }
 
-static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
+static void l2cap_chan_cleanup_listen(struct sock *parent)
 {
+       struct sock *sk;
+
+       BT_DBG("parent %p", parent);
+
+       /* Close not yet accepted channels */
+       while ((sk = bt_accept_dequeue(parent, NULL))) {
+               struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+               __clear_chan_timer(chan);
+               lock_sock(sk);
+               l2cap_chan_close(chan, ECONNRESET);
+               release_sock(sk);
+               chan->ops->close(chan->data);
+       }
+}
+
+void l2cap_chan_close(struct l2cap_chan *chan, int reason)
+{
+       struct l2cap_conn *conn = chan->conn;
        struct sock *sk = chan->sk;
 
-       if (sk->sk_type == SOCK_RAW) {
+       BT_DBG("chan %p state %d socket %p", chan, chan->state, sk->sk_socket);
+
+       switch (chan->state) {
+       case BT_LISTEN:
+               l2cap_chan_cleanup_listen(sk);
+
+               l2cap_state_change(chan, BT_CLOSED);
+               sock_set_flag(sk, SOCK_ZAPPED);
+               break;
+
+       case BT_CONNECTED:
+       case BT_CONFIG:
+               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
+                                       conn->hcon->type == ACL_LINK) {
+                       __clear_chan_timer(chan);
+                       __set_chan_timer(chan, sk->sk_sndtimeo);
+                       l2cap_send_disconn_req(conn, chan, reason);
+               } else
+                       l2cap_chan_del(chan, reason);
+               break;
+
+       case BT_CONNECT2:
+               if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
+                                       conn->hcon->type == ACL_LINK) {
+                       struct l2cap_conn_rsp rsp;
+                       __u16 result;
+
+                       if (bt_sk(sk)->defer_setup)
+                               result = L2CAP_CR_SEC_BLOCK;
+                       else
+                               result = L2CAP_CR_BAD_PSM;
+                       l2cap_state_change(chan, BT_DISCONN);
+
+                       rsp.scid   = cpu_to_le16(chan->dcid);
+                       rsp.dcid   = cpu_to_le16(chan->scid);
+                       rsp.result = cpu_to_le16(result);
+                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
+                                                       sizeof(rsp), &rsp);
+               }
+
+               l2cap_chan_del(chan, reason);
+               break;
+
+       case BT_CONNECT:
+       case BT_DISCONN:
+               l2cap_chan_del(chan, reason);
+               break;
+
+       default:
+               sock_set_flag(sk, SOCK_ZAPPED);
+               break;
+       }
+}
+
+static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan)
+{
+       if (chan->chan_type == L2CAP_CHAN_RAW) {
                switch (chan->sec_level) {
                case BT_SECURITY_HIGH:
                        return HCI_AT_DEDICATED_BONDING_MITM;
@@ -371,7 +523,7 @@ static inline int l2cap_check_security(struct l2cap_chan *chan)
        return hci_conn_security(conn->hcon, chan->sec_level, auth_type);
 }
 
-u8 l2cap_get_ident(struct l2cap_conn *conn)
+static u8 l2cap_get_ident(struct l2cap_conn *conn)
 {
        u8 id;
 
@@ -393,7 +545,7 @@ u8 l2cap_get_ident(struct l2cap_conn *conn)
        return id;
 }
 
-void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
+static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
 {
        struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
        u8 flags;
@@ -408,6 +560,8 @@ void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *d
        else
                flags = ACL_START;
 
+       bt_cb(skb)->force_active = BT_POWER_FORCE_ACTIVE_ON;
+
        hci_send_acl(conn->hcon, skb, flags);
 }
 
@@ -415,13 +569,11 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
 {
        struct sk_buff *skb;
        struct l2cap_hdr *lh;
-       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
        struct l2cap_conn *conn = chan->conn;
-       struct sock *sk = (struct sock *)pi;
        int count, hlen = L2CAP_HDR_SIZE + 2;
        u8 flags;
 
-       if (sk->sk_state != BT_CONNECTED)
+       if (chan->state != BT_CONNECTED)
                return;
 
        if (chan->fcs == L2CAP_FCS_CRC16)
@@ -432,15 +584,11 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
        count = min_t(unsigned int, conn->mtu, hlen);
        control |= L2CAP_CTRL_FRAME_TYPE;
 
-       if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+       if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
                control |= L2CAP_CTRL_FINAL;
-               chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-       }
 
-       if (chan->conn_state & L2CAP_CONN_SEND_PBIT) {
+       if (test_and_clear_bit(CONN_SEND_PBIT, &chan->conn_state))
                control |= L2CAP_CTRL_POLL;
-               chan->conn_state &= ~L2CAP_CONN_SEND_PBIT;
-       }
 
        skb = bt_skb_alloc(count, GFP_ATOMIC);
        if (!skb)
@@ -461,14 +609,16 @@ static inline void l2cap_send_sframe(struct l2cap_chan *chan, u16 control)
        else
                flags = ACL_START;
 
+       bt_cb(skb)->force_active = chan->force_active;
+
        hci_send_acl(chan->conn->hcon, skb, flags);
 }
 
 static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 {
-       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
                control |= L2CAP_SUPER_RCV_NOT_READY;
-               chan->conn_state |= L2CAP_CONN_RNR_SENT;
+               set_bit(CONN_RNR_SENT, &chan->conn_state);
        } else
                control |= L2CAP_SUPER_RCV_READY;
 
@@ -479,7 +629,7 @@ static inline void l2cap_send_rr_or_rnr(struct l2cap_chan *chan, u16 control)
 
 static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
 {
-       return !(chan->conf_state & L2CAP_CONF_CONNECT_PEND);
+       return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
 }
 
 static void l2cap_do_start(struct l2cap_chan *chan)
@@ -497,7 +647,7 @@ static void l2cap_do_start(struct l2cap_chan *chan)
                        req.psm  = chan->psm;
 
                        chan->ident = l2cap_get_ident(conn);
-                       chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+                       set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
                                                        sizeof(req), &req);
@@ -533,7 +683,7 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
        }
 }
 
-void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
+static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err)
 {
        struct sock *sk;
        struct l2cap_disconn_req req;
@@ -544,9 +694,9 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
        sk = chan->sk;
 
        if (chan->mode == L2CAP_MODE_ERTM) {
-               del_timer(&chan->retrans_timer);
-               del_timer(&chan->monitor_timer);
-               del_timer(&chan->ack_timer);
+               __clear_retrans_timer(chan);
+               __clear_monitor_timer(chan);
+               __clear_ack_timer(chan);
        }
 
        req.dcid = cpu_to_le16(chan->dcid);
@@ -554,7 +704,7 @@ void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, in
        l2cap_send_cmd(conn, l2cap_get_ident(conn),
                        L2CAP_DISCONN_REQ, sizeof(req), &req);
 
-       sk->sk_state = BT_DISCONN;
+       l2cap_state_change(chan, BT_DISCONN);
        sk->sk_err = err;
 }
 
@@ -572,13 +722,12 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
 
                bh_lock_sock(sk);
 
-               if (sk->sk_type != SOCK_SEQPACKET &&
-                               sk->sk_type != SOCK_STREAM) {
+               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
                        bh_unlock_sock(sk);
                        continue;
                }
 
-               if (sk->sk_state == BT_CONNECT) {
+               if (chan->state == BT_CONNECT) {
                        struct l2cap_conn_req req;
 
                        if (!l2cap_check_security(chan) ||
@@ -587,14 +736,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                                continue;
                        }
 
-                       if (!l2cap_mode_supported(chan->mode,
-                                       conn->feat_mask)
-                                       && chan->conf_state &
-                                       L2CAP_CONF_STATE2_DEVICE) {
-                               /* __l2cap_sock_close() calls list_del(chan)
+                       if (!l2cap_mode_supported(chan->mode, conn->feat_mask)
+                                       && test_bit(CONF_STATE2_DEVICE,
+                                       &chan->conf_state)) {
+                               /* l2cap_chan_close() calls list_del(chan)
                                 * so release the lock */
                                read_unlock_bh(&conn->chan_lock);
-                                __l2cap_sock_close(sk, ECONNRESET);
+                               l2cap_chan_close(chan, ECONNRESET);
                                read_lock_bh(&conn->chan_lock);
                                bh_unlock_sock(sk);
                                continue;
@@ -604,12 +752,12 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                        req.psm  = chan->psm;
 
                        chan->ident = l2cap_get_ident(conn);
-                       chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+                       set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ,
                                                        sizeof(req), &req);
 
-               } else if (sk->sk_state == BT_CONNECT2) {
+               } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
                        char buf[128];
                        rsp.scid = cpu_to_le16(chan->dcid);
@@ -623,7 +771,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                                        parent->sk_data_ready(parent, 0);
 
                                } else {
-                                       sk->sk_state = BT_CONFIG;
+                                       l2cap_state_change(chan, BT_CONFIG);
                                        rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
                                        rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
                                }
@@ -635,13 +783,13 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
                                                        sizeof(rsp), &rsp);
 
-                       if (chan->conf_state & L2CAP_CONF_REQ_SENT ||
+                       if (test_bit(CONF_REQ_SENT, &chan->conf_state) ||
                                        rsp.result != L2CAP_CR_SUCCESS) {
                                bh_unlock_sock(sk);
                                continue;
                        }
 
-                       chan->conf_state |= L2CAP_CONF_REQ_SENT;
+                       set_bit(CONF_REQ_SENT, &chan->conf_state);
                        l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
                                                l2cap_build_conf_req(chan, buf), buf);
                        chan->num_conf_req++;
@@ -665,7 +813,7 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdadd
        list_for_each_entry(c, &chan_list, global_l) {
                struct sock *sk = c->sk;
 
-               if (state && sk->sk_state != state)
+               if (state && c->state != state)
                        continue;
 
                if (c->scid == cid) {
@@ -709,24 +857,16 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
                goto clean;
        }
 
-       sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-       if (!sk)
-               goto clean;
-
-       chan = l2cap_chan_create(sk);
-       if (!chan) {
-               l2cap_sock_kill(sk);
+       chan = pchan->ops->new_connection(pchan->data);
+       if (!chan)
                goto clean;
-       }
 
-       l2cap_pi(sk)->chan = chan;
+       sk = chan->sk;
 
        write_lock_bh(&conn->chan_lock);
 
        hci_conn_hold(conn->hcon);
 
-       l2cap_sock_init(sk, parent);
-
        bacpy(&bt_sk(sk)->src, conn->src);
        bacpy(&bt_sk(sk)->dst, conn->dst);
 
@@ -734,9 +874,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
 
        __l2cap_chan_add(conn, chan);
 
-       l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+       __set_chan_timer(chan, sk->sk_sndtimeo);
 
-       sk->sk_state = BT_CONNECTED;
+       l2cap_state_change(chan, BT_CONNECTED);
        parent->sk_data_ready(parent, 0);
 
        write_unlock_bh(&conn->chan_lock);
@@ -745,6 +885,23 @@ clean:
        bh_unlock_sock(parent);
 }
 
+static void l2cap_chan_ready(struct sock *sk)
+{
+       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       struct sock *parent = bt_sk(sk)->parent;
+
+       BT_DBG("sk %p, parent %p", sk, parent);
+
+       chan->conf_state = 0;
+       __clear_chan_timer(chan);
+
+       l2cap_state_change(chan, BT_CONNECTED);
+       sk->sk_state_change(sk);
+
+       if (parent)
+               parent->sk_data_ready(parent, 0);
+}
+
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
        struct l2cap_chan *chan;
@@ -762,17 +919,15 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                bh_lock_sock(sk);
 
                if (conn->hcon->type == LE_LINK) {
-                       l2cap_sock_clear_timer(sk);
-                       sk->sk_state = BT_CONNECTED;
-                       sk->sk_state_change(sk);
-               }
+                       if (smp_conn_security(conn, chan->sec_level))
+                               l2cap_chan_ready(sk);
 
-               if (sk->sk_type != SOCK_SEQPACKET &&
-                               sk->sk_type != SOCK_STREAM) {
-                       l2cap_sock_clear_timer(sk);
-                       sk->sk_state = BT_CONNECTED;
+               } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+                       __clear_chan_timer(chan);
+                       l2cap_state_change(chan, BT_CONNECTED);
                        sk->sk_state_change(sk);
-               } else if (sk->sk_state == BT_CONNECT)
+
+               } else if (chan->state == BT_CONNECT)
                        l2cap_do_start(chan);
 
                bh_unlock_sock(sk);
@@ -810,6 +965,45 @@ static void l2cap_info_timeout(unsigned long arg)
        l2cap_conn_start(conn);
 }
 
+static void l2cap_conn_del(struct hci_conn *hcon, int err)
+{
+       struct l2cap_conn *conn = hcon->l2cap_data;
+       struct l2cap_chan *chan, *l;
+       struct sock *sk;
+
+       if (!conn)
+               return;
+
+       BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
+
+       kfree_skb(conn->rx_skb);
+
+       /* Kill channels */
+       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
+               sk = chan->sk;
+               bh_lock_sock(sk);
+               l2cap_chan_del(chan, err);
+               bh_unlock_sock(sk);
+               chan->ops->close(chan->data);
+       }
+
+       if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
+               del_timer_sync(&conn->info_timer);
+
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+               del_timer(&conn->security_timer);
+
+       hcon->l2cap_data = NULL;
+       kfree(conn);
+}
+
+static void security_timeout(unsigned long arg)
+{
+       struct l2cap_conn *conn = (void *) arg;
+
+       l2cap_conn_del(conn->hcon, ETIMEDOUT);
+}
+
 static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 {
        struct l2cap_conn *conn = hcon->l2cap_data;
@@ -841,7 +1035,10 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
 
        INIT_LIST_HEAD(&conn->chan_l);
 
-       if (hcon->type != LE_LINK)
+       if (hcon->type == LE_LINK)
+               setup_timer(&conn->security_timer, security_timeout,
+                                               (unsigned long) conn);
+       else
                setup_timer(&conn->info_timer, l2cap_info_timeout,
                                                (unsigned long) conn);
 
@@ -850,35 +1047,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status)
        return conn;
 }
 
-static void l2cap_conn_del(struct hci_conn *hcon, int err)
-{
-       struct l2cap_conn *conn = hcon->l2cap_data;
-       struct l2cap_chan *chan, *l;
-       struct sock *sk;
-
-       if (!conn)
-               return;
-
-       BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
-
-       kfree_skb(conn->rx_skb);
-
-       /* Kill channels */
-       list_for_each_entry_safe(chan, l, &conn->chan_l, list) {
-               sk = chan->sk;
-               bh_lock_sock(sk);
-               l2cap_chan_del(chan, err);
-               bh_unlock_sock(sk);
-               l2cap_sock_kill(sk);
-       }
-
-       if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
-               del_timer_sync(&conn->info_timer);
-
-       hcon->l2cap_data = NULL;
-       kfree(conn);
-}
-
 static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)
 {
        write_lock_bh(&conn->chan_lock);
@@ -900,7 +1068,7 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr
        list_for_each_entry(c, &chan_list, global_l) {
                struct sock *sk = c->sk;
 
-               if (state && sk->sk_state != state)
+               if (state && c->state != state)
                        continue;
 
                if (c->psm == psm) {
@@ -967,15 +1135,14 @@ int l2cap_chan_connect(struct l2cap_chan *chan)
 
        l2cap_chan_add(conn, chan);
 
-       sk->sk_state = BT_CONNECT;
-       l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+       l2cap_state_change(chan, BT_CONNECT);
+       __set_chan_timer(chan, sk->sk_sndtimeo);
 
        if (hcon->state == BT_CONNECTED) {
-               if (sk->sk_type != SOCK_SEQPACKET &&
-                               sk->sk_type != SOCK_STREAM) {
-                       l2cap_sock_clear_timer(sk);
+               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+                       __clear_chan_timer(chan);
                        if (l2cap_check_security(chan))
-                               sk->sk_state = BT_CONNECTED;
+                               l2cap_state_change(chan, BT_CONNECTED);
                } else
                        l2cap_do_start(chan);
        }
@@ -1035,7 +1202,7 @@ static void l2cap_monitor_timeout(unsigned long arg)
        }
 
        chan->retry_count++;
-       __mod_monitor_timer();
+       __set_monitor_timer(chan);
 
        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
        bh_unlock_sock(sk);
@@ -1050,9 +1217,9 @@ static void l2cap_retrans_timeout(unsigned long arg)
 
        bh_lock_sock(sk);
        chan->retry_count = 1;
-       __mod_monitor_timer();
+       __set_monitor_timer(chan);
 
-       chan->conn_state |= L2CAP_CONN_WAIT_F;
+       set_bit(CONN_WAIT_F, &chan->conn_state);
 
        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_POLL);
        bh_unlock_sock(sk);
@@ -1074,7 +1241,7 @@ static void l2cap_drop_acked_frames(struct l2cap_chan *chan)
        }
 
        if (!chan->unacked_frames)
-               del_timer(&chan->retrans_timer);
+               __clear_retrans_timer(chan);
 }
 
 void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
@@ -1089,6 +1256,7 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
        else
                flags = ACL_START;
 
+       bt_cb(skb)->force_active = chan->force_active;
        hci_send_acl(hcon, skb, flags);
 }
 
@@ -1142,10 +1310,8 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
        control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
        control &= L2CAP_CTRL_SAR;
 
-       if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+       if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
                control |= L2CAP_CTRL_FINAL;
-               chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-       }
 
        control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
                        | (tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
@@ -1163,11 +1329,10 @@ static void l2cap_retransmit_one_frame(struct l2cap_chan *chan, u8 tx_seq)
 int l2cap_ertm_send(struct l2cap_chan *chan)
 {
        struct sk_buff *skb, *tx_skb;
-       struct sock *sk = chan->sk;
        u16 control, fcs;
        int nsent = 0;
 
-       if (sk->sk_state != BT_CONNECTED)
+       if (chan->state != BT_CONNECTED)
                return -ENOTCONN;
 
        while ((skb = chan->tx_send_head) && (!l2cap_tx_window_full(chan))) {
@@ -1185,10 +1350,9 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
                control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
                control &= L2CAP_CTRL_SAR;
 
-               if (chan->conn_state & L2CAP_CONN_SEND_FBIT) {
+               if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state))
                        control |= L2CAP_CTRL_FINAL;
-                       chan->conn_state &= ~L2CAP_CONN_SEND_FBIT;
-               }
+
                control |= (chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT)
                                | (chan->next_tx_seq << L2CAP_CTRL_TXSEQ_SHIFT);
                put_unaligned_le16(control, tx_skb->data + L2CAP_HDR_SIZE);
@@ -1201,7 +1365,7 @@ int l2cap_ertm_send(struct l2cap_chan *chan)
 
                l2cap_do_send(chan, tx_skb);
 
-               __mod_retrans_timer();
+               __set_retrans_timer(chan);
 
                bt_cb(skb)->tx_seq = chan->next_tx_seq;
                chan->next_tx_seq = (chan->next_tx_seq + 1) % 64;
@@ -1240,9 +1404,9 @@ static void l2cap_send_ack(struct l2cap_chan *chan)
 
        control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
                control |= L2CAP_SUPER_RCV_NOT_READY;
-               chan->conn_state |= L2CAP_CONN_RNR_SENT;
+               set_bit(CONN_RNR_SENT, &chan->conn_state);
                l2cap_send_sframe(chan, control);
                return;
        }
@@ -1450,28 +1614,83 @@ int l2cap_sar_segment_sdu(struct l2cap_chan *chan, struct msghdr *msg, size_t le
        return size;
 }
 
-static void l2cap_chan_ready(struct sock *sk)
+int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len)
 {
-       struct sock *parent = bt_sk(sk)->parent;
-       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+       struct sk_buff *skb;
+       u16 control;
+       int err;
 
-       BT_DBG("sk %p, parent %p", sk, parent);
+       /* Connectionless channel */
+       if (chan->chan_type == L2CAP_CHAN_CONN_LESS) {
+               skb = l2cap_create_connless_pdu(chan, msg, len);
+               if (IS_ERR(skb))
+                       return PTR_ERR(skb);
 
-       chan->conf_state = 0;
-       l2cap_sock_clear_timer(sk);
+               l2cap_do_send(chan, skb);
+               return len;
+       }
 
-       if (!parent) {
-               /* Outgoing channel.
-                * Wake up socket sleeping on connect.
-                */
-               sk->sk_state = BT_CONNECTED;
-               sk->sk_state_change(sk);
-       } else {
-               /* Incoming channel.
-                * Wake up socket sleeping on accept.
-                */
-               parent->sk_data_ready(parent, 0);
+       switch (chan->mode) {
+       case L2CAP_MODE_BASIC:
+               /* Check outgoing MTU */
+               if (len > chan->omtu)
+                       return -EMSGSIZE;
+
+               /* Create a basic PDU */
+               skb = l2cap_create_basic_pdu(chan, msg, len);
+               if (IS_ERR(skb))
+                       return PTR_ERR(skb);
+
+               l2cap_do_send(chan, skb);
+               err = len;
+               break;
+
+       case L2CAP_MODE_ERTM:
+       case L2CAP_MODE_STREAMING:
+               /* Entire SDU fits into one PDU */
+               if (len <= chan->remote_mps) {
+                       control = L2CAP_SDU_UNSEGMENTED;
+                       skb = l2cap_create_iframe_pdu(chan, msg, len, control,
+                                                                       0);
+                       if (IS_ERR(skb))
+                               return PTR_ERR(skb);
+
+                       __skb_queue_tail(&chan->tx_q, skb);
+
+                       if (chan->tx_send_head == NULL)
+                               chan->tx_send_head = skb;
+
+               } else {
+                       /* Segment SDU into multiples PDUs */
+                       err = l2cap_sar_segment_sdu(chan, msg, len);
+                       if (err < 0)
+                               return err;
+               }
+
+               if (chan->mode == L2CAP_MODE_STREAMING) {
+                       l2cap_streaming_send(chan);
+                       err = len;
+                       break;
+               }
+
+               if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
+                               test_bit(CONN_WAIT_F, &chan->conn_state)) {
+                       err = len;
+                       break;
+               }
+
+               err = l2cap_ertm_send(chan);
+               if (err >= 0)
+                       err = len;
+
+               break;
+
+       default:
+               BT_DBG("bad state %1.1x", chan->mode);
+               err = -EBADFD;
        }
+
+       return err;
 }
 
 /* Copy frame to all raw sockets on that connection */
@@ -1485,7 +1704,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
        read_lock(&conn->chan_lock);
        list_for_each_entry(chan, &conn->chan_l, list) {
                struct sock *sk = chan->sk;
-               if (sk->sk_type != SOCK_RAW)
+               if (chan->chan_type != L2CAP_CHAN_RAW)
                        continue;
 
                /* Don't send frame to the socket it came from */
@@ -1495,7 +1714,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
                if (!nskb)
                        continue;
 
-               if (sock_queue_rcv_skb(sk, nskb))
+               if (chan->ops->recv(chan->data, nskb))
                        kfree_skb(nskb);
        }
        read_unlock(&conn->chan_lock);
@@ -1690,7 +1909,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
        switch (chan->mode) {
        case L2CAP_MODE_STREAMING:
        case L2CAP_MODE_ERTM:
-               if (chan->conf_state & L2CAP_CONF_STATE2_DEVICE)
+               if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state))
                        break;
 
                /* fall through */
@@ -1737,7 +1956,7 @@ done:
                        break;
 
                if (chan->fcs == L2CAP_FCS_NONE ||
-                               chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+                               test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
                        chan->fcs = L2CAP_FCS_NONE;
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
                }
@@ -1760,7 +1979,7 @@ done:
                        break;
 
                if (chan->fcs == L2CAP_FCS_NONE ||
-                               chan->conf_state & L2CAP_CONF_NO_FCS_RECV) {
+                               test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) {
                        chan->fcs = L2CAP_FCS_NONE;
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs);
                }
@@ -1812,7 +2031,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
 
                case L2CAP_CONF_FCS:
                        if (val == L2CAP_FCS_NONE)
-                               chan->conf_state |= L2CAP_CONF_NO_FCS_RECV;
+                               set_bit(CONF_NO_FCS_RECV, &chan->conf_state);
 
                        break;
 
@@ -1832,7 +2051,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
        switch (chan->mode) {
        case L2CAP_MODE_STREAMING:
        case L2CAP_MODE_ERTM:
-               if (!(chan->conf_state & L2CAP_CONF_STATE2_DEVICE)) {
+               if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) {
                        chan->mode = l2cap_select_mode(rfc.mode,
                                        chan->conn->feat_mask);
                        break;
@@ -1865,14 +2084,14 @@ done:
                        result = L2CAP_CONF_UNACCEPT;
                else {
                        chan->omtu = mtu;
-                       chan->conf_state |= L2CAP_CONF_MTU_DONE;
+                       set_bit(CONF_MTU_DONE, &chan->conf_state);
                }
                l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
 
                switch (rfc.mode) {
                case L2CAP_MODE_BASIC:
                        chan->fcs = L2CAP_FCS_NONE;
-                       chan->conf_state |= L2CAP_CONF_MODE_DONE;
+                       set_bit(CONF_MODE_DONE, &chan->conf_state);
                        break;
 
                case L2CAP_MODE_ERTM:
@@ -1889,7 +2108,7 @@ done:
                        rfc.monitor_timeout =
                                le16_to_cpu(L2CAP_DEFAULT_MONITOR_TO);
 
-                       chan->conf_state |= L2CAP_CONF_MODE_DONE;
+                       set_bit(CONF_MODE_DONE, &chan->conf_state);
 
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
                                        sizeof(rfc), (unsigned long) &rfc);
@@ -1902,7 +2121,7 @@ done:
 
                        chan->remote_mps = le16_to_cpu(rfc.max_pdu_size);
 
-                       chan->conf_state |= L2CAP_CONF_MODE_DONE;
+                       set_bit(CONF_MODE_DONE, &chan->conf_state);
 
                        l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
                                        sizeof(rfc), (unsigned long) &rfc);
@@ -1917,7 +2136,7 @@ done:
                }
 
                if (result == L2CAP_CONF_SUCCESS)
-                       chan->conf_state |= L2CAP_CONF_OUTPUT_DONE;
+                       set_bit(CONF_OUTPUT_DONE, &chan->conf_state);
        }
        rsp->scid   = cpu_to_le16(chan->dcid);
        rsp->result = cpu_to_le16(result);
@@ -1959,7 +2178,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi
                        if (olen == sizeof(rfc))
                                memcpy(&rfc, (void *)val, olen);
 
-                       if ((chan->conf_state & L2CAP_CONF_STATE2_DEVICE) &&
+                       if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
                                                        rfc.mode != chan->mode)
                                return -ECONNREFUSED;
 
@@ -2021,10 +2240,9 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
        l2cap_send_cmd(conn, chan->ident,
                                L2CAP_CONN_RSP, sizeof(rsp), &rsp);
 
-       if (chan->conf_state & L2CAP_CONF_REQ_SENT)
+       if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
                return;
 
-       chan->conf_state |= L2CAP_CONF_REQ_SENT;
        l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
                        l2cap_build_conf_req(chan, buf), buf);
        chan->num_conf_req++;
@@ -2124,17 +2342,11 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
                goto response;
        }
 
-       sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, GFP_ATOMIC);
-       if (!sk)
-               goto response;
-
-       chan = l2cap_chan_create(sk);
-       if (!chan) {
-               l2cap_sock_kill(sk);
+       chan = pchan->ops->new_connection(pchan->data);
+       if (!chan)
                goto response;
-       }
 
-       l2cap_pi(sk)->chan = chan;
+       sk = chan->sk;
 
        write_lock_bh(&conn->chan_lock);
 
@@ -2142,13 +2354,12 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
        if (__l2cap_get_chan_by_dcid(conn, scid)) {
                write_unlock_bh(&conn->chan_lock);
                sock_set_flag(sk, SOCK_ZAPPED);
-               l2cap_sock_kill(sk);
+               chan->ops->close(chan->data);
                goto response;
        }
 
        hci_conn_hold(conn->hcon);
 
-       l2cap_sock_init(sk, parent);
        bacpy(&bt_sk(sk)->src, conn->src);
        bacpy(&bt_sk(sk)->dst, conn->dst);
        chan->psm  = psm;
@@ -2160,29 +2371,29 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        dcid = chan->scid;
 
-       l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+       __set_chan_timer(chan, sk->sk_sndtimeo);
 
        chan->ident = cmd->ident;
 
        if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
                if (l2cap_check_security(chan)) {
                        if (bt_sk(sk)->defer_setup) {
-                               sk->sk_state = BT_CONNECT2;
+                               l2cap_state_change(chan, BT_CONNECT2);
                                result = L2CAP_CR_PEND;
                                status = L2CAP_CS_AUTHOR_PEND;
                                parent->sk_data_ready(parent, 0);
                        } else {
-                               sk->sk_state = BT_CONFIG;
+                               l2cap_state_change(chan, BT_CONFIG);
                                result = L2CAP_CR_SUCCESS;
                                status = L2CAP_CS_NO_INFO;
                        }
                } else {
-                       sk->sk_state = BT_CONNECT2;
+                       l2cap_state_change(chan, BT_CONNECT2);
                        result = L2CAP_CR_PEND;
                        status = L2CAP_CS_AUTHEN_PEND;
                }
        } else {
-               sk->sk_state = BT_CONNECT2;
+               l2cap_state_change(chan, BT_CONNECT2);
                result = L2CAP_CR_PEND;
                status = L2CAP_CS_NO_INFO;
        }
@@ -2213,10 +2424,10 @@ sendresp:
                                        L2CAP_INFO_REQ, sizeof(info), &info);
        }
 
-       if (chan && !(chan->conf_state & L2CAP_CONF_REQ_SENT) &&
+       if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) &&
                                result == L2CAP_CR_SUCCESS) {
                u8 buf[128];
-               chan->conf_state |= L2CAP_CONF_REQ_SENT;
+               set_bit(CONF_REQ_SENT, &chan->conf_state);
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
                                        l2cap_build_conf_req(chan, buf), buf);
                chan->num_conf_req++;
@@ -2254,31 +2465,29 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
        switch (result) {
        case L2CAP_CR_SUCCESS:
-               sk->sk_state = BT_CONFIG;
+               l2cap_state_change(chan, BT_CONFIG);
                chan->ident = 0;
                chan->dcid = dcid;
-               chan->conf_state &= ~L2CAP_CONF_CONNECT_PEND;
+               clear_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
-               if (chan->conf_state & L2CAP_CONF_REQ_SENT)
+               if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state))
                        break;
 
-               chan->conf_state |= L2CAP_CONF_REQ_SENT;
-
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
                                        l2cap_build_conf_req(chan, req), req);
                chan->num_conf_req++;
                break;
 
        case L2CAP_CR_PEND:
-               chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+               set_bit(CONF_CONNECT_PEND, &chan->conf_state);
                break;
 
        default:
                /* don't delete l2cap channel if sk is owned by user */
                if (sock_owned_by_user(sk)) {
-                       sk->sk_state = BT_DISCONN;
-                       l2cap_sock_clear_timer(sk);
-                       l2cap_sock_set_timer(sk, HZ / 5);
+                       l2cap_state_change(chan, BT_DISCONN);
+                       __clear_chan_timer(chan);
+                       __set_chan_timer(chan, HZ / 5);
                        break;
                }
 
@@ -2292,14 +2501,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
 
 static inline void set_default_fcs(struct l2cap_chan *chan)
 {
-       struct l2cap_pinfo *pi = l2cap_pi(chan->sk);
-
        /* FCS is enabled only in ERTM or streaming mode, if one or both
         * sides request it.
         */
        if (chan->mode != L2CAP_MODE_ERTM && chan->mode != L2CAP_MODE_STREAMING)
                chan->fcs = L2CAP_FCS_NONE;
-       else if (!(pi->chan->conf_state & L2CAP_CONF_NO_FCS_RECV))
+       else if (!test_bit(CONF_NO_FCS_RECV, &chan->conf_state))
                chan->fcs = L2CAP_FCS_CRC16;
 }
 
@@ -2323,7 +2530,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
        sk = chan->sk;
 
-       if (sk->sk_state != BT_CONFIG) {
+       if (chan->state != BT_CONFIG) {
                struct l2cap_cmd_rej rej;
 
                rej.reason = cpu_to_le16(0x0002);
@@ -2366,13 +2573,13 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        /* Reset config buffer. */
        chan->conf_len = 0;
 
-       if (!(chan->conf_state & L2CAP_CONF_OUTPUT_DONE))
+       if (!test_bit(CONF_OUTPUT_DONE, &chan->conf_state))
                goto unlock;
 
-       if (chan->conf_state & L2CAP_CONF_INPUT_DONE) {
+       if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
                set_default_fcs(chan);
 
-               sk->sk_state = BT_CONNECTED;
+               l2cap_state_change(chan, BT_CONNECTED);
 
                chan->next_tx_seq = 0;
                chan->expected_tx_seq = 0;
@@ -2384,9 +2591,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
                goto unlock;
        }
 
-       if (!(chan->conf_state & L2CAP_CONF_REQ_SENT)) {
+       if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
                u8 buf[64];
-               chan->conf_state |= L2CAP_CONF_REQ_SENT;
                l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
                                        l2cap_build_conf_req(chan, buf), buf);
                chan->num_conf_req++;
@@ -2451,7 +2657,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
        default:
                sk->sk_err = ECONNRESET;
-               l2cap_sock_set_timer(sk, HZ * 5);
+               __set_chan_timer(chan, HZ * 5);
                l2cap_send_disconn_req(conn, chan, ECONNRESET);
                goto done;
        }
@@ -2459,12 +2665,12 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
        if (flags & 0x01)
                goto done;
 
-       chan->conf_state |= L2CAP_CONF_INPUT_DONE;
+       set_bit(CONF_INPUT_DONE, &chan->conf_state);
 
-       if (chan->conf_state & L2CAP_CONF_OUTPUT_DONE) {
+       if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) {
                set_default_fcs(chan);
 
-               sk->sk_state = BT_CONNECTED;
+               l2cap_state_change(chan, BT_CONNECTED);
                chan->next_tx_seq = 0;
                chan->expected_tx_seq = 0;
                skb_queue_head_init(&chan->tx_q);
@@ -2506,9 +2712,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
 
        /* don't delete l2cap channel if sk is owned by user */
        if (sock_owned_by_user(sk)) {
-               sk->sk_state = BT_DISCONN;
-               l2cap_sock_clear_timer(sk);
-               l2cap_sock_set_timer(sk, HZ / 5);
+               l2cap_state_change(chan, BT_DISCONN);
+               __clear_chan_timer(chan);
+               __set_chan_timer(chan, HZ / 5);
                bh_unlock_sock(sk);
                return 0;
        }
@@ -2516,7 +2722,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        l2cap_chan_del(chan, ECONNRESET);
        bh_unlock_sock(sk);
 
-       l2cap_sock_kill(sk);
+       chan->ops->close(chan->data);
        return 0;
 }
 
@@ -2540,9 +2746,9 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
 
        /* don't delete l2cap channel if sk is owned by user */
        if (sock_owned_by_user(sk)) {
-               sk->sk_state = BT_DISCONN;
-               l2cap_sock_clear_timer(sk);
-               l2cap_sock_set_timer(sk, HZ / 5);
+               l2cap_state_change(chan,BT_DISCONN);
+               __clear_chan_timer(chan);
+               __set_chan_timer(chan, HZ / 5);
                bh_unlock_sock(sk);
                return 0;
        }
@@ -2550,7 +2756,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
        l2cap_chan_del(chan, 0);
        bh_unlock_sock(sk);
 
-       l2cap_sock_kill(sk);
+       chan->ops->close(chan->data);
        return 0;
 }
 
@@ -2858,18 +3064,18 @@ static inline void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan)
 
        control |= chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
 
-       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
                control |= L2CAP_SUPER_RCV_NOT_READY;
                l2cap_send_sframe(chan, control);
-               chan->conn_state |= L2CAP_CONN_RNR_SENT;
+               set_bit(CONN_RNR_SENT, &chan->conn_state);
        }
 
-       if (chan->conn_state & L2CAP_CONN_REMOTE_BUSY)
+       if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
                l2cap_retransmit_frames(chan);
 
        l2cap_ertm_send(chan);
 
-       if (!(chan->conn_state & L2CAP_CONN_LOCAL_BUSY) &&
+       if (!test_bit(CONN_LOCAL_BUSY, &chan->conn_state) &&
                        chan->frames_sent == 0) {
                control |= L2CAP_SUPER_RCV_READY;
                l2cap_send_sframe(chan, control);
@@ -2925,17 +3131,13 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
 
        switch (control & L2CAP_CTRL_SAR) {
        case L2CAP_SDU_UNSEGMENTED:
-               if (chan->conn_state & L2CAP_CONN_SAR_SDU)
+               if (test_bit(CONN_SAR_SDU, &chan->conn_state))
                        goto drop;
 
-               err = sock_queue_rcv_skb(chan->sk, skb);
-               if (!err)
-                       return err;
-
-               break;
+               return chan->ops->recv(chan->data, skb);
 
        case L2CAP_SDU_START:
-               if (chan->conn_state & L2CAP_CONN_SAR_SDU)
+               if (test_bit(CONN_SAR_SDU, &chan->conn_state))
                        goto drop;
 
                chan->sdu_len = get_unaligned_le16(skb->data);
@@ -2954,12 +3156,12 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
 
                memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               chan->conn_state |= L2CAP_CONN_SAR_SDU;
+               set_bit(CONN_SAR_SDU, &chan->conn_state);
                chan->partial_sdu_len = skb->len;
                break;
 
        case L2CAP_SDU_CONTINUE:
-               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
                        goto disconnect;
 
                if (!chan->sdu)
@@ -2974,13 +3176,13 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
                break;
 
        case L2CAP_SDU_END:
-               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
                        goto disconnect;
 
                if (!chan->sdu)
                        goto disconnect;
 
-               if (!(chan->conn_state & L2CAP_CONN_SAR_RETRY)) {
+               if (!test_bit(CONN_SAR_RETRY, &chan->conn_state)) {
                        chan->partial_sdu_len += skb->len;
 
                        if (chan->partial_sdu_len > chan->imtu)
@@ -2994,19 +3196,19 @@ static int l2cap_ertm_reassembly_sdu(struct l2cap_chan *chan, struct sk_buff *sk
 
                _skb = skb_clone(chan->sdu, GFP_ATOMIC);
                if (!_skb) {
-                       chan->conn_state |= L2CAP_CONN_SAR_RETRY;
+                       set_bit(CONN_SAR_RETRY, &chan->conn_state);
                        return -ENOMEM;
                }
 
-               err = sock_queue_rcv_skb(chan->sk, _skb);
+               err = chan->ops->recv(chan->data, _skb);
                if (err < 0) {
                        kfree_skb(_skb);
-                       chan->conn_state |= L2CAP_CONN_SAR_RETRY;
+                       set_bit(CONN_SAR_RETRY, &chan->conn_state);
                        return err;
                }
 
-               chan->conn_state &= ~L2CAP_CONN_SAR_RETRY;
-               chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+               clear_bit(CONN_SAR_RETRY, &chan->conn_state);
+               clear_bit(CONN_SAR_SDU, &chan->conn_state);
 
                kfree_skb(chan->sdu);
                break;
@@ -3042,7 +3244,7 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
                chan->buffer_seq = (chan->buffer_seq + 1) % 64;
        }
 
-       if (!(chan->conn_state & L2CAP_CONN_RNR_SENT))
+       if (!test_bit(CONN_RNR_SENT, &chan->conn_state))
                goto done;
 
        control = chan->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;
@@ -3050,14 +3252,14 @@ static int l2cap_try_push_rx_skb(struct l2cap_chan *chan)
        l2cap_send_sframe(chan, control);
        chan->retry_count = 1;
 
-       del_timer(&chan->retrans_timer);
-       __mod_monitor_timer();
+       __clear_retrans_timer(chan);
+       __set_monitor_timer(chan);
 
-       chan->conn_state |= L2CAP_CONN_WAIT_F;
+       set_bit(CONN_WAIT_F, &chan->conn_state);
 
 done:
-       chan->conn_state &= ~L2CAP_CONN_LOCAL_BUSY;
-       chan->conn_state &= ~L2CAP_CONN_RNR_SENT;
+       clear_bit(CONN_LOCAL_BUSY, &chan->conn_state);
+       clear_bit(CONN_RNR_SENT, &chan->conn_state);
 
        BT_DBG("chan %p, Exit local busy", chan);
 
@@ -3115,7 +3317,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c
 {
        int sctrl, err;
 
-       if (chan->conn_state & L2CAP_CONN_LOCAL_BUSY) {
+       if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
                bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
                __skb_queue_tail(&chan->busy_q, skb);
                return l2cap_try_push_rx_skb(chan);
@@ -3132,7 +3334,7 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c
        /* Busy Condition */
        BT_DBG("chan %p, Enter local busy", chan);
 
-       chan->conn_state |= L2CAP_CONN_LOCAL_BUSY;
+       set_bit(CONN_LOCAL_BUSY, &chan->conn_state);
        bt_cb(skb)->sar = control >> L2CAP_CTRL_SAR_SHIFT;
        __skb_queue_tail(&chan->busy_q, skb);
 
@@ -3140,9 +3342,9 @@ static int l2cap_push_rx_skb(struct l2cap_chan *chan, struct sk_buff *skb, u16 c
        sctrl |= L2CAP_SUPER_RCV_NOT_READY;
        l2cap_send_sframe(chan, sctrl);
 
-       chan->conn_state |= L2CAP_CONN_RNR_SENT;
+       set_bit(CONN_RNR_SENT, &chan->conn_state);
 
-       del_timer(&chan->ack_timer);
+       __clear_ack_timer(chan);
 
        queue_work(_busy_wq, &chan->busy_work);
 
@@ -3161,19 +3363,19 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 
        switch (control & L2CAP_CTRL_SAR) {
        case L2CAP_SDU_UNSEGMENTED:
-               if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+               if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
                        kfree_skb(chan->sdu);
                        break;
                }
 
-               err = sock_queue_rcv_skb(chan->sk, skb);
+               err = chan->ops->recv(chan->data, skb);
                if (!err)
                        return 0;
 
                break;
 
        case L2CAP_SDU_START:
-               if (chan->conn_state & L2CAP_CONN_SAR_SDU) {
+               if (test_bit(CONN_SAR_SDU, &chan->conn_state)) {
                        kfree_skb(chan->sdu);
                        break;
                }
@@ -3194,13 +3396,13 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 
                memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               chan->conn_state |= L2CAP_CONN_SAR_SDU;
+               set_bit(CONN_SAR_SDU, &chan->conn_state);
                chan->partial_sdu_len = skb->len;
                err = 0;
                break;
 
        case L2CAP_SDU_CONTINUE:
-               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
                        break;
 
                memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
@@ -3214,12 +3416,12 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
                break;
 
        case L2CAP_SDU_END:
-               if (!(chan->conn_state & L2CAP_CONN_SAR_SDU))
+               if (!test_bit(CONN_SAR_SDU, &chan->conn_state))
                        break;
 
                memcpy(skb_put(chan->sdu, skb->len), skb->data, skb->len);
 
-               chan->conn_state &= ~L2CAP_CONN_SAR_SDU;
+               clear_bit(CONN_SAR_SDU, &chan->conn_state);
                chan->partial_sdu_len += skb->len;
 
                if (chan->partial_sdu_len > chan->imtu)
@@ -3227,7 +3429,7 @@ static int l2cap_streaming_reassembly_sdu(struct l2cap_chan *chan, struct sk_buf
 
                if (chan->partial_sdu_len == chan->sdu_len) {
                        _skb = skb_clone(chan->sdu, GFP_ATOMIC);
-                       err = sock_queue_rcv_skb(chan->sk, _skb);
+                       err = chan->ops->recv(chan->data, _skb);
                        if (err < 0)
                                kfree_skb(_skb);
                }
@@ -3310,11 +3512,11 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
                                                        tx_seq, rx_control);
 
        if (L2CAP_CTRL_FINAL & rx_control &&
-                       chan->conn_state & L2CAP_CONN_WAIT_F) {
-               del_timer(&chan->monitor_timer);
+                       test_bit(CONN_WAIT_F, &chan->conn_state)) {
+               __clear_monitor_timer(chan);
                if (chan->unacked_frames > 0)
-                       __mod_retrans_timer();
-               chan->conn_state &= ~L2CAP_CONN_WAIT_F;
+                       __set_retrans_timer(chan);
+               clear_bit(CONN_WAIT_F, &chan->conn_state);
        }
 
        chan->expected_ack_seq = req_seq;
@@ -3333,10 +3535,10 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
                goto drop;
        }
 
-       if (chan->conn_state == L2CAP_CONN_LOCAL_BUSY)
+       if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state))
                goto drop;
 
-       if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+       if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
                struct srej_list *first;
 
                first = list_first_entry(&chan->srej_l,
@@ -3350,7 +3552,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
 
                        if (list_empty(&chan->srej_l)) {
                                chan->buffer_seq = chan->buffer_seq_srej;
-                               chan->conn_state &= ~L2CAP_CONN_SREJ_SENT;
+                               clear_bit(CONN_SREJ_SENT, &chan->conn_state);
                                l2cap_send_ack(chan);
                                BT_DBG("chan %p, Exit SREJ_SENT", chan);
                        }
@@ -3379,7 +3581,7 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
                if (tx_seq_offset < expected_tx_seq_offset)
                        goto drop;
 
-               chan->conn_state |= L2CAP_CONN_SREJ_SENT;
+               set_bit(CONN_SREJ_SENT, &chan->conn_state);
 
                BT_DBG("chan %p, Enter SREJ", chan);
 
@@ -3390,18 +3592,18 @@ static inline int l2cap_data_channel_iframe(struct l2cap_chan *chan, u16 rx_cont
                __skb_queue_head_init(&chan->busy_q);
                l2cap_add_to_srej_queue(chan, skb, tx_seq, sar);
 
-               chan->conn_state |= L2CAP_CONN_SEND_PBIT;
+               set_bit(CONN_SEND_PBIT, &chan->conn_state);
 
                l2cap_send_srejframe(chan, tx_seq);
 
-               del_timer(&chan->ack_timer);
+               __clear_ack_timer(chan);
        }
        return 0;
 
 expected:
        chan->expected_tx_seq = (chan->expected_tx_seq + 1) % 64;
 
-       if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
+       if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
                bt_cb(skb)->tx_seq = tx_seq;
                bt_cb(skb)->sar = sar;
                __skb_queue_tail(&chan->srej_q, skb);
@@ -3413,13 +3615,11 @@ expected:
                return 0;
 
        if (rx_control & L2CAP_CTRL_FINAL) {
-               if (chan->conn_state & L2CAP_CONN_REJ_ACT)
-                       chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
-               else
+               if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
                        l2cap_retransmit_frames(chan);
        }
 
-       __mod_ack_timer();
+       __set_ack_timer(chan);
 
        chan->num_acked = (chan->num_acked + 1) % num_to_ack;
        if (chan->num_acked == num_to_ack - 1)
@@ -3441,33 +3641,31 @@ static inline void l2cap_data_channel_rrframe(struct l2cap_chan *chan, u16 rx_co
        l2cap_drop_acked_frames(chan);
 
        if (rx_control & L2CAP_CTRL_POLL) {
-               chan->conn_state |= L2CAP_CONN_SEND_FBIT;
-               if (chan->conn_state & L2CAP_CONN_SREJ_SENT) {
-                       if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+               set_bit(CONN_SEND_FBIT, &chan->conn_state);
+               if (test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
+                       if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
                                        (chan->unacked_frames > 0))
-                               __mod_retrans_timer();
+                               __set_retrans_timer(chan);
 
-                       chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+                       clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
                        l2cap_send_srejtail(chan);
                } else {
                        l2cap_send_i_or_rr_or_rnr(chan);
                }
 
        } else if (rx_control & L2CAP_CTRL_FINAL) {
-               chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+               clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
-               if (chan->conn_state & L2CAP_CONN_REJ_ACT)
-                       chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
-               else
+               if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
                        l2cap_retransmit_frames(chan);
 
        } else {
-               if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
+               if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state) &&
                                (chan->unacked_frames > 0))
-                       __mod_retrans_timer();
+                       __set_retrans_timer(chan);
 
-               chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
-               if (chan->conn_state & L2CAP_CONN_SREJ_SENT)
+               clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+               if (test_bit(CONN_SREJ_SENT, &chan->conn_state))
                        l2cap_send_ack(chan);
                else
                        l2cap_ertm_send(chan);
@@ -3480,21 +3678,19 @@ static inline void l2cap_data_channel_rejframe(struct l2cap_chan *chan, u16 rx_c
 
        BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-       chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+       clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
        chan->expected_ack_seq = tx_seq;
        l2cap_drop_acked_frames(chan);
 
        if (rx_control & L2CAP_CTRL_FINAL) {
-               if (chan->conn_state & L2CAP_CONN_REJ_ACT)
-                       chan->conn_state &= ~L2CAP_CONN_REJ_ACT;
-               else
+               if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state))
                        l2cap_retransmit_frames(chan);
        } else {
                l2cap_retransmit_frames(chan);
 
-               if (chan->conn_state & L2CAP_CONN_WAIT_F)
-                       chan->conn_state |= L2CAP_CONN_REJ_ACT;
+               if (test_bit(CONN_WAIT_F, &chan->conn_state))
+                       set_bit(CONN_REJ_ACT, &chan->conn_state);
        }
 }
 static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_control)
@@ -3503,32 +3699,32 @@ static inline void l2cap_data_channel_srejframe(struct l2cap_chan *chan, u16 rx_
 
        BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-       chan->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
+       clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
 
        if (rx_control & L2CAP_CTRL_POLL) {
                chan->expected_ack_seq = tx_seq;
                l2cap_drop_acked_frames(chan);
 
-               chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+               set_bit(CONN_SEND_FBIT, &chan->conn_state);
                l2cap_retransmit_one_frame(chan, tx_seq);
 
                l2cap_ertm_send(chan);
 
-               if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+               if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
                        chan->srej_save_reqseq = tx_seq;
-                       chan->conn_state |= L2CAP_CONN_SREJ_ACT;
+                       set_bit(CONN_SREJ_ACT, &chan->conn_state);
                }
        } else if (rx_control & L2CAP_CTRL_FINAL) {
-               if ((chan->conn_state & L2CAP_CONN_SREJ_ACT) &&
+               if (test_bit(CONN_SREJ_ACT, &chan->conn_state) &&
                                chan->srej_save_reqseq == tx_seq)
-                       chan->conn_state &= ~L2CAP_CONN_SREJ_ACT;
+                       clear_bit(CONN_SREJ_ACT, &chan->conn_state);
                else
                        l2cap_retransmit_one_frame(chan, tx_seq);
        } else {
                l2cap_retransmit_one_frame(chan, tx_seq);
-               if (chan->conn_state & L2CAP_CONN_WAIT_F) {
+               if (test_bit(CONN_WAIT_F, &chan->conn_state)) {
                        chan->srej_save_reqseq = tx_seq;
-                       chan->conn_state |= L2CAP_CONN_SREJ_ACT;
+                       set_bit(CONN_SREJ_ACT, &chan->conn_state);
                }
        }
 }
@@ -3539,15 +3735,15 @@ static inline void l2cap_data_channel_rnrframe(struct l2cap_chan *chan, u16 rx_c
 
        BT_DBG("chan %p, req_seq %d ctrl 0x%4.4x", chan, tx_seq, rx_control);
 
-       chan->conn_state |= L2CAP_CONN_REMOTE_BUSY;
+       set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
        chan->expected_ack_seq = tx_seq;
        l2cap_drop_acked_frames(chan);
 
        if (rx_control & L2CAP_CTRL_POLL)
-               chan->conn_state |= L2CAP_CONN_SEND_FBIT;
+               set_bit(CONN_SEND_FBIT, &chan->conn_state);
 
-       if (!(chan->conn_state & L2CAP_CONN_SREJ_SENT)) {
-               del_timer(&chan->retrans_timer);
+       if (!test_bit(CONN_SREJ_SENT, &chan->conn_state)) {
+               __clear_retrans_timer(chan);
                if (rx_control & L2CAP_CTRL_POLL)
                        l2cap_send_rr_or_rnr(chan, L2CAP_CTRL_FINAL);
                return;
@@ -3564,11 +3760,11 @@ static inline int l2cap_data_channel_sframe(struct l2cap_chan *chan, u16 rx_cont
        BT_DBG("chan %p rx_control 0x%4.4x len %d", chan, rx_control, skb->len);
 
        if (L2CAP_CTRL_FINAL & rx_control &&
-                       chan->conn_state & L2CAP_CONN_WAIT_F) {
-               del_timer(&chan->monitor_timer);
+                       test_bit(CONN_WAIT_F, &chan->conn_state)) {
+               __clear_monitor_timer(chan);
                if (chan->unacked_frames > 0)
-                       __mod_retrans_timer();
-               chan->conn_state &= ~L2CAP_CONN_WAIT_F;
+                       __set_retrans_timer(chan);
+               clear_bit(CONN_WAIT_F, &chan->conn_state);
        }
 
        switch (rx_control & L2CAP_CTRL_SUPERVISE) {
@@ -3667,7 +3863,6 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
 {
        struct l2cap_chan *chan;
        struct sock *sk = NULL;
-       struct l2cap_pinfo *pi;
        u16 control;
        u8 tx_seq;
        int len;
@@ -3679,11 +3874,10 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
        }
 
        sk = chan->sk;
-       pi = l2cap_pi(sk);
 
        BT_DBG("chan %p, len %d", chan, skb->len);
 
-       if (sk->sk_state != BT_CONNECTED)
+       if (chan->state != BT_CONNECTED)
                goto drop;
 
        switch (chan->mode) {
@@ -3696,7 +3890,7 @@ static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk
                if (chan->imtu < skb->len)
                        goto drop;
 
-               if (!sock_queue_rcv_skb(sk, skb))
+               if (!chan->ops->recv(chan->data, skb))
                        goto done;
                break;
 
@@ -3768,13 +3962,13 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
 
        BT_DBG("sk %p, len %d", sk, skb->len);
 
-       if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+       if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
                goto drop;
 
-       if (l2cap_pi(sk)->chan->imtu < skb->len)
+       if (chan->imtu < skb->len)
                goto drop;
 
-       if (!sock_queue_rcv_skb(sk, skb))
+       if (!chan->ops->recv(chan->data, skb))
                goto done;
 
 drop:
@@ -3801,13 +3995,13 @@ static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct
 
        BT_DBG("sk %p, len %d", sk, skb->len);
 
-       if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
+       if (chan->state != BT_BOUND && chan->state != BT_CONNECTED)
                goto drop;
 
-       if (l2cap_pi(sk)->chan->imtu < skb->len)
+       if (chan->imtu < skb->len)
                goto drop;
 
-       if (!sock_queue_rcv_skb(sk, skb))
+       if (!chan->ops->recv(chan->data, skb))
                goto done;
 
 drop:
@@ -3852,6 +4046,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
                l2cap_att_channel(conn, cid, skb);
                break;
 
+       case L2CAP_CID_SMP:
+               if (smp_sig_channel(conn, skb))
+                       l2cap_conn_del(conn->hcon, EACCES);
+               break;
+
        default:
                l2cap_data_channel(conn, cid, skb);
                break;
@@ -3875,7 +4074,7 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
        list_for_each_entry(c, &chan_list, global_l) {
                struct sock *sk = c->sk;
 
-               if (sk->sk_state != BT_LISTEN)
+               if (c->state != BT_LISTEN)
                        continue;
 
                if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) {
@@ -3919,7 +4118,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon)
 
        BT_DBG("hcon %p", hcon);
 
-       if (hcon->type != ACL_LINK || !conn)
+       if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn)
                return 0x13;
 
        return conn->disc_reason;
@@ -3939,20 +4138,18 @@ static int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
 
 static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
 {
-       struct sock *sk = chan->sk;
-
-       if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM)
+       if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED)
                return;
 
        if (encrypt == 0x00) {
                if (chan->sec_level == BT_SECURITY_MEDIUM) {
-                       l2cap_sock_clear_timer(sk);
-                       l2cap_sock_set_timer(sk, HZ * 5);
+                       __clear_chan_timer(chan);
+                       __set_chan_timer(chan, HZ * 5);
                } else if (chan->sec_level == BT_SECURITY_HIGH)
-                       __l2cap_sock_close(sk, ECONNREFUSED);
+                       l2cap_chan_close(chan, ECONNREFUSED);
        } else {
                if (chan->sec_level == BT_SECURITY_MEDIUM)
-                       l2cap_sock_clear_timer(sk);
+                       __clear_chan_timer(chan);
        }
 }
 
@@ -3973,50 +4170,72 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
 
                bh_lock_sock(sk);
 
-               if (chan->conf_state & L2CAP_CONF_CONNECT_PEND) {
+               BT_DBG("chan->scid %d", chan->scid);
+
+               if (chan->scid == L2CAP_CID_LE_DATA) {
+                       if (!status && encrypt) {
+                               chan->sec_level = hcon->sec_level;
+                               del_timer(&conn->security_timer);
+                               l2cap_chan_ready(sk);
+                       }
+
                        bh_unlock_sock(sk);
                        continue;
                }
 
-               if (!status && (sk->sk_state == BT_CONNECTED ||
-                                               sk->sk_state == BT_CONFIG)) {
+               if (test_bit(CONF_CONNECT_PEND, &chan->conf_state)) {
+                       bh_unlock_sock(sk);
+                       continue;
+               }
+
+               if (!status && (chan->state == BT_CONNECTED ||
+                                               chan->state == BT_CONFIG)) {
                        l2cap_check_encryption(chan, encrypt);
                        bh_unlock_sock(sk);
                        continue;
                }
 
-               if (sk->sk_state == BT_CONNECT) {
+               if (chan->state == BT_CONNECT) {
                        if (!status) {
                                struct l2cap_conn_req req;
                                req.scid = cpu_to_le16(chan->scid);
                                req.psm  = chan->psm;
 
                                chan->ident = l2cap_get_ident(conn);
-                               chan->conf_state |= L2CAP_CONF_CONNECT_PEND;
+                               set_bit(CONF_CONNECT_PEND, &chan->conf_state);
 
                                l2cap_send_cmd(conn, chan->ident,
                                        L2CAP_CONN_REQ, sizeof(req), &req);
                        } else {
-                               l2cap_sock_clear_timer(sk);
-                               l2cap_sock_set_timer(sk, HZ / 10);
+                               __clear_chan_timer(chan);
+                               __set_chan_timer(chan, HZ / 10);
                        }
-               } else if (sk->sk_state == BT_CONNECT2) {
+               } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
-                       __u16 result;
+                       __u16 res, stat;
 
                        if (!status) {
-                               sk->sk_state = BT_CONFIG;
-                               result = L2CAP_CR_SUCCESS;
+                               if (bt_sk(sk)->defer_setup) {
+                                       struct sock *parent = bt_sk(sk)->parent;
+                                       res = L2CAP_CR_PEND;
+                                       stat = L2CAP_CS_AUTHOR_PEND;
+                                       parent->sk_data_ready(parent, 0);
+                               } else {
+                                       l2cap_state_change(chan, BT_CONFIG);
+                                       res = L2CAP_CR_SUCCESS;
+                                       stat = L2CAP_CS_NO_INFO;
+                               }
                        } else {
-                               sk->sk_state = BT_DISCONN;
-                               l2cap_sock_set_timer(sk, HZ / 10);
-                               result = L2CAP_CR_SEC_BLOCK;
+                               l2cap_state_change(chan, BT_DISCONN);
+                               __set_chan_timer(chan, HZ / 10);
+                               res = L2CAP_CR_SEC_BLOCK;
+                               stat = L2CAP_CS_NO_INFO;
                        }
 
                        rsp.scid   = cpu_to_le16(chan->dcid);
                        rsp.dcid   = cpu_to_le16(chan->scid);
-                       rsp.result = cpu_to_le16(result);
-                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+                       rsp.result = cpu_to_le16(res);
+                       rsp.status = cpu_to_le16(stat);
                        l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
                                                        sizeof(rsp), &rsp);
                }
@@ -4152,10 +4371,10 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p)
                seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n",
                                        batostr(&bt_sk(sk)->src),
                                        batostr(&bt_sk(sk)->dst),
-                                       sk->sk_state, __le16_to_cpu(c->psm),
+                                       c->state, __le16_to_cpu(c->psm),
                                        c->scid, c->dcid, c->imtu, c->omtu,
                                        c->sec_level, c->mode);
-       }
+}
 
        read_unlock_bh(&chan_list_lock);
 
index 8248303..39082d4 100644 (file)
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
 
 static const struct proto_ops l2cap_sock_ops;
-
-/* ---- L2CAP timers ---- */
-static void l2cap_sock_timeout(unsigned long arg)
-{
-       struct sock *sk = (struct sock *) arg;
-       int reason;
-
-       BT_DBG("sock %p state %d", sk, sk->sk_state);
-
-       bh_lock_sock(sk);
-
-       if (sock_owned_by_user(sk)) {
-               /* sk is owned by user. Try again later */
-               l2cap_sock_set_timer(sk, HZ / 5);
-               bh_unlock_sock(sk);
-               sock_put(sk);
-               return;
-       }
-
-       if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
-               reason = ECONNREFUSED;
-       else if (sk->sk_state == BT_CONNECT &&
-                       l2cap_pi(sk)->chan->sec_level != BT_SECURITY_SDP)
-               reason = ECONNREFUSED;
-       else
-               reason = ETIMEDOUT;
-
-       __l2cap_sock_close(sk, reason);
-
-       bh_unlock_sock(sk);
-
-       l2cap_sock_kill(sk);
-       sock_put(sk);
-}
-
-void l2cap_sock_set_timer(struct sock *sk, long timeout)
-{
-       BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
-       sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
-}
-
-void l2cap_sock_clear_timer(struct sock *sk)
-{
-       BT_DBG("sock %p state %d", sk, sk->sk_state);
-       sk_stop_timer(sk, &sk->sk_timer);
-}
+static void l2cap_sock_init(struct sock *sk, struct sock *parent);
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio);
 
 static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
 {
@@ -133,6 +90,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
                chan->sec_level = BT_SECURITY_SDP;
 
        bacpy(&bt_sk(sk)->src, &la.l2_bdaddr);
+
+       chan->state = BT_BOUND;
        sk->sk_state = BT_BOUND;
 
 done:
@@ -162,7 +121,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
 
        lock_sock(sk);
 
-       if ((sk->sk_type == SOCK_SEQPACKET || sk->sk_type == SOCK_STREAM)
+       if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED
                        && !(la.l2_psm || la.l2_cid)) {
                err = -EINVAL;
                goto done;
@@ -204,8 +163,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
        }
 
        /* PSM must be odd and lsb of upper byte must be 0 */
-       if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 &&
-                               sk->sk_type != SOCK_RAW && !la.l2_cid) {
+       if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && !la.l2_cid &&
+                                       chan->chan_type != L2CAP_CHAN_RAW) {
                err = -EINVAL;
                goto done;
        }
@@ -258,6 +217,8 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
 
        sk->sk_max_ack_backlog = backlog;
        sk->sk_ack_backlog = 0;
+
+       chan->state = BT_LISTEN;
        sk->sk_state = BT_LISTEN;
 
 done:
@@ -437,6 +398,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
        struct bt_security sec;
+       struct bt_power pwr;
        int len, err = 0;
 
        BT_DBG("sk %p", sk);
@@ -454,8 +416,8 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
        switch (optname) {
        case BT_SECURITY:
-               if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-                               && sk->sk_type != SOCK_RAW) {
+               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+                                       chan->chan_type != L2CAP_CHAN_RAW) {
                        err = -EINVAL;
                        break;
                }
@@ -485,6 +447,21 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch
 
                break;
 
+       case BT_POWER:
+               if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
+                               && sk->sk_type != SOCK_RAW) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               pwr.force_active = chan->force_active;
+
+               len = min_t(unsigned int, len, sizeof(pwr));
+               if (copy_to_user(optval, (char *) &pwr, len))
+                       err = -EFAULT;
+
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -535,7 +512,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us
                chan->mode = opts.mode;
                switch (chan->mode) {
                case L2CAP_MODE_BASIC:
-                       chan->conf_state &= ~L2CAP_CONF_STATE2_DEVICE;
+                       clear_bit(CONF_STATE2_DEVICE, &chan->conf_state);
                        break;
                case L2CAP_MODE_ERTM:
                case L2CAP_MODE_STREAMING:
@@ -585,6 +562,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
        struct bt_security sec;
+       struct bt_power pwr;
+       struct l2cap_conn *conn;
        int len, err = 0;
        u32 opt;
 
@@ -600,8 +579,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
 
        switch (optname) {
        case BT_SECURITY:
-               if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
-                               && sk->sk_type != SOCK_RAW) {
+               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+                                       chan->chan_type != L2CAP_CHAN_RAW) {
                        err = -EINVAL;
                        break;
                }
@@ -621,6 +600,20 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                }
 
                chan->sec_level = sec.level;
+
+               conn = chan->conn;
+               if (conn && chan->scid == L2CAP_CID_LE_DATA) {
+                       if (!conn->hcon->out) {
+                               err = -EINVAL;
+                               break;
+                       }
+
+                       if (smp_conn_security(conn, sec.level))
+                               break;
+
+                       err = 0;
+                       sk->sk_state = BT_CONFIG;
+               }
                break;
 
        case BT_DEFER_SETUP:
@@ -661,6 +654,23 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                chan->flushable = opt;
                break;
 
+       case BT_POWER:
+               if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED &&
+                                       chan->chan_type != L2CAP_CHAN_RAW) {
+                       err = -EINVAL;
+                       break;
+               }
+
+               pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
+
+               len = min_t(unsigned int, sizeof(pwr), optlen);
+               if (copy_from_user((char *) &pwr, optval, len)) {
+                       err = -EFAULT;
+                       break;
+               }
+               chan->force_active = pwr.force_active;
+               break;
+
        default:
                err = -ENOPROTOOPT;
                break;
@@ -674,8 +684,6 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
 {
        struct sock *sk = sock->sk;
        struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-       struct sk_buff *skb;
-       u16 control;
        int err;
 
        BT_DBG("sock %p, sk %p", sock, sk);
@@ -690,87 +698,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
        lock_sock(sk);
 
        if (sk->sk_state != BT_CONNECTED) {
-               err = -ENOTCONN;
-               goto done;
-       }
-
-       /* Connectionless channel */
-       if (sk->sk_type == SOCK_DGRAM) {
-               skb = l2cap_create_connless_pdu(chan, msg, len);
-               if (IS_ERR(skb)) {
-                       err = PTR_ERR(skb);
-               } else {
-                       l2cap_do_send(chan, skb);
-                       err = len;
-               }
-               goto done;
+               release_sock(sk);
+               return -ENOTCONN;
        }
 
-       switch (chan->mode) {
-       case L2CAP_MODE_BASIC:
-               /* Check outgoing MTU */
-               if (len > chan->omtu) {
-                       err = -EMSGSIZE;
-                       goto done;
-               }
-
-               /* Create a basic PDU */
-               skb = l2cap_create_basic_pdu(chan, msg, len);
-               if (IS_ERR(skb)) {
-                       err = PTR_ERR(skb);
-                       goto done;
-               }
-
-               l2cap_do_send(chan, skb);
-               err = len;
-               break;
-
-       case L2CAP_MODE_ERTM:
-       case L2CAP_MODE_STREAMING:
-               /* Entire SDU fits into one PDU */
-               if (len <= chan->remote_mps) {
-                       control = L2CAP_SDU_UNSEGMENTED;
-                       skb = l2cap_create_iframe_pdu(chan, msg, len, control,
-                                                                       0);
-                       if (IS_ERR(skb)) {
-                               err = PTR_ERR(skb);
-                               goto done;
-                       }
-                       __skb_queue_tail(&chan->tx_q, skb);
-
-                       if (chan->tx_send_head == NULL)
-                               chan->tx_send_head = skb;
-
-               } else {
-               /* Segment SDU into multiples PDUs */
-                       err = l2cap_sar_segment_sdu(chan, msg, len);
-                       if (err < 0)
-                               goto done;
-               }
-
-               if (chan->mode == L2CAP_MODE_STREAMING) {
-                       l2cap_streaming_send(chan);
-                       err = len;
-                       break;
-               }
-
-               if ((chan->conn_state & L2CAP_CONN_REMOTE_BUSY) &&
-                               (chan->conn_state & L2CAP_CONN_WAIT_F)) {
-                       err = len;
-                       break;
-               }
-               err = l2cap_ertm_send(chan);
-
-               if (err >= 0)
-                       err = len;
-               break;
-
-       default:
-               BT_DBG("bad state %1.1x", chan->mode);
-               err = -EBADFD;
-       }
+       err = l2cap_chan_send(chan, msg, len);
 
-done:
        release_sock(sk);
        return err;
 }
@@ -800,7 +733,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms
 /* Kill socket (only if zapped and orphan)
  * Must be called on unlocked socket.
  */
-void l2cap_sock_kill(struct sock *sk)
+static void l2cap_sock_kill(struct sock *sk)
 {
        if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
                return;
@@ -814,87 +747,6 @@ void l2cap_sock_kill(struct sock *sk)
        sock_put(sk);
 }
 
-/* Must be called on unlocked socket. */
-static void l2cap_sock_close(struct sock *sk)
-{
-       l2cap_sock_clear_timer(sk);
-       lock_sock(sk);
-       __l2cap_sock_close(sk, ECONNRESET);
-       release_sock(sk);
-       l2cap_sock_kill(sk);
-}
-
-static void l2cap_sock_cleanup_listen(struct sock *parent)
-{
-       struct sock *sk;
-
-       BT_DBG("parent %p", parent);
-
-       /* Close not yet accepted channels */
-       while ((sk = bt_accept_dequeue(parent, NULL)))
-               l2cap_sock_close(sk);
-
-       parent->sk_state = BT_CLOSED;
-       sock_set_flag(parent, SOCK_ZAPPED);
-}
-
-void __l2cap_sock_close(struct sock *sk, int reason)
-{
-       struct l2cap_chan *chan = l2cap_pi(sk)->chan;
-       struct l2cap_conn *conn = chan->conn;
-
-       BT_DBG("sk %p state %d socket %p", sk, sk->sk_state, sk->sk_socket);
-
-       switch (sk->sk_state) {
-       case BT_LISTEN:
-               l2cap_sock_cleanup_listen(sk);
-               break;
-
-       case BT_CONNECTED:
-       case BT_CONFIG:
-               if ((sk->sk_type == SOCK_SEQPACKET ||
-                                       sk->sk_type == SOCK_STREAM) &&
-                                       conn->hcon->type == ACL_LINK) {
-                       l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
-                       l2cap_send_disconn_req(conn, chan, reason);
-               } else
-                       l2cap_chan_del(chan, reason);
-               break;
-
-       case BT_CONNECT2:
-               if ((sk->sk_type == SOCK_SEQPACKET ||
-                                       sk->sk_type == SOCK_STREAM) &&
-                                       conn->hcon->type == ACL_LINK) {
-                       struct l2cap_conn_rsp rsp;
-                       __u16 result;
-
-                       if (bt_sk(sk)->defer_setup)
-                               result = L2CAP_CR_SEC_BLOCK;
-                       else
-                               result = L2CAP_CR_BAD_PSM;
-
-                       rsp.scid   = cpu_to_le16(chan->dcid);
-                       rsp.dcid   = cpu_to_le16(chan->scid);
-                       rsp.result = cpu_to_le16(result);
-                       rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
-                       l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP,
-                                                       sizeof(rsp), &rsp);
-               }
-
-               l2cap_chan_del(chan, reason);
-               break;
-
-       case BT_CONNECT:
-       case BT_DISCONN:
-               l2cap_chan_del(chan, reason);
-               break;
-
-       default:
-               sock_set_flag(sk, SOCK_ZAPPED);
-               break;
-       }
-}
-
 static int l2cap_sock_shutdown(struct socket *sock, int how)
 {
        struct sock *sk = sock->sk;
@@ -912,8 +764,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how)
                        err = __l2cap_wait_ack(sk);
 
                sk->sk_shutdown = SHUTDOWN_MASK;
-               l2cap_sock_clear_timer(sk);
-               __l2cap_sock_close(sk, 0);
+               l2cap_chan_close(chan, 0);
 
                if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
                        err = bt_sock_wait_state(sk, BT_CLOSED,
@@ -944,6 +795,49 @@ static int l2cap_sock_release(struct socket *sock)
        return err;
 }
 
+static struct l2cap_chan *l2cap_sock_new_connection_cb(void *data)
+{
+       struct sock *sk, *parent = data;
+
+       sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
+                                                               GFP_ATOMIC);
+       if (!sk)
+               return NULL;
+
+       l2cap_sock_init(sk, parent);
+
+       return l2cap_pi(sk)->chan;
+}
+
+static int l2cap_sock_recv_cb(void *data, struct sk_buff *skb)
+{
+       struct sock *sk = data;
+
+       return sock_queue_rcv_skb(sk, skb);
+}
+
+static void l2cap_sock_close_cb(void *data)
+{
+       struct sock *sk = data;
+
+       l2cap_sock_kill(sk);
+}
+
+static void l2cap_sock_state_change_cb(void *data, int state)
+{
+       struct sock *sk = data;
+
+       sk->sk_state = state;
+}
+
+static struct l2cap_ops l2cap_chan_ops = {
+       .name           = "L2CAP Socket Interface",
+       .new_connection = l2cap_sock_new_connection_cb,
+       .recv           = l2cap_sock_recv_cb,
+       .close          = l2cap_sock_close_cb,
+       .state_change   = l2cap_sock_state_change_cb,
+};
+
 static void l2cap_sock_destruct(struct sock *sk)
 {
        BT_DBG("sk %p", sk);
@@ -952,7 +846,7 @@ static void l2cap_sock_destruct(struct sock *sk)
        skb_queue_purge(&sk->sk_write_queue);
 }
 
-void l2cap_sock_init(struct sock *sk, struct sock *parent)
+static void l2cap_sock_init(struct sock *sk, struct sock *parent)
 {
        struct l2cap_pinfo *pi = l2cap_pi(sk);
        struct l2cap_chan *chan = pi->chan;
@@ -965,6 +859,7 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
                sk->sk_type = parent->sk_type;
                bt_sk(sk)->defer_setup = bt_sk(parent)->defer_setup;
 
+               chan->chan_type = pchan->chan_type;
                chan->imtu = pchan->imtu;
                chan->omtu = pchan->omtu;
                chan->conf_state = pchan->conf_state;
@@ -976,12 +871,27 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
                chan->role_switch = pchan->role_switch;
                chan->force_reliable = pchan->force_reliable;
                chan->flushable = pchan->flushable;
+               chan->force_active = pchan->force_active;
        } else {
+
+               switch (sk->sk_type) {
+               case SOCK_RAW:
+                       chan->chan_type = L2CAP_CHAN_RAW;
+                       break;
+               case SOCK_DGRAM:
+                       chan->chan_type = L2CAP_CHAN_CONN_LESS;
+                       break;
+               case SOCK_SEQPACKET:
+               case SOCK_STREAM:
+                       chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
+                       break;
+               }
+
                chan->imtu = L2CAP_DEFAULT_MTU;
                chan->omtu = 0;
                if (!disable_ertm && sk->sk_type == SOCK_STREAM) {
                        chan->mode = L2CAP_MODE_ERTM;
-                       chan->conf_state |= L2CAP_CONF_STATE2_DEVICE;
+                       set_bit(CONF_STATE2_DEVICE, &chan->conf_state);
                } else {
                        chan->mode = L2CAP_MODE_BASIC;
                }
@@ -992,10 +902,15 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent)
                chan->role_switch = 0;
                chan->force_reliable = 0;
                chan->flushable = BT_FLUSHABLE_OFF;
+               chan->force_active = BT_POWER_FORCE_ACTIVE_ON;
+
        }
 
        /* Default config options */
        chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+
+       chan->data = sk;
+       chan->ops = &l2cap_chan_ops;
 }
 
 static struct proto l2cap_proto = {
@@ -1004,9 +919,10 @@ static struct proto l2cap_proto = {
        .obj_size       = sizeof(struct l2cap_pinfo)
 };
 
-struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
+static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio)
 {
        struct sock *sk;
+       struct l2cap_chan *chan;
 
        sk = sk_alloc(net, PF_BLUETOOTH, prio, &l2cap_proto);
        if (!sk)
@@ -1023,7 +939,13 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g
        sk->sk_protocol = proto;
        sk->sk_state = BT_OPEN;
 
-       setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk);
+       chan = l2cap_chan_create(sk);
+       if (!chan) {
+               l2cap_sock_kill(sk);
+               return NULL;
+       }
+
+       l2cap_pi(sk)->chan = chan;
 
        return sk;
 }
@@ -1032,7 +954,6 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
                             int kern)
 {
        struct sock *sk;
-       struct l2cap_chan *chan;
 
        BT_DBG("sock %p", sock);
 
@@ -1051,14 +972,6 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
        if (!sk)
                return -ENOMEM;
 
-       chan = l2cap_chan_create(sk);
-       if (!chan) {
-               l2cap_sock_kill(sk);
-               return -ENOMEM;
-       }
-
-       l2cap_pi(sk)->chan = chan;
-
        l2cap_sock_init(sk, NULL);
        return 0;
 }
index dae382c..64c0418 100644 (file)
@@ -41,7 +41,7 @@ struct pending_cmd {
        void *user_data;
 };
 
-LIST_HEAD(cmd_list);
+static LIST_HEAD(cmd_list);
 
 static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
 {
@@ -990,7 +990,7 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
 
                put_unaligned_le16(conn->handle, &dc.handle);
                dc.reason = 0x13; /* Remote User Terminated Connection */
-               err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, 0, NULL);
+               err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
        }
 
 unlock:
@@ -1092,8 +1092,6 @@ static int get_connections(struct sock *sk, u16 index)
 
        put_unaligned_le16(count, &rp->conn_count);
 
-       read_lock(&hci_dev_list_lock);
-
        i = 0;
        list_for_each(p, &hdev->conn_hash.list) {
                struct hci_conn *c = list_entry(p, struct hci_conn, list);
@@ -1101,8 +1099,6 @@ static int get_connections(struct sock *sk, u16 index)
                bacpy(&rp->conn[i++], &c->dst);
        }
 
-       read_unlock(&hci_dev_list_lock);
-
        err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
 
 unlock:
@@ -1112,11 +1108,32 @@ unlock:
        return err;
 }
 
+static int send_pin_code_neg_reply(struct sock *sk, u16 index,
+               struct hci_dev *hdev, struct mgmt_cp_pin_code_neg_reply *cp)
+{
+       struct pending_cmd *cmd;
+       int err;
+
+       cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index, cp,
+                                                               sizeof(*cp));
+       if (!cmd)
+               return -ENOMEM;
+
+       err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
+                                                               &cp->bdaddr);
+       if (err < 0)
+               mgmt_pending_remove(cmd);
+
+       return err;
+}
+
 static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
                                                                        u16 len)
 {
        struct hci_dev *hdev;
+       struct hci_conn *conn;
        struct mgmt_cp_pin_code_reply *cp;
+       struct mgmt_cp_pin_code_neg_reply ncp;
        struct hci_cp_pin_code_reply reply;
        struct pending_cmd *cmd;
        int err;
@@ -1139,6 +1156,25 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
                goto failed;
        }
 
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
+       if (!conn) {
+               err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENOTCONN);
+               goto failed;
+       }
+
+       if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
+               bacpy(&ncp.bdaddr, &cp->bdaddr);
+
+               BT_ERR("PIN code is not 16 bytes long");
+
+               err = send_pin_code_neg_reply(sk, index, hdev, &ncp);
+               if (err >= 0)
+                       err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY,
+                                                               EINVAL);
+
+               goto failed;
+       }
+
        cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
        if (!cmd) {
                err = -ENOMEM;
@@ -1147,7 +1183,7 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
 
        bacpy(&reply.bdaddr, &cp->bdaddr);
        reply.pin_len = cp->pin_len;
-       memcpy(reply.pin_code, cp->pin_code, 16);
+       memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
 
        err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
        if (err < 0)
@@ -1165,7 +1201,6 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
 {
        struct hci_dev *hdev;
        struct mgmt_cp_pin_code_neg_reply *cp;
-       struct pending_cmd *cmd;
        int err;
 
        BT_DBG("");
@@ -1189,17 +1224,7 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
                goto failed;
        }
 
-       cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
-                                                               data, len);
-       if (!cmd) {
-               err = -ENOMEM;
-               goto failed;
-       }
-
-       err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(cp->bdaddr),
-                                                               &cp->bdaddr);
-       if (err < 0)
-               mgmt_pending_remove(cmd);
+       err = send_pin_code_neg_reply(sk, index, hdev, cp);
 
 failed:
        hci_dev_unlock(hdev);
@@ -1641,6 +1666,70 @@ failed:
        return err;
 }
 
+static int block_device(struct sock *sk, u16 index, unsigned char *data,
+                                                               u16 len)
+{
+       struct hci_dev *hdev;
+       struct mgmt_cp_block_device *cp;
+       int err;
+
+       BT_DBG("hci%u", index);
+
+       cp = (void *) data;
+
+       if (len != sizeof(*cp))
+               return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+                                                       EINVAL);
+
+       hdev = hci_dev_get(index);
+       if (!hdev)
+               return cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE,
+                                                       ENODEV);
+
+       err = hci_blacklist_add(hdev, &cp->bdaddr);
+
+       if (err < 0)
+               err = cmd_status(sk, index, MGMT_OP_BLOCK_DEVICE, -err);
+       else
+               err = cmd_complete(sk, index, MGMT_OP_BLOCK_DEVICE,
+                                                       NULL, 0);
+       hci_dev_put(hdev);
+
+       return err;
+}
+
+static int unblock_device(struct sock *sk, u16 index, unsigned char *data,
+                                                               u16 len)
+{
+       struct hci_dev *hdev;
+       struct mgmt_cp_unblock_device *cp;
+       int err;
+
+       BT_DBG("hci%u", index);
+
+       cp = (void *) data;
+
+       if (len != sizeof(*cp))
+               return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+                                                               EINVAL);
+
+       hdev = hci_dev_get(index);
+       if (!hdev)
+               return cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+                                                               ENODEV);
+
+       err = hci_blacklist_del(hdev, &cp->bdaddr);
+
+       if (err < 0)
+               err = cmd_status(sk, index, MGMT_OP_UNBLOCK_DEVICE, -err);
+       else
+               err = cmd_complete(sk, index, MGMT_OP_UNBLOCK_DEVICE,
+                                                               NULL, 0);
+       hci_dev_put(hdev);
+
+       return err;
+}
+
 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
 {
        unsigned char *buf;
@@ -1755,6 +1844,12 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
        case MGMT_OP_STOP_DISCOVERY:
                err = stop_discovery(sk, index);
                break;
+       case MGMT_OP_BLOCK_DEVICE:
+               err = block_device(sk, index, buf + sizeof(*hdr), len);
+               break;
+       case MGMT_OP_UNBLOCK_DEVICE:
+               err = unblock_device(sk, index, buf + sizeof(*hdr), len);
+               break;
        default:
                BT_DBG("Unknown op %u", opcode);
                err = cmd_status(sk, index, opcode, 0x01);
index 1b10727..8f01e6b 100644 (file)
@@ -679,7 +679,8 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
 {
        struct sock *sk = sock->sk;
        struct bt_security sec;
-       int len, err = 0;
+       int err = 0;
+       size_t len;
        u32 opt;
 
        BT_DBG("sk %p", sk);
@@ -741,7 +742,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, c
 static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
 {
        struct sock *sk = sock->sk;
-       struct sock *l2cap_sk;
        struct rfcomm_conninfo cinfo;
        struct l2cap_conn *conn = l2cap_pi(sk)->chan->conn;
        int len, err = 0;
@@ -786,8 +786,6 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
                        break;
                }
 
-               l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
-
                memset(&cinfo, 0, sizeof(cinfo));
                cinfo.hci_handle = conn->hcon->handle;
                memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
new file mode 100644 (file)
index 0000000..a36f870
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+   BlueZ - Bluetooth protocol stack for Linux
+   Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License version 2 as
+   published by the Free Software Foundation;
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
+   CLAIM, OR ANY SPECIAL 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.
+
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
+   SOFTWARE IS DISCLAIMED.
+*/
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
+#include <net/bluetooth/smp.h>
+#include <linux/crypto.h>
+#include <linux/scatterlist.h>
+#include <crypto/b128ops.h>
+
+#define SMP_TIMEOUT 30000 /* 30 seconds */
+
+static inline void swap128(u8 src[16], u8 dst[16])
+{
+       int i;
+       for (i = 0; i < 16; i++)
+               dst[15 - i] = src[i];
+}
+
+static inline void swap56(u8 src[7], u8 dst[7])
+{
+       int i;
+       for (i = 0; i < 7; i++)
+               dst[6 - i] = src[i];
+}
+
+static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
+{
+       struct blkcipher_desc desc;
+       struct scatterlist sg;
+       int err, iv_len;
+       unsigned char iv[128];
+
+       if (tfm == NULL) {
+               BT_ERR("tfm %p", tfm);
+               return -EINVAL;
+       }
+
+       desc.tfm = tfm;
+       desc.flags = 0;
+
+       err = crypto_blkcipher_setkey(tfm, k, 16);
+       if (err) {
+               BT_ERR("cipher setkey failed: %d", err);
+               return err;
+       }
+
+       sg_init_one(&sg, r, 16);
+
+       iv_len = crypto_blkcipher_ivsize(tfm);
+       if (iv_len) {
+               memset(&iv, 0xff, iv_len);
+               crypto_blkcipher_set_iv(tfm, iv, iv_len);
+       }
+
+       err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16);
+       if (err)
+               BT_ERR("Encrypt data error %d", err);
+
+       return err;
+}
+
+static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16],
+               u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia,
+               u8 _rat, bdaddr_t *ra, u8 res[16])
+{
+       u8 p1[16], p2[16];
+       int err;
+
+       memset(p1, 0, 16);
+
+       /* p1 = pres || preq || _rat || _iat */
+       swap56(pres, p1);
+       swap56(preq, p1 + 7);
+       p1[14] = _rat;
+       p1[15] = _iat;
+
+       memset(p2, 0, 16);
+
+       /* p2 = padding || ia || ra */
+       baswap((bdaddr_t *) (p2 + 4), ia);
+       baswap((bdaddr_t *) (p2 + 10), ra);
+
+       /* res = r XOR p1 */
+       u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+       /* res = e(k, res) */
+       err = smp_e(tfm, k, res);
+       if (err) {
+               BT_ERR("Encrypt data error");
+               return err;
+       }
+
+       /* res = res XOR p2 */
+       u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+       /* res = e(k, res) */
+       err = smp_e(tfm, k, res);
+       if (err)
+               BT_ERR("Encrypt data error");
+
+       return err;
+}
+
+static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16],
+                       u8 r1[16], u8 r2[16], u8 _r[16])
+{
+       int err;
+
+       /* Just least significant octets from r1 and r2 are considered */
+       memcpy(_r, r1 + 8, 8);
+       memcpy(_r + 8, r2 + 8, 8);
+
+       err = smp_e(tfm, k, _r);
+       if (err)
+               BT_ERR("Encrypt data error");
+
+       return err;
+}
+
+static int smp_rand(u8 *buf)
+{
+       get_random_bytes(buf, 16);
+
+       return 0;
+}
+
+static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code,
+                                               u16 dlen, void *data)
+{
+       struct sk_buff *skb;
+       struct l2cap_hdr *lh;
+       int len;
+
+       len = L2CAP_HDR_SIZE + sizeof(code) + dlen;
+
+       if (len > conn->mtu)
+               return NULL;
+
+       skb = bt_skb_alloc(len, GFP_ATOMIC);
+       if (!skb)
+               return NULL;
+
+       lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
+       lh->len = cpu_to_le16(sizeof(code) + dlen);
+       lh->cid = cpu_to_le16(L2CAP_CID_SMP);
+
+       memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code));
+
+       memcpy(skb_put(skb, dlen), data, dlen);
+
+       return skb;
+}
+
+static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
+{
+       struct sk_buff *skb = smp_build_cmd(conn, code, len, data);
+
+       BT_DBG("code 0x%2.2x", code);
+
+       if (!skb)
+               return;
+
+       hci_send_acl(conn->hcon, skb, 0);
+}
+
+static __u8 seclevel_to_authreq(__u8 level)
+{
+       switch (level) {
+       case BT_SECURITY_HIGH:
+               /* Right now we don't support bonding */
+               return SMP_AUTH_MITM;
+
+       default:
+               return SMP_AUTH_NONE;
+       }
+}
+
+static void build_pairing_cmd(struct l2cap_conn *conn,
+                               struct smp_cmd_pairing *cmd, __u8 authreq)
+{
+       cmd->io_capability = conn->hcon->io_capability;
+       cmd->oob_flag = SMP_OOB_NOT_PRESENT;
+       cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
+       cmd->init_key_dist = 0x00;
+       cmd->resp_key_dist = 0x00;
+       cmd->auth_req = authreq;
+}
+
+static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
+{
+       if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
+                       (max_key_size < SMP_MIN_ENC_KEY_SIZE))
+               return SMP_ENC_KEY_SIZE;
+
+       conn->smp_key_size = max_key_size;
+
+       return 0;
+}
+
+static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct smp_cmd_pairing rsp, *req = (void *) skb->data;
+       u8 key_size;
+
+       BT_DBG("conn %p", conn);
+
+       conn->preq[0] = SMP_CMD_PAIRING_REQ;
+       memcpy(&conn->preq[1], req, sizeof(*req));
+       skb_pull(skb, sizeof(*req));
+
+       if (req->oob_flag)
+               return SMP_OOB_NOT_AVAIL;
+
+       /* We didn't start the pairing, so no requirements */
+       build_pairing_cmd(conn, &rsp, SMP_AUTH_NONE);
+
+       key_size = min(req->max_key_size, rsp.max_key_size);
+       if (check_enc_key_size(conn, key_size))
+               return SMP_ENC_KEY_SIZE;
+
+       /* Just works */
+       memset(conn->tk, 0, sizeof(conn->tk));
+
+       conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+       memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
+
+       smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
+
+       mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
+       return 0;
+}
+
+static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
+       struct smp_cmd_pairing_confirm cp;
+       struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+       int ret;
+       u8 res[16], key_size;
+
+       BT_DBG("conn %p", conn);
+
+       skb_pull(skb, sizeof(*rsp));
+
+       req = (void *) &conn->preq[1];
+
+       key_size = min(req->max_key_size, rsp->max_key_size);
+       if (check_enc_key_size(conn, key_size))
+               return SMP_ENC_KEY_SIZE;
+
+       if (rsp->oob_flag)
+               return SMP_OOB_NOT_AVAIL;
+
+       /* Just works */
+       memset(conn->tk, 0, sizeof(conn->tk));
+
+       conn->prsp[0] = SMP_CMD_PAIRING_RSP;
+       memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
+
+       ret = smp_rand(conn->prnd);
+       if (ret)
+               return SMP_UNSPECIFIED;
+
+       ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp, 0,
+                       conn->src, conn->hcon->dst_type, conn->dst, res);
+       if (ret)
+               return SMP_UNSPECIFIED;
+
+       swap128(res, cp.confirm_val);
+
+       smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+
+       return 0;
+}
+
+static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
+
+       BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+       memcpy(conn->pcnf, skb->data, sizeof(conn->pcnf));
+       skb_pull(skb, sizeof(conn->pcnf));
+
+       if (conn->hcon->out) {
+               u8 random[16];
+
+               swap128(conn->prnd, random);
+               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random),
+                                                               random);
+       } else {
+               struct smp_cmd_pairing_confirm cp;
+               int ret;
+               u8 res[16];
+
+               ret = smp_rand(conn->prnd);
+               if (ret)
+                       return SMP_UNSPECIFIED;
+
+               ret = smp_c1(tfm, conn->tk, conn->prnd, conn->preq, conn->prsp,
+                                               conn->hcon->dst_type, conn->dst,
+                                               0, conn->src, res);
+               if (ret)
+                       return SMP_CONFIRM_FAILED;
+
+               swap128(res, cp.confirm_val);
+
+               smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp);
+       }
+
+       mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
+       return 0;
+}
+
+static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct hci_conn *hcon = conn->hcon;
+       struct crypto_blkcipher *tfm = hcon->hdev->tfm;
+       int ret;
+       u8 key[16], res[16], random[16], confirm[16];
+
+       swap128(skb->data, random);
+       skb_pull(skb, sizeof(random));
+
+       memset(hcon->ltk, 0, sizeof(hcon->ltk));
+
+       if (conn->hcon->out)
+               ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp, 0,
+                               conn->src, conn->hcon->dst_type, conn->dst,
+                               res);
+       else
+               ret = smp_c1(tfm, conn->tk, random, conn->preq, conn->prsp,
+                               conn->hcon->dst_type, conn->dst, 0, conn->src,
+                               res);
+       if (ret)
+               return SMP_UNSPECIFIED;
+
+       BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
+
+       swap128(res, confirm);
+
+       if (memcmp(conn->pcnf, confirm, sizeof(conn->pcnf)) != 0) {
+               BT_ERR("Pairing failed (confirmation values mismatch)");
+               return SMP_CONFIRM_FAILED;
+       }
+
+       if (conn->hcon->out) {
+               __le16 ediv;
+               u8 rand[8];
+
+               smp_s1(tfm, conn->tk, random, conn->prnd, key);
+               swap128(key, hcon->ltk);
+
+               memset(hcon->ltk + conn->smp_key_size, 0,
+                               SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+
+               memset(rand, 0, sizeof(rand));
+               ediv = 0;
+               hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
+       } else {
+               u8 r[16];
+
+               swap128(conn->prnd, r);
+               smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r);
+
+               smp_s1(tfm, conn->tk, conn->prnd, random, key);
+               swap128(key, hcon->ltk);
+
+               memset(hcon->ltk + conn->smp_key_size, 0,
+                               SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
+       }
+
+       return 0;
+}
+
+static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       struct smp_cmd_security_req *rp = (void *) skb->data;
+       struct smp_cmd_pairing cp;
+       struct hci_conn *hcon = conn->hcon;
+
+       BT_DBG("conn %p", conn);
+
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+               return 0;
+
+       skb_pull(skb, sizeof(*rp));
+
+       memset(&cp, 0, sizeof(cp));
+       build_pairing_cmd(conn, &cp, rp->auth_req);
+
+       conn->preq[0] = SMP_CMD_PAIRING_REQ;
+       memcpy(&conn->preq[1], &cp, sizeof(cp));
+
+       smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+
+       mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
+       set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
+       return 0;
+}
+
+int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+{
+       struct hci_conn *hcon = conn->hcon;
+       __u8 authreq;
+
+       BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level);
+
+       if (IS_ERR(hcon->hdev->tfm))
+               return 1;
+
+       if (test_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend))
+               return 0;
+
+       if (sec_level == BT_SECURITY_LOW)
+               return 1;
+
+       if (hcon->sec_level >= sec_level)
+               return 1;
+
+       authreq = seclevel_to_authreq(sec_level);
+
+       if (hcon->link_mode & HCI_LM_MASTER) {
+               struct smp_cmd_pairing cp;
+
+               build_pairing_cmd(conn, &cp, authreq);
+               conn->preq[0] = SMP_CMD_PAIRING_REQ;
+               memcpy(&conn->preq[1], &cp, sizeof(cp));
+
+               mod_timer(&conn->security_timer, jiffies +
+                                       msecs_to_jiffies(SMP_TIMEOUT));
+
+               smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
+       } else {
+               struct smp_cmd_security_req cp;
+               cp.auth_req = authreq;
+               smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp);
+       }
+
+       hcon->pending_sec_level = sec_level;
+       set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->pend);
+
+       return 0;
+}
+
+int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
+{
+       __u8 code = skb->data[0];
+       __u8 reason;
+       int err = 0;
+
+       if (IS_ERR(conn->hcon->hdev->tfm)) {
+               err = PTR_ERR(conn->hcon->hdev->tfm);
+               reason = SMP_PAIRING_NOTSUPP;
+               goto done;
+       }
+
+       skb_pull(skb, sizeof(code));
+
+       switch (code) {
+       case SMP_CMD_PAIRING_REQ:
+               reason = smp_cmd_pairing_req(conn, skb);
+               break;
+
+       case SMP_CMD_PAIRING_FAIL:
+               reason = 0;
+               err = -EPERM;
+               break;
+
+       case SMP_CMD_PAIRING_RSP:
+               reason = smp_cmd_pairing_rsp(conn, skb);
+               break;
+
+       case SMP_CMD_SECURITY_REQ:
+               reason = smp_cmd_security_req(conn, skb);
+               break;
+
+       case SMP_CMD_PAIRING_CONFIRM:
+               reason = smp_cmd_pairing_confirm(conn, skb);
+               break;
+
+       case SMP_CMD_PAIRING_RANDOM:
+               reason = smp_cmd_pairing_random(conn, skb);
+               break;
+
+       case SMP_CMD_ENCRYPT_INFO:
+       case SMP_CMD_MASTER_IDENT:
+       case SMP_CMD_IDENT_INFO:
+       case SMP_CMD_IDENT_ADDR_INFO:
+       case SMP_CMD_SIGN_INFO:
+       default:
+               BT_DBG("Unknown command code 0x%2.2x", code);
+
+               reason = SMP_CMD_NOTSUPP;
+               err = -EOPNOTSUPP;
+               goto done;
+       }
+
+done:
+       if (reason)
+               smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason),
+                                                               &reason);
+
+       kfree_skb(skb);
+       return err;
+}
index eebf7a6..0e7e426 100644 (file)
@@ -218,6 +218,16 @@ static inline int drv_hw_scan(struct ieee80211_local *local,
        return ret;
 }
 
+static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
+                                     struct ieee80211_sub_if_data *sdata)
+{
+       might_sleep();
+
+       trace_drv_cancel_hw_scan(local, sdata);
+       local->ops->cancel_hw_scan(&local->hw, &sdata->vif);
+       trace_drv_return_void(local);
+}
+
 static inline int
 drv_sched_scan_start(struct ieee80211_local *local,
                     struct ieee80211_sub_if_data *sdata,
index ed9edcb..3cb6795 100644 (file)
@@ -460,6 +460,12 @@ DEFINE_EVENT(local_sdata_evt, drv_hw_scan,
        TP_ARGS(local, sdata)
 );
 
+DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata),
+       TP_ARGS(local, sdata)
+);
+
 DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_sub_if_data *sdata),
index d595265..faca503 100644 (file)
@@ -2206,6 +2206,7 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
                add_timer(&ifmgd->chswitch_timer);
        ieee80211_sta_reset_beacon_monitor(sdata);
        ieee80211_restart_sta_timer(sdata);
+       ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.monitor_work);
 }
 #endif
 
@@ -2652,3 +2653,10 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
        cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
 }
 EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
+
+unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       return sdata->dev->operstate;
+}
+EXPORT_SYMBOL(ieee80211_get_operstate);
index 730778a..67839eb 100644 (file)
@@ -6,6 +6,28 @@
 #include "driver-ops.h"
 #include "led.h"
 
+/* return value indicates whether the driver should be further notified */
+static bool ieee80211_quiesce(struct ieee80211_sub_if_data *sdata)
+{
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_STATION:
+               ieee80211_sta_quiesce(sdata);
+               return true;
+       case NL80211_IFTYPE_ADHOC:
+               ieee80211_ibss_quiesce(sdata);
+               return true;
+       case NL80211_IFTYPE_MESH_POINT:
+               ieee80211_mesh_quiesce(sdata);
+               return true;
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_MONITOR:
+               /* don't tell driver about this */
+               return false;
+       default:
+               return true;
+       }
+}
+
 int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
 {
        struct ieee80211_local *local = hw_to_local(hw);
@@ -54,6 +76,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
                        local->quiescing = false;
                        return err;
                }
+               list_for_each_entry(sdata, &local->interfaces, list) {
+                       cancel_work_sync(&sdata->work);
+                       ieee80211_quiesce(sdata);
+               }
                goto suspend;
        }
 
@@ -82,23 +108,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
        list_for_each_entry(sdata, &local->interfaces, list) {
                cancel_work_sync(&sdata->work);
 
-               switch(sdata->vif.type) {
-               case NL80211_IFTYPE_STATION:
-                       ieee80211_sta_quiesce(sdata);
-                       break;
-               case NL80211_IFTYPE_ADHOC:
-                       ieee80211_ibss_quiesce(sdata);
-                       break;
-               case NL80211_IFTYPE_MESH_POINT:
-                       ieee80211_mesh_quiesce(sdata);
-                       break;
-               case NL80211_IFTYPE_AP_VLAN:
-               case NL80211_IFTYPE_MONITOR:
-                       /* don't tell driver about this */
+               if (!ieee80211_quiesce(sdata))
                        continue;
-               default:
-                       break;
-               }
 
                if (!ieee80211_sdata_running(sdata))
                        continue;
index 58ffa7d..1758b46 100644 (file)
@@ -821,10 +821,8 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
  */
 void ieee80211_scan_cancel(struct ieee80211_local *local)
 {
-       bool abortscan;
-
        /*
-        * We are only canceling software scan, or deferred scan that was not
+        * We are canceling software scan, or deferred scan that was not
         * yet really started (see __ieee80211_start_scan ).
         *
         * Regarding hardware scan:
@@ -836,23 +834,30 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
         * - we can not cancel scan_work since driver can schedule it
         *   by ieee80211_scan_completed(..., true) to finish scan
         *
-        * Hence low lever driver is responsible for canceling HW scan.
+        * Hence we only call the cancel_hw_scan() callback, but the low-level
+        * driver is still responsible for calling ieee80211_scan_completed()
+        * after the scan was completed/aborted.
         */
 
        mutex_lock(&local->mtx);
-       abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
-       if (abortscan) {
-               /*
-                * The scan is canceled, but stop work from being pending.
-                *
-                * If the work is currently running, it must be blocked on
-                * the mutex, but we'll set scan_sdata = NULL and it'll
-                * simply exit once it acquires the mutex.
-                */
-               cancel_delayed_work(&local->scan_work);
-               /* and clean up */
-               __ieee80211_scan_completed(&local->hw, true, false);
+       if (!local->scan_req)
+               goto out;
+
+       if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
+               if (local->ops->cancel_hw_scan)
+                       drv_cancel_hw_scan(local, local->scan_sdata);
+               goto out;
        }
+
+       /*
+        * If the work is currently running, it must be blocked on
+        * the mutex, but we'll set scan_sdata = NULL and it'll
+        * simply exit once it acquires the mutex.
+        */
+       cancel_delayed_work(&local->scan_work);
+       /* and clean up */
+       __ieee80211_scan_completed(&local->hw, true, false);
+out:
        mutex_unlock(&local->mtx);
 }
 
index d3fe2d2..05e3fb8 100644 (file)
@@ -1276,7 +1276,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                if (ieee80211_sdata_running(sdata))
                        ieee80211_enable_keys(sdata);
 
+#ifdef CONFIG_PM
  wake_up:
+#endif
        ieee80211_wake_queues_by_reason(hw,
                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
index ca5276c..0a4db02 100644 (file)
@@ -1696,6 +1696,8 @@ static int netlink_dump(struct sock *sk)
        if (!nlh)
                goto errout_skb;
 
+       nl_dump_check_consistent(cb, nlh);
+
        memcpy(nlmsg_data(nlh), &len, sizeof(len));
 
        if (sk_filter(sk, skb))
index 493b939..3633ab6 100644 (file)
@@ -170,7 +170,9 @@ void __cfg80211_send_deauth(struct net_device *dev,
                        break;
                }
                if (wdev->authtry_bsses[i] &&
-                   memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
+                   memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
+                          ETH_ALEN) == 0 &&
+                   memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) == 0) {
                        cfg80211_unhold_bss(wdev->authtry_bsses[i]);
                        cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
                        wdev->authtry_bsses[i] = NULL;
index 10823e2..aed6d2a 100644 (file)
@@ -3620,7 +3620,8 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
        return __cfg80211_stop_sched_scan(rdev, false);
 }
 
-static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
+static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
+                           u32 seq, int flags,
                            struct cfg80211_registered_device *rdev,
                            struct wireless_dev *wdev,
                            struct cfg80211_internal_bss *intbss)
@@ -3632,11 +3633,13 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 
        ASSERT_WDEV_LOCK(wdev);
 
-       hdr = nl80211hdr_put(msg, pid, seq, flags,
+       hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).pid, seq, flags,
                             NL80211_CMD_NEW_SCAN_RESULTS);
        if (!hdr)
                return -1;
 
+       genl_dump_check_consistent(cb, hdr, &nl80211_fam);
+
        NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
        NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
 
@@ -3725,11 +3728,12 @@ static int nl80211_dump_scan(struct sk_buff *skb,
        spin_lock_bh(&rdev->bss_lock);
        cfg80211_bss_expire(rdev);
 
+       cb->seq = rdev->bss_generation;
+
        list_for_each_entry(scan, &rdev->bss_list, list) {
                if (++idx <= start)
                        continue;
-               if (nl80211_send_bss(skb,
-                               NETLINK_CB(cb->skb).pid,
+               if (nl80211_send_bss(skb, cb,
                                cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                rdev, wdev, scan) < 0) {
                        idx--;